diff --git a/app/app.js b/app/app.js
index c94961bb2..8ec6554ba 100644
--- a/app/app.js
+++ b/app/app.js
@@ -21,7 +21,8 @@ angular.module('dockerui', [
'events',
'stats',
'network',
- 'networks'])
+ 'networks',
+ 'volumes'])
.config(['$routeProvider', function ($routeProvider) {
'use strict';
$routeProvider.when('/', {
diff --git a/app/components/masthead/masthead.html b/app/components/masthead/masthead.html
index 3bb8a0267..7ff8766a0 100644
--- a/app/components/masthead/masthead.html
+++ b/app/components/masthead/masthead.html
@@ -5,7 +5,8 @@
Containers
Containers Network
Images
- Networks
+ Networks
+ Volumes
Info
diff --git a/app/components/masthead/mastheadController.js b/app/components/masthead/mastheadController.js
index 9d12cba42..ae375cab4 100644
--- a/app/components/masthead/mastheadController.js
+++ b/app/components/masthead/mastheadController.js
@@ -1,4 +1,11 @@
angular.module('masthead', [])
- .controller('MastheadController', ['$scope', function ($scope) {
+ .controller('MastheadController', ['$scope', 'Version', function ($scope, Version) {
$scope.template = 'app/components/masthead/masthead.html';
+ $scope.showNetworksVolumes = false;
+
+ Version.get(function(d) {
+ if (d.ApiVersion >= 1.21) {
+ $scope.showNetworksVolumes = true;
+ }
+ });
}]);
diff --git a/app/components/volumes/volumes.html b/app/components/volumes/volumes.html
new file mode 100644
index 000000000..af8921776
--- /dev/null
+++ b/app/components/volumes/volumes.html
@@ -0,0 +1,56 @@
+Volumes:
+
+
+
+
\ No newline at end of file
diff --git a/app/components/volumes/volumesController.js b/app/components/volumes/volumesController.js
new file mode 100644
index 000000000..bed59316a
--- /dev/null
+++ b/app/components/volumes/volumesController.js
@@ -0,0 +1,75 @@
+angular.module('volumes', []).config(['$routeProvider', function ($routeProvider) {
+ $routeProvider.when('/volumes', {
+ templateUrl: 'app/components/volumes/volumes.html',
+ controller: 'VolumesController'
+ });
+}]).controller('VolumesController', ['$scope', 'Volume', 'ViewSpinner', 'Messages', '$route', 'errorMsgFilter',
+ function ($scope, Volume, ViewSpinner, Messages, $route, errorMsgFilter) {
+ $scope.toggle = false;
+ $scope.predicate = '-Created';
+ $scope.createVolumeConfig = {
+ "Name": "",
+ "Driver": ""
+ };
+
+
+
+ $scope.removeAction = function () {
+ ViewSpinner.spin();
+ var counter = 0;
+ var complete = function () {
+ counter = counter - 1;
+ if (counter === 0) {
+ ViewSpinner.stop();
+ }
+ };
+ angular.forEach($scope.volumes, function (volume) {
+ if (volume.Checked) {
+ counter = counter + 1;
+ Volume.remove({name: volume.Name}, function (d) {
+ Messages.send("Volume deleted", volume.Name);
+ var index = $scope.volumes.indexOf(volume);
+ $scope.volumes.splice(index, 1);
+ complete();
+ }, function (e) {
+ Messages.error("Failure", e.data);
+ complete();
+ });
+ }
+ });
+ };
+
+ $scope.toggleSelectAll = function () {
+ angular.forEach($scope.volumes, function (i) {
+ i.Checked = $scope.toggle;
+ });
+ };
+
+ $scope.addVolume = function addVolume(createVolumeConfig) {
+ ViewSpinner.spin();
+ Volume.create(createVolumeConfig, function (d) {
+ if (d.Name) {
+ Messages.send("Volume created", d.Name);
+ } else {
+ Messages.error('Failure', errorMsgFilter(d));
+ }
+ ViewSpinner.stop();
+ fetchVolumes();
+ }, function (e) {
+ Messages.error("Failure", e.data);
+ ViewSpinner.stop();
+ });
+ };
+
+ function fetchVolumes() {
+ ViewSpinner.spin();
+ Volume.query({}, function (d) {
+ $scope.volumes = d.Volumes;
+ ViewSpinner.stop();
+ }, function (e) {
+ Messages.error("Failure", e.data);
+ ViewSpinner.stop();
+ });
+ }
+ fetchVolumes();
+ }]);
diff --git a/app/shared/services.js b/app/shared/services.js
index 3f48132b5..e0775de67 100644
--- a/app/shared/services.js
+++ b/app/shared/services.js
@@ -117,7 +117,7 @@ angular.module('dockerui.services', ['ngResource'])
get: {method: 'GET'}
});
}])
- .factory('Network', ['$resource', 'Settings', function NetworksFactory($resource, Settings) {
+ .factory('Network', ['$resource', 'Settings', function NetworkFactory($resource, Settings) {
'use strict';
// http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#2-5-networks
return $resource(Settings.url + '/networks/:id/:action', {id: '@id'}, {
@@ -129,6 +129,16 @@ angular.module('dockerui.services', ['ngResource'])
disconnect: {method: 'POST', params: {action: 'disconnect'}}
});
}])
+ .factory('Volume', ['$resource', 'Settings', function VolumeFactory($resource, Settings) {
+ 'use strict';
+ // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#2-5-networks
+ return $resource(Settings.url + '/volumes/:name/:action', {name: '@name'}, {
+ query: {method: 'GET'},
+ get: {method: 'GET'},
+ create: {method: 'POST', params: {action: 'create'}},
+ remove: {method: 'DELETE'}
+ });
+ }])
.factory('Settings', ['DOCKER_ENDPOINT', 'DOCKER_PORT', 'UI_VERSION', function SettingsFactory(DOCKER_ENDPOINT, DOCKER_PORT, UI_VERSION) {
'use strict';
var url = DOCKER_ENDPOINT;
diff --git a/test/unit/app/components/volumesController.spec.js b/test/unit/app/components/volumesController.spec.js
new file mode 100644
index 000000000..ef567c07a
--- /dev/null
+++ b/test/unit/app/components/volumesController.spec.js
@@ -0,0 +1,64 @@
+describe('VolumesController', function () {
+ var $scope, $httpBackend, $routeParams;
+
+ beforeEach(module('dockerui'));
+ beforeEach(inject(function (_$httpBackend_, $controller, _$routeParams_) {
+ $scope = {};
+ $httpBackend = _$httpBackend_;
+ $routeParams = _$routeParams_;
+ $controller('VolumesController', {
+ '$scope': $scope,
+ '$routeParams': $routeParams
+ });
+ }));
+
+ it('initializes correctly', function () {
+ expectGetVolumes();
+ $httpBackend.flush();
+ });
+
+
+ it('issues correct remove calls to the remote API', function () {
+ expectGetVolumes();
+ $httpBackend.flush();
+ $scope.volumes[0].Checked = true;
+ $scope.volumes[2].Checked = true;
+ $httpBackend.expectDELETE('dockerapi/volumes/tardis').respond(200);
+ $httpBackend.expectDELETE('dockerapi/volumes/bar').respond(200);
+ $scope.removeAction();
+ $httpBackend.flush();
+ });
+ it('issues a correct volume creation call to the remote API', function () {
+ expectGetVolumes();
+ var createBody = {
+ "Name": "tardis",
+ "Driver": "local"
+ };
+ $httpBackend.expectPOST('dockerapi/volumes/create', createBody).respond(201);
+ expectGetVolumes();
+ $scope.addVolume(createBody);
+ $httpBackend.flush();
+ });
+
+ function expectGetVolumes() {
+ $httpBackend.expectGET('dockerapi/volumes').respond({
+ "Volumes": [
+ {
+ "Name": "tardis",
+ "Driver": "local",
+ "Mountpoint": "/var/lib/docker/volumes/tardis"
+ },
+ {
+ "Name": "foo",
+ "Driver": "local",
+ "Mountpoint": "/var/lib/docker/volumes/foo"
+ },
+ {
+ "Name": "bar",
+ "Driver": "local",
+ "Mountpoint": "/var/lib/docker/volumes/bar"
+ }
+ ]
+ });
+ }
+});
\ No newline at end of file