diff --git a/app/components/startContainer/startContainerController.js b/app/components/startContainer/startContainerController.js index d0bee1909..ddd606aa3 100644 --- a/app/components/startContainer/startContainerController.js +++ b/app/components/startContainer/startContainerController.js @@ -1,6 +1,6 @@ angular.module('startContainer', ['ui.bootstrap']) -.controller('StartContainerController', ['$scope', '$routeParams', '$location', 'Container', 'Messages', 'containernameFilter', -function($scope, $routeParams, $location, Container, Messages, containernameFilter) { +.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) { @@ -13,8 +13,8 @@ function($scope, $routeParams, $location, Container, Messages, containernameFilt Env: [], Volumes: [], SecurityOpts: [], - PortBindings: [], HostConfig: { + PortBindings: [], Binds: [], Links: [], Dns: [], @@ -25,8 +25,13 @@ function($scope, $routeParams, $location, Container, Messages, containernameFilt } }; + $scope.menuStatus = { + containerOpen: true, + hostConfigOpen: false + }; + function failedRequestHandler(e, Messages) { - Messages.send({class: 'text-error', data: e.data}); + Messages.error('Error', errorMsgFilter(e)); } function rmEmptyKeys(col) { @@ -67,7 +72,7 @@ function($scope, $routeParams, $location, Container, Messages, containernameFilt var ExposedPorts = {}; var PortBindings = {}; // TODO: consider using compatibility library - config.PortBindings.forEach(function(portBinding) { + config.HostConfig.PortBindings.forEach(function(portBinding) { var intPort = portBinding.intPort + "/tcp"; var binding = { HostIp: portBinding.ip, @@ -85,7 +90,6 @@ function($scope, $routeParams, $location, Container, Messages, containernameFilt } }); config.ExposedPorts = ExposedPorts; - delete config.PortBindings; config.HostConfig.PortBindings = PortBindings; // Remove empty fields from the request to avoid overriding defaults @@ -111,35 +115,6 @@ function($scope, $routeParams, $location, Container, Messages, containernameFilt }); }; - $scope.addPortBinding = function() { - $scope.config.PortBindings.push({ip: '', extPort: '', intPort: ''}); - }; - - $scope.removePortBinding = function(portBinding) { - var idx = $scope.config.PortBindings.indexOf(portBinding); - $scope.config.PortBindings.splice(idx, 1); - }; - - // TODO: refactor out - $scope.addEnv = function() { - $scope.config.Env.push({name: '', value: ''}); - }; - - $scope.removeEnv = function(envar) { - var idx = $scope.config.env.indexOf(envar); - $scope.config.Env.splice(idx, 1); - }; - - // Todo: refactor out - $scope.addVolumeFrom = function() { - $scope.config.HostConfig.volumesFrom.push({name: ''}); - }; - - $scope.removeVolumeFrom = function(volume) { - var idx = $scope.config.HostConfig.volumesFrom.indexOf(volume); - $scope.config.HostConfig.volumesFrom.splice(idx, 1); - }; - $scope.addEntry = function(array, entry) { array.push(entry); }; diff --git a/app/components/startContainer/startContainerController.spec.js b/app/components/startContainer/startContainerController.spec.js index 50fe21035..0ce1f15f2 100644 --- a/app/components/startContainer/startContainerController.spec.js +++ b/app/components/startContainer/startContainerController.spec.js @@ -20,18 +20,18 @@ describe('startContainerController', function() { })); function expectGetContainers() { $httpBackend.expectGET('dockerapi/containers/json?all=1').respond([{ - "Command": "./dockerui -e /docker.sock", - "Created": 1421817232, - "Id": "b17882378cee8ec0136f482681b764cca430befd52a9bfd1bde031f49b8bba9f", - "Image": "dockerui:latest", - "Names": ["/dockerui"], - "Ports": [{ - "IP": "0.0.0.0", - "PrivatePort": 9000, - "PublicPort": 9000, - "Type": "tcp" + 'Command': './dockerui -e /docker.sock', + 'Created': 1421817232, + 'Id': 'b17882378cee8ec0136f482681b764cca430befd52a9bfd1bde031f49b8bba9f', + 'Image': 'dockerui:latest', + 'Names': ['/dockerui'], + 'Ports': [{ + 'IP': '0.0.0.0', + 'PrivatePort': 9000, + 'PublicPort': 9000, + 'Type': 'tcp' }], - "Status": "Up 2 minutes" + 'Status': 'Up 2 minutes' }]); } describe('Create and start a container with port bindings', function() { @@ -39,15 +39,15 @@ describe('startContainerController', function() { var controller = createController(); var id = '6abd8bfba81cf8a05a76a4bdefcb36c4b66cd02265f4bfcd0e236468696ebc6c'; var expectedBody = { - "name": "container-name", - "ExposedPorts": { - "9000/tcp": {}, + 'name': 'container-name', + 'ExposedPorts': { + '9000/tcp': {}, }, - "HostConfig": { - "PortBindings": { - "9000/tcp": [{ - "HostPort": "9999", - "HostIp": "10.20.10.15", + 'HostConfig': { + 'PortBindings': { + '9000/tcp': [{ + 'HostPort': '9999', + 'HostIp': '10.20.10.15', }] }, } @@ -56,16 +56,16 @@ describe('startContainerController', function() { expectGetContainers(); $httpBackend.expectPOST('dockerapi/containers/create?name=container-name', expectedBody).respond({ - "Id": id, - "Warnings": null + 'Id': id, + 'Warnings': null }); $httpBackend.expectPOST('dockerapi/containers/' + id + '/start?').respond({ - "Id": id, - "Warnings": null + 'Id': id, + 'Warnings': null }); scope.config.name = 'container-name'; - scope.config.PortBindings = [{ + scope.config.HostConfig.PortBindings = [{ ip: '10.20.10.15', extPort: '9999', intPort: '9000' @@ -81,19 +81,19 @@ describe('startContainerController', function() { var controller = createController(); var id = '6abd8bfba81cf8a05a76a4bdefcb36c4b66cd02265f4bfcd0e236468696ebc6c'; var expectedBody = { - "name": "container-name", - "Env": ["SHELL=/bin/bash", "TERM=xterm-256color"] + 'name': 'container-name', + 'Env': ['SHELL=/bin/bash', 'TERM=xterm-256color'] }; expectGetContainers(); $httpBackend.expectPOST('dockerapi/containers/create?name=container-name', expectedBody).respond({ - "Id": id, - "Warnings": null + 'Id': id, + 'Warnings': null }); $httpBackend.expectPOST('dockerapi/containers/' + id + '/start?').respond({ - "Id": id, - "Warnings": null + 'Id': id, + 'Warnings': null }); scope.config.name = 'container-name'; @@ -116,25 +116,75 @@ describe('startContainerController', function() { var id = '6abd8bfba81cf8a05a76a4bdefcb36c4b66cd02265f4bfcd0e236468696ebc6c'; var expectedBody = { HostConfig: { - "VolumesFrom": ["parent", "other:ro"] + 'VolumesFrom': ['parent', 'other:ro'] }, - "name": "container-name" + 'name': 'container-name' }; expectGetContainers(); - $httpBackend.expectPOST('dockerapi/containers/create?name=container-name', expectedBody).respond({ - "Id": id, - "Warnings": null + 'Id': id, + 'Warnings': null }); $httpBackend.expectPOST('dockerapi/containers/' + id + '/start?').respond({ - "Id": id, - "Warnings": null + 'Id': id, + 'Warnings': null }); scope.config.name = 'container-name'; - scope.config.HostConfig.VolumesFrom = [{name: "parent"}, {name:"other:ro"}]; + scope.config.HostConfig.VolumesFrom = [{name: 'parent'}, {name:'other:ro'}]; + + scope.create(); + $httpBackend.flush(); + }); + }); + + describe('Create and start a container with multiple options', function() { + it('should issue a correct create request to the Docker remote API', function() { + var controller = createController(); + var id = '6abd8bfba81cf8a05a76a4bdefcb36c4b66cd02265f4bfcd0e236468696ebc6c'; + var expectedBody = { + Volumes: ['/var/www'], + SecurityOpts: ['label:type:svirt_apache'], + HostConfig: { + Binds: ['/app:/app'], + Links: ['web:db'], + Dns: ['8.8.8.8'], + DnsSearch: ['example.com'], + CapAdd: ['cap_sys_admin'], + CapDrop: ['cap_foo_bar'] + }, + name: 'container-name' + }; + + expectGetContainers(); + + $httpBackend.expectPOST('dockerapi/containers/create?name=container-name', expectedBody).respond({ + 'Id': id, + 'Warnings': null + }); + $httpBackend.expectPOST('dockerapi/containers/' + id + '/start?').respond({ + 'Id': id, + 'Warnings': null + }); + + scope.config.name = 'container-name'; + scope.config.Volumes = [{name: '/var/www'}]; + scope.config.SecurityOpts = [{name: 'label:type:svirt_apache'}]; + scope.config.NetworkDisabled = true; + scope.config.Tty = true; + scope.config.OpenStdin = true; + scope.config.StdinOnce = true; + + scope.config.HostConfig.Binds = [{name: '/app:/app'}]; + scope.config.HostConfig.Links = [{name: 'web:db'}]; + scope.config.HostConfig.Dns = [{name: '8.8.8.8'}]; + scope.config.HostConfig.DnsSearch = [{name: 'example.com'}]; + scope.config.HostConfig.CapAdd = [{name: 'cap_sys_admin'}]; + scope.config.HostConfig.CapDrop = [{name: 'cap_foo_bar'}]; + scope.config.HostConfig.PublishAllPorts = true; + scope.config.HostConfig.Privileged = true; scope.create(); $httpBackend.flush(); diff --git a/app/components/startContainer/startcontainer.html b/app/components/startContainer/startcontainer.html index 3599698f4..309fe03d0 100644 --- a/app/components/startContainer/startcontainer.html +++ b/app/components/startContainer/startcontainer.html @@ -8,7 +8,7 @@ +
@@ -115,15 +116,15 @@
- +
- + - +
@@ -131,7 +132,7 @@
- +
@@ -161,7 +162,7 @@
- +
@@ -171,7 +172,7 @@
- +
@@ -183,7 +184,7 @@
- +
@@ -206,10 +207,10 @@
@@ -234,10 +236,10 @@ - +
- +
diff --git a/app/shared/filters.js b/app/shared/filters.js index 2b390d9c9..f0b7c6daa 100644 --- a/app/shared/filters.js +++ b/app/shared/filters.js @@ -99,4 +99,15 @@ angular.module('dockerui.filters', []) 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; + }; }); diff --git a/app/shared/services.js b/app/shared/services.js index 5a06bc5db..6dbed1f94 100644 --- a/app/shared/services.js +++ b/app/shared/services.js @@ -119,7 +119,7 @@ angular.module('dockerui.services', ['ngResource']) $.gritter.add({ title: title, text: text, - time: 6000, + time: 10000, before_open: function() { if($('.gritter-item-wrapper').length === 4) { return false; diff --git a/test/unit/shared/filters.spec.js b/test/unit/shared/filters.spec.js index b6c753faf..f48640783 100644 --- a/test/unit/shared/filters.spec.js +++ b/test/unit/shared/filters.spec.js @@ -153,4 +153,13 @@ describe('filters', function () { expect(getdateFilter(1420424998)).toBe('Sun Jan 04 2015'); })); }); + + describe('errorMsgFilter', function() { + it('should convert the $resource object to a string message', + inject(function(errorMsgFilter) { + var response = {'0':'C','1':'o','2':'n','3':'f','4':'l','5':'i','6':'c','7':'t','8':',','9':' ','10':'T','11':'h','12':'e','13':' ','14':'n','15':'a','16':'m','17':'e','18':' ','19':'u','20':'b','21':'u','22':'n','23':'t','24':'u','25':'-','26':'s','27':'l','28':'e','29':'e','30':'p','31':'-','32':'r','33':'u','34':'n','35':'t','36':'i','37':'m','38':'e','39':' ','40':'i','41':'s','42':' ','43':'a','44':'l','45':'r','46':'e','47':'a','48':'d','49':'y','50':' ','51':'a','52':'s','53':'s','54':'i','55':'g','56':'n','57':'e','58':'d','59':' ','60':'t','61':'o','62':' ','63':'b','64':'6','65':'9','66':'e','67':'5','68':'3','69':'a','70':'6','71':'2','72':'2','73':'c','74':'8','75':'.','76':' ','77':'Y','78':'o','79':'u','80':' ','81':'h','82':'a','83':'v','84':'e','85':' ','86':'t','87':'o','88':' ','89':'d','90':'e','91':'l','92':'e','93':'t','94':'e','95':' ','96':'(','97':'o','98':'r','99':' ','100':'r','101':'e','102':'n','103':'a','104':'m','105':'e','106':')','107':' ','108':'t','109':'h','110':'a','111':'t','112':' ','113':'c','114':'o','115':'n','116':'t','117':'a','118':'i','119':'n','120':'e','121':'r','122':' ','123':'t','124':'o','125':' ','126':'b','127':'e','128':' ','129':'a','130':'b','131':'l','132':'e','133':' ','134':'t','135':'o','136':' ','137':'a','138':'s','139':'s','140':'i','141':'g','142':'n','143':' ','144':'u','145':'b','146':'u','147':'n','148':'t','149':'u','150':'-','151':'s','152':'l','153':'e','154':'e','155':'p','156':'-','157':'r','158':'u','159':'n','160':'t','161':'i','162':'m','163':'e','164':' ','165':'t','166':'o','167':' ','168':'a','169':' ','170':'c','171':'o','172':'n','173':'t','174':'a','175':'i','176':'n','177':'e','178':'r','179':' ','180':'a','181':'g','182':'a','183':'i','184':'n','185':'.','186':'\n','$promise':{},'$resolved':true}; + var message = 'Conflict, The name ubuntu-sleep-runtime is already assigned to b69e53a622c8. You have to delete (or rename) that container to be able to assign ubuntu-sleep-runtime to a container again.\n'; + expect(errorMsgFilter(response)).toBe(message); + })); + }); }); \ No newline at end of file