Skip to content

Commit

Permalink
Refactor: Added name and tag to Image class
Browse files Browse the repository at this point in the history
The OCI image specification has no guidance on image distribution
as of this patch, but they are considering it. How 'image' and 'tag'
are extracted from different images can be set by the derived class.

- Moved Docker specific properties to DockerImage class
This includes repotag and history
- Moved check for instantiation method from Image class to DockerImage
class
- Added name and tag to the Image class
- Added name and tag setting to the DockerImage class if instantiated
using a repotag
- Added check for name and tag in the tests

The tests work but the main tern executable does not

Signed-off-by: Nisha K <[email protected]>
  • Loading branch information
Nisha K committed Mar 5, 2018
1 parent 664f147 commit 5752650
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 39 deletions.
49 changes: 43 additions & 6 deletions classes/docker_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,54 @@
from utils.constants import manifest_file
from utils.container import extract_image_metadata
from utils.dockerfile import directives
from utils.dockerfile import tag_separator

from .image_layer import ImageLayer
from .image import Image


class DockerImage(Image):
'''A representation of an image created by Docker
See image.py for super class's attributes'''
See image.py for super class's attributes
Docker Image specific attributes:
repotags: the list of repotags associated with this image
history: a list of commands used to create the filesystem layers
'''
def __init__(self, repotag=None, id=None):
'''Use superclass's attributes'''
super().__init__(repotag, id)
'''Initialize using repotag and id'''
super().__init__(id)
self.__repotag = repotag
self.__repotags = []
self.__history = None
if self.repotag is not None:
repo_tag_list = self.__repotag.split(tag_separator)
self._name = repo_tag_list[0]
self._tag = repo_tag_list[1]

@property
def repotag(self):
return self.__repotag

@property
def repotags(self):
return self.__repotags

@property
def history(self):
return self.__history

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.id is not None:
return self.id
elif self.repotag is not None:
return self.repotag
elif self.id is not None:
return self.id
else:
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
Expand Down Expand Up @@ -92,7 +129,7 @@ def set_layer_created_by(self):
# the history is ordered according to the order of the layers
# so the first non-empty history corresponds with the first layer
index = 0
for item in self._history:
for item in self.__history:
if 'empty_layer' not in item.keys():
if 'created_by' in item.keys():
self._layers[index].created_by = item['created_by']
Expand All @@ -110,9 +147,9 @@ def load_image(self):
print('Failed to extract image')
self._manifest = self.get_image_manifest()
self._id = self.get_image_id(self._manifest)
self._repotags = self.get_image_repotags(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)
self.__history = self.get_image_history(self._config)
layer_paths = self.get_image_layers(self._manifest)
layer_diffs = self.get_diff_ids(self._config)
while layer_diffs and layer_paths:
Expand Down
44 changes: 11 additions & 33 deletions classes/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,26 @@
class Image(object):
'''A representation of the image to be analyzed
attributes:
repotag: the repotag used to reference the image
id: this is a unique identifier for the image - for OCI spec this could
be the digest. For now this is the sha256sum of the config.json in a
Docker compatible manifest
be the digest. For now this is the sha256sum of the config.json
manifest: the json object representing the image manifest
repotags: the list of repotags associated with this image
config: the image config metadata
layers: list of layer objects in the image
history: a list of commands used to create the filesystem layers
methods:
load_image: this method is to be implemented in the derived classes
get_layer_diff_ids: returns a list of layer diff ids only
get_image_option: returns whether the image object was instantiated
using the repotag or id
'''
def __init__(self, repotag=None, id=None):
'''Either initialize using the repotag or the id'''
self._repotag = repotag
def __init__(self, id=None):
'''Either initialize using id'''
self._id = id
self._name = ''
self._tag = ''
self._manifest = {}
self._repotags = []
self._config = {}
self._layers = []
self._notices = []
self._history = None

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

@property
def manifest(self):
Expand All @@ -45,10 +36,6 @@ def manifest(self):
def id(self):
return self._id

@property
def repotags(self):
return self._repotags

@property
def config(self):
return self._config
Expand All @@ -62,8 +49,12 @@ def notices(self):
return self._notices

@property
def history(self):
return self._history
def name(self):
return self._name

@property
def tag(self):
return self._tag

def add_notice(self, notice):
self._notices.append(notice)
Expand All @@ -72,19 +63,6 @@ def get_layer_diff_ids(self):
'''Get a list of layer diff ids'''
return [layer.diff_id for layer in self.layers]

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.id is not None:
return self.id
elif self.repotag is not None:
return self.repotag
elif self.id is not None:
return self.id
else:
raise NameError("Image object initialized with no repotag or ID")

def load_image(self):
'''Load image metadata
Currently there is no standard way to do this. For a specific tool,
Expand Down
2 changes: 2 additions & 0 deletions tests/test_class_docker_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ def tearDown(self):

def testInstance(self):
self.assertEqual(self.image.repotag, 'debian:jessie')
self.assertEqual(self.image.name, 'debian')
self.assertEqual(self.image.tag, 'jessie')
self.assertFalse(self.image.id)
self.assertFalse(self.image.manifest)
self.assertFalse(self.image.repotags)
Expand Down

0 comments on commit 5752650

Please sign in to comment.