diff --git a/endpoints/api/image.py b/endpoints/api/image.py index 3060053ad..3a6c62507 100644 --- a/endpoints/api/image.py +++ b/endpoints/api/image.py @@ -9,22 +9,33 @@ from data import model from util.cache import cache_control_flask_restful -def image_view(image): +def image_view(image, image_map): extended_props = image if image.storage and image.storage.id: extended_props = image.storage command = extended_props.command + + def docker_id(aid): + if not aid: + return '' + + return image_map[aid] + + # Calculate the ancestors string, with the DBID's replaced with the docker IDs. + ancestors = [docker_id(a) for a in image.ancestors.split('/')] + ancestors_string = '/'.join(ancestors) + return { 'id': image.docker_image_id, 'created': format_date(extended_props.created), 'comment': extended_props.comment, 'command': json.loads(command) if command else None, - 'ancestors': image.ancestors, - 'dbid': image.id, 'size': extended_props.image_size, 'locations': list(image.storage.locations), 'uploading': image.storage.uploading, + 'ancestors': ancestors_string, + 'sort_index': len(image.ancestors) } @@ -42,14 +53,16 @@ class RepositoryImageList(RepositoryParamResource): for tag in all_tags: tags_by_image_id[tag.image.docker_image_id].append(tag.name) + image_map = {} + for image in all_images: + image_map[str(image.id)] = image.docker_image_id def add_tags(image_json): image_json['tags'] = tags_by_image_id[image_json['id']] return image_json - return { - 'images': [add_tags(image_view(image)) for image in all_images] + 'images': [add_tags(image_view(image, image_map)) for image in all_images] } @@ -64,7 +77,12 @@ class RepositoryImage(RepositoryParamResource): if not image: raise NotFound() - return image_view(image) + # Lookup all the ancestor images for the image. + image_map = {} + for current_image in model.get_parent_images(namespace, repository, image): + image_map[str(current_image.id)] = image.docker_image_id + + return image_view(image, image_map) @resource('/v1/repository//image//changes') diff --git a/endpoints/api/repository.py b/endpoints/api/repository.py index 17a35fea1..4e85a35b5 100644 --- a/endpoints/api/repository.py +++ b/endpoints/api/repository.py @@ -168,8 +168,7 @@ class Repository(RepositoryParamResource): def tag_view(tag): return { 'name': tag.name, - 'image_id': tag.image.docker_image_id, - 'dbid': tag.image.id + 'image_id': tag.image.docker_image_id } organization = None diff --git a/endpoints/api/tag.py b/endpoints/api/tag.py index f9210881c..779b821ae 100644 --- a/endpoints/api/tag.py +++ b/endpoints/api/tag.py @@ -85,11 +85,14 @@ class RepositoryTagImages(RepositoryParamResource): raise NotFound() parent_images = model.get_parent_images(namespace, repository, tag_image) + image_map = {} + for image in parent_images: + image_map[str(image.id)] = image.docker_image_id parents = list(parent_images) parents.reverse() all_images = [tag_image] + parents return { - 'images': [image_view(image) for image in all_images] + 'images': [image_view(image, image_map) for image in all_images] } diff --git a/static/js/app.js b/static/js/app.js index 5457b46d2..ff689745e 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -6058,7 +6058,7 @@ quayApp.directive('tagSpecificImagesView', function () { } var currentTag = $scope.repository.tags[$scope.tag]; - if (image.dbid == currentTag.dbid) { + if (image.id == currentTag.image_id) { classes += 'tag-image '; } @@ -6068,15 +6068,15 @@ quayApp.directive('tagSpecificImagesView', function () { var forAllTagImages = function(tag, callback, opt_cutoff) { if (!tag) { return; } - if (!$scope.imageByDBID) { - $scope.imageByDBID = []; + if (!$scope.imageByDockerId) { + $scope.imageByDockerId = []; for (var i = 0; i < $scope.images.length; ++i) { var currentImage = $scope.images[i]; - $scope.imageByDBID[currentImage.dbid] = currentImage; + $scope.imageByDockerId[currentImage.id] = currentImage; } } - var tag_image = $scope.imageByDBID[tag.dbid]; + var tag_image = $scope.imageByDockerId[tag.image_id]; if (!tag_image) { return; } @@ -6085,7 +6085,7 @@ quayApp.directive('tagSpecificImagesView', function () { var ancestors = tag_image.ancestors.split('/').reverse(); for (var i = 0; i < ancestors.length; ++i) { - var image = $scope.imageByDBID[ancestors[i]]; + var image = $scope.imageByDockerId[ancestors[i]]; if (image) { if (image == opt_cutoff) { return; @@ -6111,7 +6111,7 @@ quayApp.directive('tagSpecificImagesView', function () { var getIdsForTag = function(currentTag) { var ids = {}; forAllTagImages(currentTag, function(image) { - ids[image.dbid] = true; + ids[image.id] = true; }, $scope.imageCutoff); return ids; }; @@ -6121,8 +6121,8 @@ quayApp.directive('tagSpecificImagesView', function () { for (var currentTagName in $scope.repository.tags) { var currentTag = $scope.repository.tags[currentTagName]; if (currentTag != tag) { - for (var dbid in getIdsForTag(currentTag)) { - delete toDelete[dbid]; + for (var id in getIdsForTag(currentTag)) { + delete toDelete[id]; } } } @@ -6131,7 +6131,7 @@ quayApp.directive('tagSpecificImagesView', function () { var images = []; for (var i = 0; i < $scope.images.length; ++i) { var image = $scope.images[i]; - if (toDelete[image.dbid]) { + if (toDelete[image.id]) { images.push(image); } } @@ -6142,7 +6142,7 @@ quayApp.directive('tagSpecificImagesView', function () { return result; } - return b.dbid - a.dbid; + return b.sort_index - a.sort_index; }); $scope.tagSpecificImages = images; diff --git a/static/js/controllers.js b/static/js/controllers.js index a4849e342..6dacc86ca 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -497,7 +497,7 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi }; $scope.findImageForTag = function(tag) { - return tag && $scope.imageByDBID && $scope.imageByDBID[tag.dbid]; + return tag && $scope.imageByDockerId && $scope.imageByDockerId[tag.image_id]; }; $scope.createOrMoveTag = function(image, tagName, opt_invalid) { @@ -685,9 +685,9 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi }; var forAllTagImages = function(tag, callback) { - if (!tag || !$scope.imageByDBID) { return; } + if (!tag || !$scope.imageByDockerId) { return; } - var tag_image = $scope.imageByDBID[tag.dbid]; + var tag_image = $scope.imageByDockerId[tag.image_id]; if (!tag_image) { return; } // Callback the tag's image itself. @@ -697,7 +697,7 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi if (!tag_image.ancestors) { return; } var ancestors = tag_image.ancestors.split('/'); for (var i = 0; i < ancestors.length; ++i) { - var image = $scope.imageByDBID[ancestors[i]]; + var image = $scope.imageByDockerId[ancestors[i]]; if (image) { callback(image); } @@ -786,10 +786,10 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi $scope.specificImages = []; // Build various images for quick lookup of images. - $scope.imageByDBID = {}; + $scope.imageByDockerId = {}; for (var i = 0; i < $scope.images.length; ++i) { var currentImage = $scope.images[i]; - $scope.imageByDBID[currentImage.dbid] = currentImage; + $scope.imageByDockerId[currentImage.id] = currentImage; } // Dispose of any existing tree. diff --git a/static/js/graphing.js b/static/js/graphing.js index b18e5ddbe..795904747 100644 --- a/static/js/graphing.js +++ b/static/js/graphing.js @@ -307,8 +307,8 @@ ImageHistoryTree.prototype.setHighlightedPath_ = function(image) { this.markPath_(this.currentNode_, false); } - var imageByDBID = this.imageByDBID_; - var currentNode = imageByDBID[image.dbid]; + var imageByDockerId = this.imageByDockerId_; + var currentNode = imageByDockerId[image.id]; if (currentNode) { this.markPath_(currentNode, true); this.currentNode_ = currentNode; @@ -386,7 +386,7 @@ ImageHistoryTree.prototype.buildRoot_ = function() { var formatted = {"name": "No images found"}; // Build a node for each image. - var imageByDBID = {}; + var imageByDockerId = {}; for (var i = 0; i < this.images_.length; ++i) { var image = this.images_[i]; var imageNode = { @@ -395,9 +395,9 @@ ImageHistoryTree.prototype.buildRoot_ = function() { "image": image, "tags": image.tags }; - imageByDBID[image.dbid] = imageNode; + imageByDockerId[image.id] = imageNode; } - this.imageByDBID_ = imageByDBID; + this.imageByDockerId_ = imageByDockerId; // For each node, attach it to its immediate parent. If there is no immediate parent, // then the node is the root. @@ -408,10 +408,10 @@ ImageHistoryTree.prototype.buildRoot_ = function() { // Skip images that are currently uploading. if (image.uploading) { continue; } - var imageNode = imageByDBID[image.dbid]; + var imageNode = imageByDockerId[image.id]; var ancestors = this.getAncestors_(image); - var immediateParent = ancestors[ancestors.length - 1] * 1; - var parent = imageByDBID[immediateParent]; + var immediateParent = ancestors[ancestors.length - 1]; + var parent = imageByDockerId[immediateParent]; if (parent) { // Add a reference to the parent. This makes walking the tree later easier. imageNode.parent = parent; @@ -442,7 +442,7 @@ ImageHistoryTree.prototype.buildRoot_ = function() { // Skip images that are currently uploading. if (image.uploading) { continue; } - var imageNode = imageByDBID[image.dbid]; + var imageNode = imageByDockerId[image.id]; maxChildCount = Math.max(maxChildCount, this.determineMaximumChildCount_(imageNode)); } @@ -573,7 +573,7 @@ ImageHistoryTree.prototype.setTag_ = function(tagName) { return; } - var imageByDBID = this.imageByDBID_; + var imageByDockerId = this.imageByDockerId_; // Save the current tag. var previousTagName = this.currentTag_; @@ -596,10 +596,10 @@ ImageHistoryTree.prototype.setTag_ = function(tagName) { // Skip images that are currently uploading. if (image.uploading) { continue; } - var imageNode = this.imageByDBID_[image.dbid]; + var imageNode = this.imageByDockerId_[image.id]; var ancestors = this.getAncestors_(image); - var immediateParent = ancestors[ancestors.length - 1] * 1; - var parent = imageByDBID[immediateParent]; + var immediateParent = ancestors[ancestors.length - 1]; + var parent = imageByDockerId[immediateParent]; if (parent && imageNode.highlighted) { var arr = parent.children; if (parent._children) { diff --git a/test/test_api_usage.py b/test/test_api_usage.py index cbbb5baf4..a38b761c8 100644 --- a/test/test_api_usage.py +++ b/test/test_api_usage.py @@ -1429,6 +1429,7 @@ class TestListAndGetImage(ApiTestCase): params=dict(repository=ADMIN_ACCESS_USER + '/simple')) assert len(json['images']) > 0 + for image in json['images']: assert 'id' in image assert 'tags' in image @@ -1436,7 +1437,6 @@ class TestListAndGetImage(ApiTestCase): assert 'comment' in image assert 'command' in image assert 'ancestors' in image - assert 'dbid' in image assert 'size' in image ijson = self.getJsonResponse(RepositoryImage,