/*! dockerui - v0.9.0-beta - 2015-08-24
* https://github.com/crosbymichael/dockerui
* Copyright (c) 2015 Michael Crosby & Kevan Ahlquist;
* Licensed MIT
*/
angular.module('dockerui', ['dockerui.templates', 'ngRoute', 'dockerui.services', 'dockerui.filters', 'masthead', 'footer', 'dashboard', 'container', 'containers', 'containersNetwork', 'images', 'image', 'pullImage', 'startContainer', 'sidebar', 'info', 'builder', 'containerLogs', 'containerTop', 'events'])
.config(['$routeProvider', function ($routeProvider) {
'use strict';
$routeProvider.when('/', {
templateUrl: 'app/components/dashboard/dashboard.html',
controller: 'DashboardController'
});
$routeProvider.when('/containers/', {
templateUrl: 'app/components/containers/containers.html',
controller: 'ContainersController'
});
$routeProvider.when('/containers/:id/', {
templateUrl: 'app/components/container/container.html',
controller: 'ContainerController'
});
$routeProvider.when('/containers/:id/logs/', {
templateUrl: 'app/components/containerLogs/containerlogs.html',
controller: 'ContainerLogsController'
});
$routeProvider.when('/containers/:id/top', {
templateUrl: 'app/components/containerTop/containerTop.html',
controller: 'ContainerTopController'
});
$routeProvider.when('/containers_network', {
templateUrl: 'app/components/containersNetwork/containersNetwork.html',
controller: 'ContainersNetworkController'
});
$routeProvider.when('/images/', {
templateUrl: 'app/components/images/images.html',
controller: 'ImagesController'
});
$routeProvider.when('/images/:id*/', {
templateUrl: 'app/components/image/image.html',
controller: 'ImageController'
});
$routeProvider.when('/info', {templateUrl: 'app/components/info/info.html', controller: 'InfoController'});
$routeProvider.when('/events', {templateUrl: 'app/components/events/events.html', controller: 'EventsController'});
$routeProvider.otherwise({redirectTo: '/'});
}])
// This is your docker url that the api will use to make requests
// You need to set this to the api endpoint without the port i.e. http://192.168.1.9
.constant('DOCKER_ENDPOINT', 'dockerapi')
.constant('DOCKER_PORT', '') // Docker port, leave as an empty string if no port is requred. If you have a port, prefix it with a ':' i.e. :4243
.constant('UI_VERSION', 'v0.7.0')
.constant('DOCKER_API_VERSION', 'v1.17');
angular.module('builder', [])
.controller('BuilderController', ['$scope', 'Dockerfile', 'Messages',
function($scope, Dockerfile, Messages) {
$scope.template = 'app/components/builder/builder.html';
}]);
angular.module('container', [])
.controller('ContainerController', ['$scope', '$routeParams', '$location', 'Container', 'ContainerCommit', 'Messages', 'ViewSpinner',
function($scope, $routeParams, $location, Container, ContainerCommit, Messages, ViewSpinner) {
$scope.changes = [];
$scope.edit = false;
var update = function() {
ViewSpinner.spin();
Container.get({id: $routeParams.id}, function(d) {
$scope.container = d;
$scope.container.edit = false;
$scope.container.newContainerName = d.Name;
ViewSpinner.stop();
}, function(e) {
if (e.status === 404) {
$('.detail').hide();
Messages.error("Not found", "Container not found.");
} else {
Messages.error("Failure", e.data);
}
ViewSpinner.stop();
});
};
$scope.start = function(){
ViewSpinner.spin();
Container.start({
id: $scope.container.Id,
HostConfig: $scope.container.HostConfig
}, function(d) {
update();
Messages.send("Container started", $routeParams.id);
}, function(e) {
update();
Messages.error("Failure", "Container failed to start." + e.data);
});
};
$scope.stop = function() {
ViewSpinner.spin();
Container.stop({id: $routeParams.id}, function(d) {
update();
Messages.send("Container stopped", $routeParams.id);
}, function(e) {
update();
Messages.error("Failure", "Container failed to stop." + e.data);
});
};
$scope.kill = function() {
ViewSpinner.spin();
Container.kill({id: $routeParams.id}, function(d) {
update();
Messages.send("Container killed", $routeParams.id);
}, function(e) {
update();
Messages.error("Failure", "Container failed to die." + e.data);
});
};
$scope.commit = function() {
ViewSpinner.spin();
ContainerCommit.commit({id: $routeParams.id, repo: $scope.container.Config.Image}, function(d) {
update();
Messages.send("Container commited", $routeParams.id);
}, function(e) {
update();
Messages.error("Failure", "Container failed to commit." + e.data);
});
};
$scope.pause = function() {
ViewSpinner.spin();
Container.pause({id: $routeParams.id}, function(d) {
update();
Messages.send("Container paused", $routeParams.id);
}, function(e) {
update();
Messages.error("Failure", "Container failed to pause." + e.data);
});
};
$scope.unpause = function() {
ViewSpinner.spin();
Container.unpause({id: $routeParams.id}, function(d) {
update();
Messages.send("Container unpaused", $routeParams.id);
}, function(e) {
update();
Messages.error("Failure", "Container failed to unpause." + e.data);
});
};
$scope.remove = function() {
ViewSpinner.spin();
Container.remove({id: $routeParams.id}, function(d) {
update();
Messages.send("Container removed", $routeParams.id);
}, function(e){
update();
Messages.error("Failure", "Container failed to remove." + e.data);
});
};
$scope.restart = function() {
ViewSpinner.spin();
Container.restart({id: $routeParams.id}, function(d) {
update();
Messages.send("Container restarted", $routeParams.id);
}, function(e){
update();
Messages.error("Failure", "Container failed to restart." + e.data);
});
};
$scope.hasContent = function(data) {
return data !== null && data !== undefined;
};
$scope.getChanges = function() {
ViewSpinner.spin();
Container.changes({id: $routeParams.id}, function(d) {
$scope.changes = d;
ViewSpinner.stop();
});
};
$scope.renameContainer = function () {
// #FIXME fix me later to handle http status to show the correct error message
Container.rename({id: $routeParams.id, 'name': $scope.container.newContainerName}, function(data){
if (data.name){
$scope.container.Name = data.name;
Messages.send("Container renamed", $routeParams.id);
}else {
$scope.container.newContainerName = $scope.container.Name;
Messages.error("Failure", "Container failed to rename.");
}
});
$scope.container.edit = false;
};
update();
$scope.getChanges();
}]);
angular.module('containerLogs', [])
.controller('ContainerLogsController', ['$scope', '$routeParams', '$location', '$anchorScroll', 'ContainerLogs', 'Container', 'ViewSpinner',
function($scope, $routeParams, $location, $anchorScroll, ContainerLogs, Container, ViewSpinner) {
$scope.stdout = '';
$scope.stderr = '';
$scope.showTimestamps = false;
$scope.tailLines = 2000;
ViewSpinner.spin();
Container.get({id: $routeParams.id}, function(d) {
$scope.container = d;
ViewSpinner.stop();
}, function(e) {
if (e.status === 404) {
Messages.error("Not found", "Container not found.");
} else {
Messages.error("Failure", e.data);
}
ViewSpinner.stop();
});
function getLogs() {
ViewSpinner.spin();
ContainerLogs.get($routeParams.id, {
stdout: 1,
stderr: 0,
timestamps: $scope.showTimestamps,
tail: $scope.tailLines
}, function(data, status, headers, config) {
// Replace carriage returns with newlines to clean up output
data = data.replace(/[\r]/g, '\n');
// Strip 8 byte header from each line of output
data = data.substring(8);
data = data.replace(/\n(.{8})/g, '\n');
$scope.stdout = data;
ViewSpinner.stop();
});
ContainerLogs.get($routeParams.id, {
stdout: 0,
stderr: 1,
timestamps: $scope.showTimestamps,
tail: $scope.tailLines
}, function(data, status, headers, config) {
// Replace carriage returns with newlines to clean up output
data = data.replace(/[\r]/g, '\n');
// Strip 8 byte header from each line of output
data = data.substring(8);
data = data.replace(/\n(.{8})/g, '\n');
$scope.stderr = data;
ViewSpinner.stop();
});
}
// initial call
getLogs();
var logIntervalId = window.setInterval(getLogs, 5000);
$scope.$on("$destroy", function(){
// clearing interval when view changes
clearInterval(logIntervalId);
});
$scope.scrollTo = function(id) {
$location.hash(id);
$anchorScroll();
};
$scope.toggleTimestamps = function() {
getLogs();
};
$scope.toggleTail = function() {
getLogs();
};
}]);
angular.module('containerTop', [])
.controller('ContainerTopController', ['$scope', '$routeParams', 'ContainerTop', 'ViewSpinner', function ($scope, $routeParams, ContainerTop, ViewSpinner) {
$scope.ps_args = '';
/**
* Get container processes
*/
$scope.getTop = function () {
ViewSpinner.spin();
ContainerTop.get($routeParams.id, {
ps_args: $scope.ps_args
}, function (data) {
$scope.containerTop = data;
ViewSpinner.stop();
});
};
$scope.getTop();
}]);
angular.module('containers', [])
.controller('ContainersController', ['$scope', 'Container', 'Settings', 'Messages', 'ViewSpinner',
function($scope, Container, Settings, Messages, ViewSpinner) {
$scope.predicate = '-Created';
$scope.toggle = false;
$scope.displayAll = Settings.displayAll;
var update = function(data) {
ViewSpinner.spin();
Container.query(data, function(d) {
$scope.containers = d.map(function(item) {
return new ContainerViewModel(item); });
ViewSpinner.stop();
});
};
var batch = function(items, action, msg) {
ViewSpinner.spin();
var counter = 0;
var complete = function() {
counter = counter -1;
if (counter === 0) {
ViewSpinner.stop();
update({all: Settings.displayAll ? 1 : 0});
}
};
angular.forEach(items, function(c) {
if (c.Checked) {
if(action === Container.start){
Container.get({id: c.Id}, function(d) {
c = d;
counter = counter + 1;
action({id: c.Id, HostConfig: c.HostConfig || {}}, function(d) {
Messages.send("Container " + msg, c.Id);
var index = $scope.containers.indexOf(c);
complete();
}, function(e) {
Messages.error("Failure", e.data);
complete();
});
}, function(e) {
if (e.status === 404) {
$('.detail').hide();
Messages.error("Not found", "Container not found.");
} else {
Messages.error("Failure", e.data);
}
complete();
});
}
else{
counter = counter + 1;
action({id: c.Id}, function(d) {
Messages.send("Container " + msg, c.Id);
var index = $scope.containers.indexOf(c);
complete();
}, function(e) {
Messages.error("Failure", e.data);
complete();
});
}
}
});
if (counter === 0) {
ViewSpinner.stop();
}
};
$scope.toggleSelectAll = function() {
angular.forEach($scope.containers, function(i) {
i.Checked = $scope.toggle;
});
};
$scope.toggleGetAll = function() {
Settings.displayAll = $scope.displayAll;
update({all: Settings.displayAll ? 1 : 0});
};
$scope.startAction = function() {
batch($scope.containers, Container.start, "Started");
};
$scope.stopAction = function() {
batch($scope.containers, Container.stop, "Stopped");
};
$scope.restartAction = function() {
batch($scope.containers, Container.restart, "Restarted");
};
$scope.killAction = function() {
batch($scope.containers, Container.kill, "Killed");
};
$scope.pauseAction = function() {
batch($scope.containers, Container.pause, "Paused");
};
$scope.unpauseAction = function() {
batch($scope.containers, Container.unpause, "Unpaused");
};
$scope.removeAction = function() {
batch($scope.containers, Container.remove, "Removed");
};
update({all: Settings.displayAll ? 1 : 0});
}]);
angular.module('containersNetwork', ['ngVis'])
.controller('ContainersNetworkController', ['$scope', '$location', 'Container', 'Messages', 'VisDataSet', function($scope, $location, Container, Messages, VisDataSet) {
function ContainerNode(data) {
this.Id = data.Id;
// names have the following format: /Name
this.Name = data.Name.substring(1);
this.Image = data.Config.Image;
this.Running = data.State.Running;
var dataLinks = data.HostConfig.Links;
if (dataLinks != null) {
this.Links = {};
for (var i = 0; i < dataLinks.length; i++) {
// links have the following format: /TargetContainerName:/SourceContainerName/LinkAlias
var link = dataLinks[i].split(":");
var target = link[0].substring(1);
var alias = link[1].substring(link[1].lastIndexOf("/") + 1);
// only keep shortest alias
if (this.Links[target] == null || alias.length < this.Links[target].length) {
this.Links[target] = alias;
}
}
}
var dataVolumes = data.HostConfig.VolumesFrom;
//converting array into properties for simpler and faster access
if (dataVolumes != null) {
this.VolumesFrom = {};
for (var j = 0; j < dataVolumes.length; j++) {
this.VolumesFrom[dataVolumes[j]] = true;
}
}
}
function ContainersNetworkData() {
this.nodes = new VisDataSet();
this.edges = new VisDataSet();
this.addContainerNode = function(container) {
this.nodes.add({
id: container.Id,
label: container.Name,
title: "
" +
"- ID: " + container.Id + "
" +
"- Image: " + container.Image + "
" +
"
",
color: (container.Running ? "#8888ff" : "#cccccc")
});
};
this.hasEdge = function(from, to) {
return this.edges.getIds({
filter: function (item) {
return item.from == from.Id && item.to == to.Id;
} }).length > 0;
};
this.addLinkEdgeIfExists = function(from, to) {
if (from.Links != null && from.Links[to.Name] != null && !this.hasEdge(from, to)) {
this.edges.add({
from: from.Id,
to: to.Id,
label: from.Links[to.Name] });
}
};
this.addVolumeEdgeIfExists = function(from, to) {
if (from.VolumesFrom != null && (from.VolumesFrom[to.Id] != null || from.VolumesFrom[to.Name] != null) && !this.hasEdge(from, to)) {
this.edges.add({
from: from.Id,
to: to.Id,
color: { color: '#A0A0A0', highlight: '#A0A0A0', hover: '#848484'}});
}
};
this.removeContainersNodes = function(containersIds) {
this.nodes.remove(containersIds);
};
}
function ContainersNetwork() {
this.data = new ContainersNetworkData();
this.containers = {};
this.selectedContainersIds = [];
this.shownContainersIds = [];
this.events = {
select : function(event) {
$scope.network.selectedContainersIds = event.nodes;
$scope.$apply( function() {
$scope.query = '';
});
},
doubleClick : function(event) {
$scope.$apply( function() {
$location.path('/containers/' + event.nodes[0]);
});
}
};
this.options = {
navigation: true,
keyboard: true,
height: '500px', width: '700px',
nodes: {
shape: 'box'
},
edges: {
style: 'arrow'
},
physics: {
barnesHut : {
springLength: 200
}
}
};
this.addContainer = function(data) {
var container = new ContainerNode(data);
this.containers[container.Id] = container;
this.shownContainersIds.push(container.Id);
this.data.addContainerNode(container);
for (var otherContainerId in this.containers) {
var otherContainer = this.containers[otherContainerId];
this.data.addLinkEdgeIfExists(container, otherContainer);
this.data.addLinkEdgeIfExists(otherContainer, container);
this.data.addVolumeEdgeIfExists(container, otherContainer);
this.data.addVolumeEdgeIfExists(otherContainer, container);
}
};
this.selectContainers = function(query) {
if (this.component != null) {
this.selectedContainersIds = this.searchContainers(query);
this.component.selectNodes(this.selectedContainersIds);
}
};
this.searchContainers = function(query) {
if (query.trim() === "") {
return [];
}
var selectedContainersIds = [];
for (var i=0; i < this.shownContainersIds.length; i++) {
var container = this.containers[this.shownContainersIds[i]];
if (container.Name.indexOf(query) > -1 ||
container.Image.indexOf(query) > -1 ||
container.Id.indexOf(query) > -1) {
selectedContainersIds.push(container.Id);
}
}
return selectedContainersIds;
};
this.hideSelected = function() {
var i=0;
while ( i < this.shownContainersIds.length ) {
if (this.selectedContainersIds.indexOf(this.shownContainersIds[i]) > -1) {
this.shownContainersIds.splice(i, 1);
} else {
i++;
}
}
this.data.removeContainersNodes(this.selectedContainersIds);
$scope.query = '';
this.selectedContainersIds = [];
};
this.searchDownstream = function(containerId, downstreamContainersIds) {
if (downstreamContainersIds.indexOf(containerId) > -1) {
return;
}
downstreamContainersIds.push(containerId);
var container = this.containers[containerId];
if (container.Links == null && container.VolumesFrom == null) {
return;
}
for (var otherContainerId in this.containers) {
var otherContainer = this.containers[otherContainerId];
if (container.Links != null && container.Links[otherContainer.Name] != null) {
this.searchDownstream(otherContainer.Id, downstreamContainersIds);
} else if (container.VolumesFrom != null &&
container.VolumesFrom[otherContainer.Id] != null) {
this.searchDownstream(otherContainer.Id, downstreamContainersIds);
}
}
};
this.updateShownContainers = function(newShownContainersIds) {
for (var containerId in this.containers) {
if (newShownContainersIds.indexOf(containerId) > -1 &&
this.shownContainersIds.indexOf(containerId) === -1) {
this.data.addContainerNode(this.containers[containerId]);
} else if (newShownContainersIds.indexOf(containerId) === -1 &&
this.shownContainersIds.indexOf(containerId) > -1) {
this.data.removeContainersNodes(containerId);
}
}
this.shownContainersIds = newShownContainersIds;
};
this.showSelectedDownstream = function() {
var downstreamContainersIds = [];
for (var i=0; i < this.selectedContainersIds.length; i++) {
this.searchDownstream(this.selectedContainersIds[i], downstreamContainersIds);
}
this.updateShownContainers(downstreamContainersIds);
};
this.searchUpstream = function(containerId, upstreamContainersIds) {
if (upstreamContainersIds.indexOf(containerId) > -1) {
return;
}
upstreamContainersIds.push(containerId);
var container = this.containers[containerId];
for (var otherContainerId in this.containers) {
var otherContainer = this.containers[otherContainerId];
if (otherContainer.Links != null && otherContainer.Links[container.Name] != null) {
this.searchUpstream(otherContainer.Id, upstreamContainersIds);
} else if (otherContainer.VolumesFrom != null &&
otherContainer.VolumesFrom[container.Id] != null) {
this.searchUpstream(otherContainer.Id, upstreamContainersIds);
}
}
};
this.showSelectedUpstream = function() {
var upstreamContainersIds = [];
for (var i=0; i < this.selectedContainersIds.length; i++) {
this.searchUpstream(this.selectedContainersIds[i], upstreamContainersIds);
}
this.updateShownContainers(upstreamContainersIds);
};
this.showAll = function() {
for (var containerId in this.containers) {
if (this.shownContainersIds.indexOf(containerId) === -1) {
this.data.addContainerNode(this.containers[containerId]);
this.shownContainersIds.push(containerId);
}
}
};
}
$scope.network = new ContainersNetwork();
var showFailure = function (event) {
Messages.error('Failure', e.data);
};
var addContainer = function (container) {
$scope.network.addContainer(container);
};
var update = function (data) {
Container.query(data, function(d) {
for (var i = 0; i < d.length; i++) {
Container.get({id: d[i].Id}, addContainer, showFailure);
}
});
};
update({all: 0});
$scope.includeStopped = false;
$scope.toggleIncludeStopped = function() {
$scope.network.updateShownContainers([]);
update({all: $scope.includeStopped ? 1 : 0});
};
}]);
angular.module('dashboard', [])
.controller('DashboardController', ['$scope', 'Container', 'Image', 'Settings', 'LineChart', function($scope, Container, Image, Settings, LineChart) {
$scope.predicate = '-Created';
$scope.containers = [];
var getStarted = function(data) {
$scope.totalContainers = data.length;
LineChart.build('#containers-started-chart', data, function(c) { return new Date(c.Created * 1000).toLocaleDateString(); });
var s = $scope;
Image.query({}, function(d) {
s.totalImages = d.length;
LineChart.build('#images-created-chart', d, function(c) { return new Date(c.Created * 1000).toLocaleDateString(); });
});
};
var opts = {animation:false};
if (Settings.firstLoad) {
$('#stats').hide();
opts.animation = true;
Settings.firstLoad = false;
$('#masthead').show();
setTimeout(function() {
$('#masthead').slideUp('slow');
$('#stats').slideDown('slow');
}, 5000);
}
Container.query({all: 1}, function(d) {
var running = 0;
var ghost = 0;
var stopped = 0;
for (var i = 0; i < d.length; i++) {
var item = d[i];
if (item.Status === "Ghost") {
ghost += 1;
} else if (item.Status.indexOf('Exit') !== -1) {
stopped += 1;
} else {
running += 1;
$scope.containers.push(new ContainerViewModel(item));
}
}
getStarted(d);
var c = new Chart($('#containers-chart').get(0).getContext("2d"));
var data = [
{
value: running,
color: '#5bb75b',
title: 'Running'
}, // running
{
value: stopped,
color: '#C7604C',
title: 'Stopped'
}, // stopped
{
value: ghost,
color: '#E2EAE9',
title: 'Ghost'
} // ghost
];
c.Doughnut(data, opts);
var lgd = $('#chart-legend').get(0);
legend(lgd, data);
});
}]);
angular.module('events', ['ngOboe'])
.controller('EventsController', ['Settings', '$scope', 'Oboe', 'Messages', '$timeout', function(Settings, $scope, oboe, Messages, $timeout) {
$scope.updateEvents = function() {
$scope.dockerEvents = [];
// TODO: Clean up URL building
var url = Settings.url + '/events?';
if ($scope.model.since) {
var sinceSecs = Math.floor($scope.model.since.getTime() / 1000);
url += 'since=' + sinceSecs + '&';
}
if ($scope.model.until) {
var untilSecs = Math.floor($scope.model.until.getTime() / 1000);
url += 'until=' + untilSecs;
}
oboe({
url: url,
pattern: '{id status time}'
})
.then(function(node) {
// finished loading
$timeout(function() {
$scope.$apply();
});
}, function(error) {
// handle errors
Messages.error("Failure", error.data);
}, function(node) {
// node received
$scope.dockerEvents.push(node);
});
};
// Init
$scope.model = {};
$scope.model.since = new Date(Date.now() - 86400000); // 24 hours in the past
$scope.model.until = new Date();
$scope.updateEvents();
}]);
angular.module('footer', [])
.controller('FooterController', ['$scope', 'Settings', 'Docker', function($scope, Settings, Docker) {
$scope.template = 'app/components/footer/statusbar.html';
$scope.uiVersion = Settings.uiVersion;
Docker.get({}, function(d) { $scope.apiVersion = d.ApiVersion; });
}]);
angular.module('image', [])
.controller('ImageController', ['$scope', '$q', '$routeParams', '$location', 'Image', 'Container', 'Messages', 'LineChart',
function($scope, $q, $routeParams, $location, Image, Container, Messages, LineChart) {
$scope.history = [];
$scope.tag = {repo: '', force: false};
$scope.remove = function() {
Image.remove({id: $routeParams.id}, function(d) {
Messages.send("Image Removed", $routeParams.id);
}, function(e) {
$scope.error = e.data;
$('#error-message').show();
});
};
$scope.getHistory = function() {
Image.history({id: $routeParams.id}, function(d) {
$scope.history = d;
});
};
$scope.updateTag = function() {
var tag = $scope.tag;
Image.tag({id: $routeParams.id, repo: tag.repo, force: tag.force ? 1 : 0}, function(d) {
Messages.send("Tag Added", $routeParams.id);
}, function(e) {
$scope.error = e.data;
$('#error-message').show();
});
};
function getContainersFromImage($q, Container, tag) {
var defer = $q.defer();
Container.query({all:1, notruc:1}, function(d) {
var containers = [];
for (var i = 0; i < d.length; i++) {
var c = d[i];
if (c.Image === tag) {
containers.push(new ContainerViewModel(c));
}
}
defer.resolve(containers);
});
return defer.promise;
}
Image.get({id: $routeParams.id}, function(d) {
$scope.image = d;
$scope.tag = d.id;
var t = $routeParams.tag;
if (t && t !== ":") {
$scope.tag = t;
var promise = getContainersFromImage($q, Container, t);
promise.then(function(containers) {
LineChart.build('#containers-started-chart', containers, function(c) { return new Date(c.Created * 1000).toLocaleDateString(); });
});
}
}, function(e) {
if (e.status === 404) {
$('.detail').hide();
$scope.error = "Image not found.
" + $routeParams.id;
} else {
$scope.error = e.data;
}
$('#error-message').show();
});
$scope.getHistory();
}]);
angular.module('images', [])
.controller('ImagesController', ['$scope', 'Image', 'ViewSpinner', 'Messages',
function($scope, Image, ViewSpinner, Messages) {
$scope.toggle = false;
$scope.predicate = '-Created';
$scope.showBuilder = function() {
$('#build-modal').modal('show');
};
$scope.removeAction = function() {
ViewSpinner.spin();
var counter = 0;
var complete = function() {
counter = counter - 1;
if (counter === 0) {
ViewSpinner.stop();
}
};
angular.forEach($scope.images, function(i) {
if (i.Checked) {
counter = counter + 1;
Image.remove({id: i.Id}, function(d) {
angular.forEach(d, function(resource) {
Messages.send("Image deleted", resource.Deleted);
});
var index = $scope.images.indexOf(i);
$scope.images.splice(index, 1);
complete();
}, function(e) {
Messages.error("Failure", e.data);
complete();
});
}
});
};
$scope.toggleSelectAll = function() {
angular.forEach($scope.images, function(i) {
i.Checked = $scope.toggle;
});
};
ViewSpinner.spin();
Image.query({}, function(d) {
$scope.images = d.map(function(item) { return new ImageViewModel(item); });
ViewSpinner.stop();
}, function (e) {
Messages.error("Failure", e.data);
ViewSpinner.stop();
});
}]);
angular.module('info', [])
.controller('InfoController', ['$scope', 'System', 'Docker', 'Settings', 'Messages',
function($scope, System, Docker, Settings, Messages) {
$scope.info = {};
$scope.docker = {};
$scope.endpoint = Settings.endpoint;
$scope.apiVersion = Settings.version;
Docker.get({}, function(d) { $scope.docker = d; });
System.get({}, function(d) { $scope.info = d; });
}]);
angular.module('masthead', [])
.controller('MastheadController', ['$scope', function($scope) {
$scope.template = 'app/components/masthead/masthead.html';
}]);
angular.module('pullImage', [])
.controller('PullImageController', ['$scope', '$log', 'Dockerfile', 'Messages', 'Image', 'ViewSpinner',
function($scope, $log, Dockerfile, Messages, Image, ViewSpinner) {
$scope.template = 'app/components/pullImage/pullImage.html';
$scope.init = function() {
$scope.config = {
registry: '',
repo: '',
fromImage: '',
tag: 'latest'
}
}
$scope.init();
function failedRequestHandler(e, Messages) {
Messages.error('Error', errorMsgFilter(e));
}
$scope.pull = function() {
$('#error-message').hide();
var config = angular.copy($scope.config);
var imageName = (config.registry ? config.registry + '/' : '' ) +
(config.repo ? config.repo + '/' : '') +
(config.fromImage) +
(config.tag ? ':' + config.tag : '');
ViewSpinner.spin();
$('#pull-modal').modal('hide');
Image.create(config, function(data) {
ViewSpinner.stop();
if (data.constructor === Array) {
var f = data.length > 0 && data[data.length-1].hasOwnProperty('error');
//check for error
if (f) {
var d = data[data.length - 1];
$scope.error = "Cannot pull image " + imageName + " Reason: " + d.error;
$('#pull-modal').modal('show');
$('#error-message').show();
} else {
Messages.send("Image Added", imageName);
$scope.init();
}
} else {
Messages.send("Image Added", imageName);
$scope.init();
}
}, function(e) {
ViewSpinner.stop();
$scope.error = "Cannot pull image " + imageName + " Reason: " + e.data;
$('#pull-modal').modal('show');
$('#error-message').show();
});
}
}]);
angular.module('sidebar', [])
.controller('SideBarController', ['$scope', 'Container', 'Settings',
function($scope, Container, Settings) {
$scope.template = 'partials/sidebar.html';
$scope.containers = [];
$scope.endpoint = Settings.endpoint;
Container.query({all: 0}, function(d) {
$scope.containers = d;
});
}]);
angular.module('startContainer', ['ui.bootstrap'])
.controller('StartContainerController', ['$scope', '$routeParams', '$location', 'Container', 'Messages', 'containernameFilter', 'errorMsgFilter',
function($scope, $routeParams, $location, Container, Messages, containernameFilter, errorMsgFilter) {
$scope.template = 'app/components/startContainer/startcontainer.html';
Container.query({all: 1}, function(d) {
$scope.containerNames = d.map(function(container){
return containernameFilter(container);
});
});
$scope.config = {
Env: [],
Volumes: [],
SecurityOpts: [],
HostConfig: {
PortBindings: [],
Binds: [],
Links: [],
Dns: [],
DnsSearch: [],
VolumesFrom: [],
CapAdd: [],
CapDrop: [],
Devices: [],
LxcConf: [],
ExtraHosts: []
}
};
$scope.menuStatus = {
containerOpen: true,
hostConfigOpen: false
};
function failedRequestHandler(e, Messages) {
Messages.error('Error', errorMsgFilter(e));
}
function rmEmptyKeys(col) {
for (var key in col) {
if (col[key] === null || col[key] === undefined || col[key] === '' || $.isEmptyObject(col[key]) || col[key].length === 0) {
delete col[key];
}
}
}
function getNames(arr) {
return arr.map(function(item) {return item.name;});
}
$scope.create = function() {
// Copy the config before transforming fields to the remote API format
var config = angular.copy($scope.config);
config.Image = $routeParams.id;
if (config.Cmd && config.Cmd[0] === "[") {
config.Cmd = angular.fromJson(config.Cmd);
} else if (config.Cmd) {
config.Cmd = config.Cmd.split(' ');
}
config.Env = config.Env.map(function(envar) {return envar.name + '=' + envar.value;});
config.Volumes = getNames(config.Volumes);
config.SecurityOpts = getNames(config.SecurityOpts);
config.HostConfig.VolumesFrom = getNames(config.HostConfig.VolumesFrom);
config.HostConfig.Binds = getNames(config.HostConfig.Binds);
config.HostConfig.Links = getNames(config.HostConfig.Links);
config.HostConfig.Dns = getNames(config.HostConfig.Dns);
config.HostConfig.DnsSearch = getNames(config.HostConfig.DnsSearch);
config.HostConfig.CapAdd = getNames(config.HostConfig.CapAdd);
config.HostConfig.CapDrop = getNames(config.HostConfig.CapDrop);
config.HostConfig.LxcConf = config.HostConfig.LxcConf.reduce(function(prev, cur, idx){
prev[cur.name] = cur.value;
return prev;
}, {});
config.HostConfig.ExtraHosts = config.HostConfig.ExtraHosts.map(function(entry) {return entry.host + ':' + entry.ip;});
var ExposedPorts = {};
var PortBindings = {};
config.HostConfig.PortBindings.forEach(function(portBinding) {
var intPort = portBinding.intPort + "/tcp";
if (portBinding.protocol === "udp") {
intPort = portBinding.intPort + "/udp";
}
var binding = {
HostIp: portBinding.ip,
HostPort: portBinding.extPort
};
if (portBinding.intPort) {
ExposedPorts[intPort] = {};
if (intPort in PortBindings) {
PortBindings[intPort].push(binding);
} else {
PortBindings[intPort] = [binding];
}
} else {
Messages.send('Warning', 'Internal port must be specified for PortBindings');
}
});
config.ExposedPorts = ExposedPorts;
config.HostConfig.PortBindings = PortBindings;
// Remove empty fields from the request to avoid overriding defaults
rmEmptyKeys(config.HostConfig);
rmEmptyKeys(config);
var ctor = Container;
var loc = $location;
var s = $scope;
Container.create(config, function(d) {
if (d.Id) {
var reqBody = config.HostConfig || {};
reqBody.id = d.Id;
ctor.start(reqBody, function(cd) {
if (cd.id) {
Messages.send('Container Started', d.Id);
$('#create-modal').modal('hide');
loc.path('/containers/' + d.Id + '/');
} else {
failedRequestHandler(cd, Messages);
ctor.remove({id: d.Id}, function() {
Messages.send('Container Removed', d.Id);
});
}
}, function(e) {
failedRequestHandler(e, Messages);
});
} else {
failedRequestHandler(d, Messages);
}
}, function(e) {
failedRequestHandler(e, Messages);
});
};
$scope.addEntry = function(array, entry) {
array.push(entry);
};
$scope.rmEntry = function(array, entry) {
var idx = array.indexOf(entry);
array.splice(idx, 1);
};
}]);
angular.module('dockerui.filters', [])
.filter('truncate', function() {
'use strict';
return function(text, length, end) {
if (isNaN(length)) {
length = 10;
}
if (end === undefined){
end = '...';
}
if (text.length <= length || text.length - end.length <= length) {
return text;
}
else {
return String(text).substring(0, length - end.length) + end;
}
};
})
.filter('statusbadge', function() {
'use strict';
return function(text) {
if (text === 'Ghost') {
return 'important';
} else if (text.indexOf('Exit') !== -1 && text !== 'Exit 0') {
return 'warning';
}
return 'success';
};
})
.filter('getstatetext', function() {
'use strict';
return function(state) {
if (state === undefined) {
return '';
}
if (state.Ghost && state.Running) {
return 'Ghost';
}
if (state.Running && state.Paused) {
return 'Running (Paused)';
}
if (state.Running) {
return 'Running';
}
return 'Stopped';
};
})
.filter('getstatelabel', function() {
'use strict';
return function(state) {
if (state === undefined) {
return '';
}
if (state.Ghost && state.Running) {
return 'label-important';
}
if (state.Running) {
return 'label-success';
}
return '';
};
})
.filter('humansize', function() {
'use strict';
return function(bytes) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes === 0) {
return 'n/a';
}
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10);
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[[i]];
};
})
.filter('containername', function() {
'use strict';
return function(container) {
var name = container.Names[0];
return name.substring(1, name.length);
};
})
.filter('repotag', function() {
'use strict';
return function(image) {
if (image.RepoTags && image.RepoTags.length > 0) {
var tag = image.RepoTags[0];
if (tag === ':') { tag = ''; }
return tag;
}
return '';
};
})
.filter('getdate', function() {
'use strict';
return function(data) {
//Multiply by 1000 for the unix format
var date = new Date(data * 1000);
return date.toDateString();
};
})
.filter('errorMsg', function() {
return function(object) {
var idx = 0;
var msg = '';
while (object[idx] && typeof(object[idx]) === 'string') {
msg += object[idx];
idx++;
}
return msg;
};
});
angular.module('dockerui.services', ['ngResource'])
.factory('Container', function ($resource, Settings) {
'use strict';
// Resource for interacting with the docker containers
// http://docs.docker.io/en/latest/api/docker_remote_api.html#containers
return $resource(Settings.url + '/containers/:id/:action', {
name: '@name'
}, {
query: {method: 'GET', params: {all: 0, action: 'json'}, isArray: true},
get: {method: 'GET', params: {action: 'json'}},
start: {method: 'POST', params: {id: '@id', action: 'start'}},
stop: {method: 'POST', params: {id: '@id', t: 5, action: 'stop'}},
restart: {method: 'POST', params: {id: '@id', t: 5, action: 'restart'}},
kill: {method: 'POST', params: {id: '@id', action: 'kill'}},
pause: {method: 'POST', params: {id: '@id', action: 'pause'}},
unpause: {method: 'POST', params: {id: '@id', action: 'unpause'}},
changes: {method: 'GET', params: {action: 'changes'}, isArray: true},
create: {method: 'POST', params: {action: 'create'}},
remove: {method: 'DELETE', params: {id: '@id', v: 0}},
rename: {method: 'POST', params: {id: '@id', action: 'rename'}, isArray: false}
});
})
.factory('ContainerCommit', function ($resource, $http, Settings) {
'use strict';
return {
commit: function (params, callback) {
$http({
method: 'POST',
url: Settings.url + '/commit',
params: {
'container': params.id,
'repo': params.repo
}
}).success(callback).error(function (data, status, headers, config) {
console.log(error, data);
});
}
};
})
.factory('ContainerLogs', function ($resource, $http, Settings) {
'use strict';
return {
get: function (id, params, callback) {
$http({
method: 'GET',
url: Settings.url + '/containers/' + id + '/logs',
params: {
'stdout': params.stdout || 0,
'stderr': params.stderr || 0,
'timestamps': params.timestamps || 0,
'tail': params.tail || 'all'
}
}).success(callback).error(function (data, status, headers, config) {
console.log(error, data);
});
}
};
})
.factory('ContainerTop', function ($http, Settings) {
'use strict';
return {
get: function (id, params, callback, errorCallback) {
$http({
method: 'GET',
url: Settings.url + '/containers/' + id + '/top',
params: {
ps_args: params.ps_args
}
}).success(callback);
}
};
})
.factory('Image', function ($resource, Settings) {
'use strict';
// Resource for docker images
// http://docs.docker.io/en/latest/api/docker_remote_api.html#images
return $resource(Settings.url + '/images/:id/:action', {}, {
query: {method: 'GET', params: {all: 0, action: 'json'}, isArray: true},
get: {method: 'GET', params: {action: 'json'}},
search: {method: 'GET', params: {action: 'search'}},
history: {method: 'GET', params: {action: 'history'}, isArray: true},
create: {method: 'POST', isArray: true, transformResponse: [function f(data) {
var str = data.replace(/\n/g, " ").replace(/\}\W*\{/g, "}, {");
return angular.fromJson("[" + str + "]");
}],
params: {action: 'create', fromImage: '@fromImage', repo: '@repo', tag: '@tag', registry: '@registry'}},
insert: {method: 'POST', params: {id: '@id', action: 'insert'}},
push: {method: 'POST', params: {id: '@id', action: 'push'}},
tag: {method: 'POST', params: {id: '@id', action: 'tag', force: 0, repo: '@repo'}},
remove: {method: 'DELETE', params: {id: '@id'}, isArray: true}
});
})
.factory('Docker', function ($resource, Settings) {
'use strict';
// Information for docker
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
return $resource(Settings.url + '/version', {}, {
get: {method: 'GET'}
});
})
.factory('Auth', function ($resource, Settings) {
'use strict';
// Auto Information for docker
// http://docs.docker.io/en/latest/api/docker_remote_api.html#set-auth-configuration
return $resource(Settings.url + '/auth', {}, {
get: {method: 'GET'},
update: {method: 'POST'}
});
})
.factory('System', function ($resource, Settings) {
'use strict';
// System for docker
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
return $resource(Settings.url + '/info', {}, {
get: {method: 'GET'}
});
})
.factory('Settings', function (DOCKER_ENDPOINT, DOCKER_PORT, DOCKER_API_VERSION, UI_VERSION) {
'use strict';
var url = DOCKER_ENDPOINT;
if (DOCKER_PORT) {
url = url + DOCKER_PORT + '\\' + DOCKER_PORT;
}
return {
displayAll: false,
endpoint: DOCKER_ENDPOINT,
version: DOCKER_API_VERSION,
rawUrl: DOCKER_ENDPOINT + DOCKER_PORT + '/' + DOCKER_API_VERSION,
uiVersion: UI_VERSION,
url: url,
firstLoad: true
};
})
.factory('ViewSpinner', function () {
'use strict';
var spinner = new Spinner();
var target = document.getElementById('view');
return {
spin: function () {
spinner.spin(target);
},
stop: function () {
spinner.stop();
}
};
})
.factory('Messages', function ($rootScope) {
'use strict';
return {
send: function (title, text) {
$.gritter.add({
title: title,
text: text,
time: 2000,
before_open: function () {
if ($('.gritter-item-wrapper').length === 3) {
return false;
}
}
});
},
error: function (title, text) {
$.gritter.add({
title: title,
text: text,
time: 10000,
before_open: function () {
if ($('.gritter-item-wrapper').length === 4) {
return false;
}
}
});
}
};
})
.factory('Dockerfile', function (Settings) {
'use strict';
var url = Settings.rawUrl + '/build';
return {
build: function (file, callback) {
var data = new FormData();
var dockerfile = new Blob([file], {type: 'text/text'});
data.append('Dockerfile', dockerfile);
var request = new XMLHttpRequest();
request.onload = callback;
request.open('POST', url);
request.send(data);
}
};
})
.factory('LineChart', function (Settings) {
'use strict';
var url = Settings.rawUrl + '/build';
return {
build: function (id, data, getkey) {
var chart = new Chart($(id).get(0).getContext("2d"));
var map = {};
for (var i = 0; i < data.length; i++) {
var c = data[i];
var key = getkey(c);
var count = map[key];
if (count === undefined) {
count = 0;
}
count += 1;
map[key] = count;
}
var labels = [];
data = [];
var keys = Object.keys(map);
for (i = keys.length - 1; i > -1; i--) {
var k = keys[i];
labels.push(k);
data.push(map[k]);
}
var dataset = {
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
data: data
};
chart.Line({
labels: labels,
datasets: [dataset]
},
{
scaleStepWidth: 1,
pointDotRadius: 1,
scaleOverride: true,
scaleSteps: labels.length
});
}
};
});
function ImageViewModel(data) {
this.Id = data.Id;
this.Tag = data.Tag;
this.Repository = data.Repository;
this.Created = data.Created;
this.Checked = false;
this.RepoTags = data.RepoTags;
this.VirtualSize = data.VirtualSize;
}
function ContainerViewModel(data) {
this.Id = data.Id;
this.Image = data.Image;
this.Command = data.Command;
this.Created = data.Created;
this.SizeRw = data.SizeRw;
this.Status = data.Status;
this.Checked = false;
this.Names = data.Names;
}
angular.module('dockerui.templates', ['app/components/builder/builder.html', 'app/components/container/container.html', 'app/components/containerLogs/containerlogs.html', 'app/components/containerTop/containerTop.html', 'app/components/containers/containers.html', 'app/components/containersNetwork/containersNetwork.html', 'app/components/dashboard/dashboard.html', 'app/components/events/events.html', 'app/components/footer/statusbar.html', 'app/components/image/image.html', 'app/components/images/images.html', 'app/components/info/info.html', 'app/components/masthead/masthead.html', 'app/components/pullImage/pullImage.html', 'app/components/sidebar/sidebar.html', 'app/components/startContainer/startcontainer.html']);
angular.module("app/components/builder/builder.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/builder/builder.html",
"\n" +
"
\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"
{{ messages }}
\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/container/container.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/container/container.html",
"\n" +
"\n" +
"
\n" +
"
Container: {{ container.Name }}\n" +
" \n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
" Container:\n" +
" \n" +
" \n" +
" \n" +
"
\n" +
" \n" +
"\n" +
"
\n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
"
\n" +
"\n" +
"
\n" +
" \n" +
" \n" +
" | Created: | \n" +
" {{ container.Created }} | \n" +
"
\n" +
" \n" +
" | Path: | \n" +
" {{ container.Path }} | \n" +
"
\n" +
" \n" +
" | Args: | \n" +
" {{ container.Args }} | \n" +
"
\n" +
" \n" +
" | Exposed Ports: | \n" +
" \n" +
" \n" +
" | \n" +
"
\n" +
" \n" +
" | Environment: | \n" +
" \n" +
" \n" +
" | \n" +
"
\n" +
"\n" +
" \n" +
" | Publish All: | \n" +
" {{ container.HostConfig.PublishAllPorts }} | \n" +
"
\n" +
" \n" +
" | Ports: | \n" +
" \n" +
" \n" +
" - \n" +
" {{ containerport }} => {{ v.HostIp }}:{{ v.HostPort }}\n" +
"
\n" +
" \n" +
" | \n" +
"\n" +
"
\n" +
" \n" +
" | Hostname: | \n" +
" {{ container.Config.Hostname }} | \n" +
"
\n" +
" \n" +
" | IPAddress: | \n" +
" {{ container.NetworkSettings.IPAddress }} | \n" +
"
\n" +
" \n" +
" | Cmd: | \n" +
" {{ container.Config.Cmd }} | \n" +
"
\n" +
" \n" +
" | Entrypoint: | \n" +
" {{ container.Config.Entrypoint }} | \n" +
"
\n" +
" \n" +
" | Volumes: | \n" +
" {{ container.Volumes }} | \n" +
"
\n" +
"\n" +
" \n" +
" | SysInitpath: | \n" +
" {{ container.SysInitPath }} | \n" +
"
\n" +
" \n" +
" | Image: | \n" +
" {{ container.Image }} | \n" +
"
\n" +
" \n" +
" | State: | \n" +
" {{ container.State|getstatetext }} | \n" +
"
\n" +
" \n" +
" | Logs: | \n" +
" stdout/stderr | \n" +
"
\n" +
" \n" +
" | Top: | \n" +
" Top | \n" +
"
\n" +
" \n" +
"
\n" +
"\n" +
"
\n" +
"
\n" +
" Changes:\n" +
"
\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
"
\n" +
" - \n" +
" {{ change.Path }} {{ change.Kind }}\n" +
"
\n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
"\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/containerLogs/containerlogs.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/containerLogs/containerlogs.html",
"\n" +
"
\n" +
"
\n" +
"
\n" +
" \n" +
" \n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
"
\n" +
"
\n" +
"
STDOUT
\n" +
" \n" +
"
\n" +
"
{{stdout}}\n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
"
STDERR
\n" +
" \n" +
"
\n" +
"
{{stderr}}\n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/containerTop/containerTop.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/containerTop/containerTop.html",
"\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
" \n" +
" \n" +
" | {{title}} | \n" +
"
\n" +
" \n" +
" \n" +
" \n" +
" | {{processInfo}} | \n" +
"
\n" +
" \n" +
"
\n" +
"
");
}]);
angular.module("app/components/containers/containers.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/containers/containers.html",
"\n" +
"Containers:
\n" +
"\n" +
"\n" +
"
\n" +
" - \n" +
" Actions \n" +
" \n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"\n" +
"");
}]);
angular.module("app/components/containersNetwork/containersNetwork.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/containersNetwork/containersNetwork.html",
"\n" +
"
Containers Network
\n" +
"\n" +
"
\n" +
"
\n" +
" \n" +
" \n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
" \n" +
" \n" +
" \n" +
" \n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/dashboard/dashboard.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/dashboard/dashboard.html",
" \n" +
"\n" +
" \n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"
\n" +
"
Running Containers
\n" +
"
\n" +
"
\n" +
"
\n" +
"
Status
\n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
"
\n" +
"
Containers created
\n" +
"
\n" +
"
Images created
\n" +
"
\n" +
"
\n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/events/events.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/events/events.html",
"\n" +
"
\n" +
"
Events
\n" +
"
\n" +
"
\n" +
"
\n" +
" \n" +
" \n" +
" | Event | \n" +
" From | \n" +
" ID | \n" +
" Time | \n" +
"
\n" +
" \n" +
" | \n" +
" | \n" +
" | \n" +
" | | \n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/footer/statusbar.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/footer/statusbar.html",
"\n" +
"");
}]);
angular.module("app/components/image/image.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/image/image.html",
"\n" +
"\n" +
"\n" +
" {{ error }}\n" +
"
\n" +
"\n" +
"\n" +
" \n" +
"
Image: {{ tag }}
\n" +
"\n" +
"
\n" +
" \n" +
"
\n" +
"\n" +
"
\n" +
"
Containers created:
\n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
" \n" +
" \n" +
" | Created: | \n" +
" {{ image.Created }} | \n" +
"
\n" +
" \n" +
" | Parent: | \n" +
" {{ image.Parent }} | \n" +
"
\n" +
" \n" +
" | Size (Virtual Size): | \n" +
" {{ image.Size|humansize }} ({{ image.VirtualSize|humansize }}) | \n" +
"
\n" +
"\n" +
" \n" +
" | Hostname: | \n" +
" {{ image.ContainerConfig.Hostname }} | \n" +
"
\n" +
" \n" +
" | User: | \n" +
" {{ image.ContainerConfig.User }} | \n" +
"
\n" +
" \n" +
" | Cmd: | \n" +
" {{ image.ContainerConfig.Cmd }} | \n" +
"
\n" +
" \n" +
" | Volumes: | \n" +
" {{ image.ContainerConfig.Volumes }} | \n" +
"
\n" +
" \n" +
" | Volumes from: | \n" +
" {{ image.ContainerConfig.VolumesFrom }} | \n" +
"
\n" +
" \n" +
" | Built with: | \n" +
" Docker {{ image.DockerVersion }} on {{ image.Os}}, {{ image.Architecture }} | \n" +
"
\n" +
"\n" +
" \n" +
"
\n" +
"\n" +
"
\n" +
"
\n" +
" History:\n" +
"
\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
"
\n" +
" - \n" +
" {{ change.Id }}: Created: {{ change.Created|getdate }} Created by: {{ change.CreatedBy }}\n" +
"
\n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
"\n" +
"
\n" +
"\n" +
"
\n" +
"\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/images/images.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/images/images.html",
"\n" +
"\n" +
"\n" +
"Images:
\n" +
"\n" +
"\n" +
" - \n" +
" Actions \n" +
" \n" +
"
\n" +
" - Pull
\n" +
"
\n" +
"\n" +
"");
}]);
angular.module("app/components/info/info.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/info/info.html",
"\n" +
"
Docker Information
\n" +
"
\n" +
"
\n" +
" API Endpoint: {{ endpoint }}
\n" +
" API Version: {{ docker.ApiVersion }}
\n" +
" Docker version: {{ docker.Version }}
\n" +
" Git Commit: {{ docker.GitCommit }}
\n" +
" Go Version: {{ docker.GoVersion }}
\n" +
"
\n" +
"
\n" +
"\n" +
"
\n" +
" \n" +
" \n" +
" | Containers: | \n" +
" {{ info.Containers }} | \n" +
"
\n" +
" \n" +
" | Images: | \n" +
" {{ info.Images }} | \n" +
"
\n" +
" \n" +
" | Debug: | \n" +
" {{ info.Debug }} | \n" +
"
\n" +
" \n" +
" | CPUs: | \n" +
" {{ info.NCPU }} | \n" +
"
\n" +
" \n" +
" | Total Memory: | \n" +
" {{ info.MemTotal|humansize }} | \n" +
"
\n" +
" \n" +
" | Operating System: | \n" +
" {{ info.OperatingSystem }} | \n" +
"
\n" +
" \n" +
" | Kernel Version: | \n" +
" {{ info.KernelVersion }} | \n" +
"
\n" +
" \n" +
" | ID: | \n" +
" {{ info.ID }} | \n" +
"
\n" +
" \n" +
" | Labels: | \n" +
" {{ info.Labels }} | \n" +
"
\n" +
" \n" +
" | File Descriptors: | \n" +
" {{ info.NFd }} | \n" +
"
\n" +
" \n" +
" | Goroutines: | \n" +
" {{ info.NGoroutines }} | \n" +
"
\n" +
" \n" +
" | Storage Driver: | \n" +
" {{ info.Driver }} | \n" +
"
\n" +
" \n" +
" | Storage Driver Status: | \n" +
" \n" +
" \n" +
" {{ val[0] }}: {{ val[1] }}\n" +
" \n" +
" | \n" +
"
\n" +
" \n" +
" | Execution Driver: | \n" +
" {{ info.ExecutionDriver }} | \n" +
"
\n" +
" \n" +
" | Events: | \n" +
" Events | \n" +
"
\n" +
" \n" +
" | IPv4 Forwarding: | \n" +
" {{ info.IPv4Forwarding }} | \n" +
"
\n" +
" \n" +
" | Index Server Address: | \n" +
" {{ info.IndexServerAddress }} | \n" +
"
\n" +
" \n" +
" | Init Path: | \n" +
" {{ info.InitPath }} | \n" +
"
\n" +
" \n" +
" | Docker Root Directory: | \n" +
" {{ info.DockerRootDir }} | \n" +
"
\n" +
" \n" +
" | Init SHA1 | \n" +
" {{ info.InitSha1 }} | \n" +
"
\n" +
" \n" +
" | Memory Limit: | \n" +
" {{ info.MemoryLimit }} | \n" +
"
\n" +
" \n" +
" | Swap Limit: | \n" +
" {{ info.SwapLimit }} | \n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/masthead/masthead.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/masthead/masthead.html",
" \n" +
"");
}]);
angular.module("app/components/pullImage/pullImage.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/pullImage/pullImage.html",
"\n" +
"
\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
" {{ error }}\n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/sidebar/sidebar.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/sidebar/sidebar.html",
"\n" +
"
Running containers:\n" +
"
\n" +
"
Endpoint: {{ endpoint }}\n" +
"
\n" +
"
\n" +
"");
}]);
angular.module("app/components/startContainer/startcontainer.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("app/components/startContainer/startcontainer.html",
"\n" +
"
\n" +
"
\n" +
" \n" +
"
\n" +
" \n" +
"
\n" +
"
\n" +
"
\n" +
"");
}]);