Merge branch 'huggies'

This commit is contained in:
Joseph Schorr 2014-09-22 13:41:29 -04:00
commit dc685b2387
7 changed files with 60 additions and 40 deletions

View file

@ -9,22 +9,33 @@ from data import model
from util.cache import cache_control_flask_restful from util.cache import cache_control_flask_restful
def image_view(image): def image_view(image, image_map):
extended_props = image extended_props = image
if image.storage and image.storage.id: if image.storage and image.storage.id:
extended_props = image.storage extended_props = image.storage
command = extended_props.command 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 { return {
'id': image.docker_image_id, 'id': image.docker_image_id,
'created': format_date(extended_props.created), 'created': format_date(extended_props.created),
'comment': extended_props.comment, 'comment': extended_props.comment,
'command': json.loads(command) if command else None, 'command': json.loads(command) if command else None,
'ancestors': image.ancestors,
'dbid': image.id,
'size': extended_props.image_size, 'size': extended_props.image_size,
'locations': list(image.storage.locations), 'locations': list(image.storage.locations),
'uploading': image.storage.uploading, 'uploading': image.storage.uploading,
'ancestors': ancestors_string,
'sort_index': len(image.ancestors)
} }
@ -42,14 +53,16 @@ class RepositoryImageList(RepositoryParamResource):
for tag in all_tags: for tag in all_tags:
tags_by_image_id[tag.image.docker_image_id].append(tag.name) 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): def add_tags(image_json):
image_json['tags'] = tags_by_image_id[image_json['id']] image_json['tags'] = tags_by_image_id[image_json['id']]
return image_json return image_json
return { 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: if not image:
raise NotFound() 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/<repopath:repository>/image/<image_id>/changes') @resource('/v1/repository/<repopath:repository>/image/<image_id>/changes')

View file

@ -168,8 +168,7 @@ class Repository(RepositoryParamResource):
def tag_view(tag): def tag_view(tag):
return { return {
'name': tag.name, 'name': tag.name,
'image_id': tag.image.docker_image_id, 'image_id': tag.image.docker_image_id
'dbid': tag.image.id
} }
organization = None organization = None

View file

@ -85,11 +85,14 @@ class RepositoryTagImages(RepositoryParamResource):
raise NotFound() raise NotFound()
parent_images = model.get_parent_images(namespace, repository, tag_image) 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 = list(parent_images)
parents.reverse() parents.reverse()
all_images = [tag_image] + parents all_images = [tag_image] + parents
return { return {
'images': [image_view(image) for image in all_images] 'images': [image_view(image, image_map) for image in all_images]
} }

View file

@ -6058,7 +6058,7 @@ quayApp.directive('tagSpecificImagesView', function () {
} }
var currentTag = $scope.repository.tags[$scope.tag]; var currentTag = $scope.repository.tags[$scope.tag];
if (image.dbid == currentTag.dbid) { if (image.id == currentTag.image_id) {
classes += 'tag-image '; classes += 'tag-image ';
} }
@ -6068,15 +6068,15 @@ quayApp.directive('tagSpecificImagesView', function () {
var forAllTagImages = function(tag, callback, opt_cutoff) { var forAllTagImages = function(tag, callback, opt_cutoff) {
if (!tag) { return; } if (!tag) { return; }
if (!$scope.imageByDBID) { if (!$scope.imageByDockerId) {
$scope.imageByDBID = []; $scope.imageByDockerId = [];
for (var i = 0; i < $scope.images.length; ++i) { for (var i = 0; i < $scope.images.length; ++i) {
var currentImage = $scope.images[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) { if (!tag_image) {
return; return;
} }
@ -6085,7 +6085,7 @@ quayApp.directive('tagSpecificImagesView', function () {
var ancestors = tag_image.ancestors.split('/').reverse(); var ancestors = tag_image.ancestors.split('/').reverse();
for (var i = 0; i < ancestors.length; ++i) { for (var i = 0; i < ancestors.length; ++i) {
var image = $scope.imageByDBID[ancestors[i]]; var image = $scope.imageByDockerId[ancestors[i]];
if (image) { if (image) {
if (image == opt_cutoff) { if (image == opt_cutoff) {
return; return;
@ -6111,7 +6111,7 @@ quayApp.directive('tagSpecificImagesView', function () {
var getIdsForTag = function(currentTag) { var getIdsForTag = function(currentTag) {
var ids = {}; var ids = {};
forAllTagImages(currentTag, function(image) { forAllTagImages(currentTag, function(image) {
ids[image.dbid] = true; ids[image.id] = true;
}, $scope.imageCutoff); }, $scope.imageCutoff);
return ids; return ids;
}; };
@ -6121,8 +6121,8 @@ quayApp.directive('tagSpecificImagesView', function () {
for (var currentTagName in $scope.repository.tags) { for (var currentTagName in $scope.repository.tags) {
var currentTag = $scope.repository.tags[currentTagName]; var currentTag = $scope.repository.tags[currentTagName];
if (currentTag != tag) { if (currentTag != tag) {
for (var dbid in getIdsForTag(currentTag)) { for (var id in getIdsForTag(currentTag)) {
delete toDelete[dbid]; delete toDelete[id];
} }
} }
} }
@ -6131,7 +6131,7 @@ quayApp.directive('tagSpecificImagesView', function () {
var images = []; var images = [];
for (var i = 0; i < $scope.images.length; ++i) { for (var i = 0; i < $scope.images.length; ++i) {
var image = $scope.images[i]; var image = $scope.images[i];
if (toDelete[image.dbid]) { if (toDelete[image.id]) {
images.push(image); images.push(image);
} }
} }
@ -6142,7 +6142,7 @@ quayApp.directive('tagSpecificImagesView', function () {
return result; return result;
} }
return b.dbid - a.dbid; return b.sort_index - a.sort_index;
}); });
$scope.tagSpecificImages = images; $scope.tagSpecificImages = images;

View file

@ -497,7 +497,7 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
}; };
$scope.findImageForTag = function(tag) { $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) { $scope.createOrMoveTag = function(image, tagName, opt_invalid) {
@ -685,9 +685,9 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
}; };
var forAllTagImages = function(tag, callback) { 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; } if (!tag_image) { return; }
// Callback the tag's image itself. // Callback the tag's image itself.
@ -697,7 +697,7 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
if (!tag_image.ancestors) { return; } if (!tag_image.ancestors) { return; }
var ancestors = tag_image.ancestors.split('/'); var ancestors = tag_image.ancestors.split('/');
for (var i = 0; i < ancestors.length; ++i) { for (var i = 0; i < ancestors.length; ++i) {
var image = $scope.imageByDBID[ancestors[i]]; var image = $scope.imageByDockerId[ancestors[i]];
if (image) { if (image) {
callback(image); callback(image);
} }
@ -786,10 +786,10 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
$scope.specificImages = []; $scope.specificImages = [];
// Build various images for quick lookup of images. // Build various images for quick lookup of images.
$scope.imageByDBID = {}; $scope.imageByDockerId = {};
for (var i = 0; i < $scope.images.length; ++i) { for (var i = 0; i < $scope.images.length; ++i) {
var currentImage = $scope.images[i]; var currentImage = $scope.images[i];
$scope.imageByDBID[currentImage.dbid] = currentImage; $scope.imageByDockerId[currentImage.id] = currentImage;
} }
// Dispose of any existing tree. // Dispose of any existing tree.

View file

@ -307,8 +307,8 @@ ImageHistoryTree.prototype.setHighlightedPath_ = function(image) {
this.markPath_(this.currentNode_, false); this.markPath_(this.currentNode_, false);
} }
var imageByDBID = this.imageByDBID_; var imageByDockerId = this.imageByDockerId_;
var currentNode = imageByDBID[image.dbid]; var currentNode = imageByDockerId[image.id];
if (currentNode) { if (currentNode) {
this.markPath_(currentNode, true); this.markPath_(currentNode, true);
this.currentNode_ = currentNode; this.currentNode_ = currentNode;
@ -386,7 +386,7 @@ ImageHistoryTree.prototype.buildRoot_ = function() {
var formatted = {"name": "No images found"}; var formatted = {"name": "No images found"};
// Build a node for each image. // Build a node for each image.
var imageByDBID = {}; var imageByDockerId = {};
for (var i = 0; i < this.images_.length; ++i) { for (var i = 0; i < this.images_.length; ++i) {
var image = this.images_[i]; var image = this.images_[i];
var imageNode = { var imageNode = {
@ -395,9 +395,9 @@ ImageHistoryTree.prototype.buildRoot_ = function() {
"image": image, "image": image,
"tags": image.tags "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, // For each node, attach it to its immediate parent. If there is no immediate parent,
// then the node is the root. // then the node is the root.
@ -408,10 +408,10 @@ ImageHistoryTree.prototype.buildRoot_ = function() {
// Skip images that are currently uploading. // Skip images that are currently uploading.
if (image.uploading) { continue; } if (image.uploading) { continue; }
var imageNode = imageByDBID[image.dbid]; var imageNode = imageByDockerId[image.id];
var ancestors = this.getAncestors_(image); var ancestors = this.getAncestors_(image);
var immediateParent = ancestors[ancestors.length - 1] * 1; var immediateParent = ancestors[ancestors.length - 1];
var parent = imageByDBID[immediateParent]; var parent = imageByDockerId[immediateParent];
if (parent) { if (parent) {
// Add a reference to the parent. This makes walking the tree later easier. // Add a reference to the parent. This makes walking the tree later easier.
imageNode.parent = parent; imageNode.parent = parent;
@ -442,7 +442,7 @@ ImageHistoryTree.prototype.buildRoot_ = function() {
// Skip images that are currently uploading. // Skip images that are currently uploading.
if (image.uploading) { continue; } if (image.uploading) { continue; }
var imageNode = imageByDBID[image.dbid]; var imageNode = imageByDockerId[image.id];
maxChildCount = Math.max(maxChildCount, this.determineMaximumChildCount_(imageNode)); maxChildCount = Math.max(maxChildCount, this.determineMaximumChildCount_(imageNode));
} }
@ -573,7 +573,7 @@ ImageHistoryTree.prototype.setTag_ = function(tagName) {
return; return;
} }
var imageByDBID = this.imageByDBID_; var imageByDockerId = this.imageByDockerId_;
// Save the current tag. // Save the current tag.
var previousTagName = this.currentTag_; var previousTagName = this.currentTag_;
@ -596,10 +596,10 @@ ImageHistoryTree.prototype.setTag_ = function(tagName) {
// Skip images that are currently uploading. // Skip images that are currently uploading.
if (image.uploading) { continue; } if (image.uploading) { continue; }
var imageNode = this.imageByDBID_[image.dbid]; var imageNode = this.imageByDockerId_[image.id];
var ancestors = this.getAncestors_(image); var ancestors = this.getAncestors_(image);
var immediateParent = ancestors[ancestors.length - 1] * 1; var immediateParent = ancestors[ancestors.length - 1];
var parent = imageByDBID[immediateParent]; var parent = imageByDockerId[immediateParent];
if (parent && imageNode.highlighted) { if (parent && imageNode.highlighted) {
var arr = parent.children; var arr = parent.children;
if (parent._children) { if (parent._children) {

View file

@ -1429,6 +1429,7 @@ class TestListAndGetImage(ApiTestCase):
params=dict(repository=ADMIN_ACCESS_USER + '/simple')) params=dict(repository=ADMIN_ACCESS_USER + '/simple'))
assert len(json['images']) > 0 assert len(json['images']) > 0
for image in json['images']: for image in json['images']:
assert 'id' in image assert 'id' in image
assert 'tags' in image assert 'tags' in image
@ -1436,7 +1437,6 @@ class TestListAndGetImage(ApiTestCase):
assert 'comment' in image assert 'comment' in image
assert 'command' in image assert 'command' in image
assert 'ancestors' in image assert 'ancestors' in image
assert 'dbid' in image
assert 'size' in image assert 'size' in image
ijson = self.getJsonResponse(RepositoryImage, ijson = self.getJsonResponse(RepositoryImage,