From 0d2ec20a42d6a2e57f338c603946389ce2021c0b Mon Sep 17 00:00:00 2001 From: Eugene Kazakov Date: Mon, 1 May 2017 20:02:08 +0700 Subject: [PATCH] Display image details from Manifest v2 schema 2 --- app/image/image-controller.js | 38 ++------ app/image/image-details-directive.html | 68 ++++++-------- app/services/registry-services.js | 119 ++++++++++++------------- app/tag/tag-list-directive.html | 24 +---- 4 files changed, 96 insertions(+), 153 deletions(-) diff --git a/app/image/image-controller.js b/app/image/image-controller.js index 65da230..62992c0 100644 --- a/app/image/image-controller.js +++ b/app/image/image-controller.js @@ -8,39 +8,15 @@ * Controller of the docker-registry-frontend */ angular.module('image-controller', ['registry-services', 'app-mode-services']) - .controller('ImageController', ['$scope', '$route', '$routeParams', '$location', '$log', '$filter', 'Manifest', 'AppMode', - function($scope, $route, $routeParams, $location, $log, $filter, Manifest, AppMode){ - + .controller('ImageController', ['$scope', '$route', '$routeParams', '$location', '$log', '$filter', 'Manifest', 'Blob', 'AppMode', + function($scope, $route, $routeParams, $location, $log, $filter, Manifest, Blob, AppMode){ $scope.appMode = AppMode.query(); - $scope.totalImageSize = 0; - $scope.imageDetails = Manifest.query({repoUser: $scope.repositoryUser, repoName: $scope.repositoryName, tagName: $scope.tagName}); - + $scope.details = Manifest.query({repoUser: $scope.repositoryUser, repoName: $scope.repositoryName, tagName: $scope.tagName}); + $scope.config = {}; + $scope.details.$promise.then(function(data) { + $scope.config = Blob.query({repoUser: $scope.repositoryUser, repoName: $scope.repositoryName, digest: data.config.digest}); + }); - - // This is not totally working right now (problem with big layers) - /** - * Calculates the total download size for the image based on - * it's layers. - */ - /* - $scope.totalImageSize = null; - $scope.calculateTotalImageSize = function() { - $scope.totalImageSize = 0; - var size; - angular.forEach($scope.imageDetails.fsLayers, function (id, key) { - - Blob.query({repoUser: $scope.repositoryUser, repoName: $scope.repositoryName, digest: id.blobSum}).$promise.then( function(data, headers){ - size = data; - console.log(data) - console.log(size) - if(!isNaN(data.contentLength-0)){ - $scope.totalImageSize += data.contentLength; - } - }); - }); - }; - */ - }]); diff --git a/app/image/image-details-directive.html b/app/image/image-details-directive.html index f66e1b2..d34703f 100644 --- a/app/image/image-details-directive.html +++ b/app/image/image-details-directive.html @@ -1,7 +1,7 @@

Image Details
- + Create a tag for this image @@ -14,74 +14,48 @@

General information
-
- -
-

{{imageDetails.author}}

-
-
-
- -
-

-

{{imageDetails.comment}}
-

-
-
-
+

- - ({{imageDetails.created | date:'yyyy-MM-dd HH:mm:ss Z'}}) + + ({{config.created | date:'yyyy-MM-dd HH:mm:ss Z'}})

-
+
-

{{imageDetails.docker_version}}

+

{{config.docker_version}}

-
+
-

{{imageDetails.os}}/{{imageDetails.architecture}}

+

{{config.os}}/{{config.architecture}}

- +

- {{imageDetails.id | limitTo: 12}} + {{details.imageId | limitTo: 12}}

- - - +
- + Labels @@ -93,12 +67,22 @@

- + {{key}} {{value}} + + + Dockerfile + +
+      
+{{instruction}}
+      
+    
+
diff --git a/app/services/registry-services.js b/app/services/registry-services.js index ed4f843..5d369b6 100644 --- a/app/services/registry-services.js +++ b/app/services/registry-services.js @@ -146,82 +146,81 @@ angular.module('registry-services', ['ngResource']) return $resource('/v2/:repoUser/:repoName/manifests/:tagName', {}, { // Response example: // { - // "schemaVersion": 1, - // "name": "arthur/busybox", - // "tag": "demo", - // "architecture": "amd64", - // "fsLayers": [ + // "schemaVersion": 2, + // "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + // "config": { + // "mediaType": "application/vnd.docker.container.image.v1+json", + // "size": 7963, + // "digest": "sha256:1f1e1ccbb0918e4b08f877035831d178a6c34aeec58cfe2dc6014557b2e8ec13" + // }, + // "layers": [ // { - // "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" + // "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + // "size": 52550276, + // "digest": "sha256:cd0a524342efac6edff500c17e625735bbe479c926439b263bbe3c8518a0849c" // }, // { - // "blobSum": "sha256:d7e8ec85c5abc60edf74bd4b8d68049350127e4102a084f22060f7321eac3586" + // "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + // "size": 78849205, + // "digest": "sha256:14b8a88a0af049efa3c92b1c96a947f501ec7c751a568b0d3881b3c757a184a3" // } - // ], - // "history": [ - // { - // "v1Compatibility": "{\"id\":\"3e1018ee907f25aef8c50016296ab33624796511fdbfdbbdeca6a3ed2d0ba4e2\",\"parent\":\"176dfc9032a1ec3ac8586b383e325e1a65d1f5b5e6f46c2a55052b5aea8310f7\",\"created\":\"2016-01-12T17:47:39.251310827Z\",\"container\":\"2732d16efa11ab7da6393645e85a7f2070af94941a782a69e86457a2284f4a69\",\"container_config\":{\"Hostname\":\"ea7fe68f39fd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) LABEL awesome=Not yet!\"],\"Image\":\"176dfc9032a1ec3ac8586b383e325e1a65d1f5b5e6f46c2a55052b5aea8310f7\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":[],\"Labels\":{\"awesome\":\"Not yet!\",\"test\":\"yes\",\"working\":\"true\"}},\"docker_version\":\"1.9.1\",\"author\":\"Arthur\",\"config\":{\"Hostname\":\"ea7fe68f39fd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"sh\"],\"Image\":\"176dfc9032a1ec3ac8586b383e325e1a65d1f5b5e6f46c2a55052b5aea8310f7\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":[],\"Labels\":{\"awesome\":\"Not yet!\",\"test\":\"yes\",\"working\":\"true\"}},\"architecture\":\"amd64\",\"os\":\"linux\"}" - // }, - // { - // "v1Compatibility": "{\"id\":\"5c5fb281b01ee091a0fffa5b4a4c7fb7d358e7fb7c49c263d6d7a4e35d199fd0\",\"created\":\"2015-12-08T18:31:50.979824705Z\",\"container\":\"ea7fe68f39fd0df314e841247fb940ddef4c02ab7b5edb0ee724adc3174bc8d9\",\"container_config\":{\"Hostname\":\"ea7fe68f39fd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:c295b0748bf05d4527f500b62ff269bfd0037f7515f1375d2ee474b830bad382 in /\"],\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.8.3\",\"config\":{\"Hostname\":\"ea7fe68f39fd\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":1113436}" - // } - // ], + // ] // } 'query': { method:'GET', - isArray: false, + headers: { + accept: 'application/vnd.docker.distribution.manifest.v2+json', + }, transformResponse: function(data, headers){ - var res = {}; - var history = []; - var tmp; - var resp = angular.fromJson(data); - var v1Compatibility = undefined; - - for (var idx in resp.history){ - - v1Compatibility = angular.fromJson(resp.history[idx].v1Compatibility); + data = angular.fromJson(data); + data.digest = headers('docker-content-digest'); + data.imageId = data.config.digest.replace(/^sha256:/, ''); + data.size = data.layers.reduce(function(size, layer) { + return size + layer.size; + }, data.config.size); - if(v1Compatibility !== undefined){ - tmp = { - id : v1Compatibility.id, - os : v1Compatibility.os, - docker_version: v1Compatibility.docker_version, - created: v1Compatibility.created, - // parentLayer: v1Compatibility.parent - }; - if(v1Compatibility.author){ - tmp.author = v1Compatibility.author; - } - if(v1Compatibility.config && v1Compatibility.config.Labels){ - tmp.labels = v1Compatibility.config.Labels; - } - history.push(tmp); - } - } - if(history.length > 0){ - res = history[0]; - res.history = history; - } - res.fsLayers = resp.fsLayers; - res.digest = headers('docker-content-digest'); - res.architecture = resp.architecture; - return res; + return data; }, } }); }]) - // This is not totally working right now (problem with big layers) - /* .factory('Blob', ['$resource', function($resource){ return $resource('/v2/:repoUser/:repoName/blobs/:digest', {}, { - + // { + // "architecture": "amd64", + // "config": {}, + // "container": "caab3f21c75adc3560754e71374cd01cb1bbe39b2b9c2809ff6c22bbcd39206c", + // "container_config": {}, + // "created": "2017-04-25T03:44:24.620936172Z", + // "docker_version": "17.04.0-ce", + // "history": [ + // { + // "created": "2017-04-24T19:20:41.290148217Z", + // "created_by": "/bin/sh -c #(nop) ADD file:712c48086043553b85ffb031d8f6c5de857a2e53974df30cdfbc1e85c1b00a25 in / " + // }, + // { + // "created": "2017-04-24T19:20:42.022627269Z", + // "created_by": "/bin/sh -c #(nop) CMD [\"/bin/bash\"]", + // "empty_layer": true + // } + // ], + // "os": "linux", + // "rootfs": {} + // } 'query': { - method:'HEAD', - interceptor: function(data, headers){ - var res = {contentLength: parseInt(headers('content-length'))}; - return res; - } + method: 'GET', + transformResponse: function(data, headers){ + data = angular.fromJson(data); + data.dockerfile = data.history.map(function(history) { + return history.created_by + .replace(new RegExp('^/bin/sh -c #\\(nop\\)\\s*'), '') + .replace(new RegExp('^/bin/sh -c\\s*'), 'RUN ') + .replace(/\t\t/g, '\\\n\t'); + }); + + return data; + } } }); - }]) */ ; + }]); diff --git a/app/tag/tag-list-directive.html b/app/tag/tag-list-directive.html index c9fc235..e49c9ba 100644 --- a/app/tag/tag-list-directive.html +++ b/app/tag/tag-list-directive.html @@ -11,12 +11,8 @@ Tag - Image ID - Created - Author - Docker version - - + Image ID + Size (MB) @@ -27,20 +23,8 @@ {{tag.name}} - - - - - - + + {{tag.details.size / 1024 / 1024 | number: 2}}