Cleaned up controller methods, Added placeholders, fixed PortBindings and error messages.
parent
4682ae4ca7
commit
f75d298fe1
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="modal-body">
|
||||
<form role="form">
|
||||
<accordion close-others="true">
|
||||
<accordion-group heading="Container options">
|
||||
<accordion-group heading="Container options" is-open="menuStatus.containerOpen">
|
||||
<fieldset>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
|
@ -94,7 +94,7 @@
|
|||
<label>Security Options:</label>
|
||||
<div ng-repeat="opt in config.SecurityOpts">
|
||||
<div class="form-group form-inline">
|
||||
<input type="text" ng-model="opt.name" class="form-control" placeholder="???"/>
|
||||
<input type="text" ng-model="opt.name" class="form-control" placeholder="label:type:svirt_apache"/>
|
||||
<button type="button" class="btn btn-danger btn-sm" ng-click="rmEntry(config.SecurityOpts, opt)">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -102,6 +102,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<label>Environment Variables:</label>
|
||||
<div ng-repeat="envar in config.Env">
|
||||
|
@ -115,15 +116,15 @@
|
|||
<input type="text" ng-model="envar.value" class="form-control" placeholder="value"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-danger btn-xs form-control" ng-click="removeEnv(portBinding)">Remove</button>
|
||||
<button class="btn btn-danger btn-xs form-control" ng-click="rmEntry(config.Env, envar)">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success btn-sm" ng-click="addEnv()">Add ENV variable</button>
|
||||
<button type="button" class="btn btn-success btn-sm" ng-click="addEntry(config.Env, {name: '', value: ''})">Add ENV variable</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</accordion-group>
|
||||
<accordion-group heading="HostConfig options">
|
||||
<accordion-group heading="HostConfig options" is-open="menuStatus.hostConfigOpen">
|
||||
<fieldset>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
|
@ -131,7 +132,7 @@
|
|||
<label>Binds:</label>
|
||||
<div ng-repeat="bind in config.HostConfig.Binds">
|
||||
<div class="form-group form-inline">
|
||||
<input type="text" ng-model="bind.name" class="form-control" placeholder="???"/>
|
||||
<input type="text" ng-model="bind.name" class="form-control" placeholder="/host:/container"/>
|
||||
<button type="button" class="btn btn-danger btn-sm" ng-click="rmEntry(config.HostConfig.Binds, bind)">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -161,7 +162,7 @@
|
|||
<label>DnsSearch:</label>
|
||||
<div ng-repeat="entry in config.HostConfig.DnsSearch">
|
||||
<div class="form-group form-inline">
|
||||
<input type="text" ng-model="entry.name" class="form-control" placeholder="???"/>
|
||||
<input type="text" ng-model="entry.name" class="form-control" placeholder="example.com"/>
|
||||
<button type="button" class="btn btn-danger btn-sm" ng-click="rmEntry(config.HostConfig.DnsSearch, entry)">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -171,7 +172,7 @@
|
|||
<label>CapAdd:</label>
|
||||
<div ng-repeat="entry in config.HostConfig.CapAdd">
|
||||
<div class="form-group form-inline">
|
||||
<input type="text" ng-model="entry.name" class="form-control" placeholder="???"/>
|
||||
<input type="text" ng-model="entry.name" class="form-control" placeholder="cap_sys_admin"/>
|
||||
<button type="button" class="btn btn-danger btn-sm" ng-click="rmEntry(config.HostConfig.CapAdd, entry)">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -183,7 +184,7 @@
|
|||
<label>CapDrop:</label>
|
||||
<div ng-repeat="entry in config.HostConfig.CapDrop">
|
||||
<div class="form-group form-inline">
|
||||
<input type="text" ng-model="entry.name" class="form-control" placeholder="???"/>
|
||||
<input type="text" ng-model="entry.name" class="form-control" placeholder="cap_sys_admin"/>
|
||||
<button type="button" class="btn btn-danger btn-sm" ng-click="rmEntry(config.HostConfig.CapDrop, entry)">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -206,10 +207,10 @@
|
|||
<div ng-repeat="volume in config.HostConfig.VolumesFrom">
|
||||
<div class="form-inline">
|
||||
<select ng-model="volume.name" ng-options="name for name in containerNames track by name" class="form-control"/>
|
||||
<button class="btn btn-danger btn-xs form-control" ng-click="removeVolumeFrom($index)">Remove</button>
|
||||
<button class="btn btn-danger btn-xs form-control" ng-click="rmEntry(config.HostConfig.VolumesFrom, volume)">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success btn-sm" ng-click="addVolumeFrom()">Add volume</button>
|
||||
<button type="button" class="btn btn-success btn-sm" ng-click="addEntry(config.HostConfig.VolumesFrom, {name: ''})">Add volume</button>
|
||||
</div>
|
||||
<!--
|
||||
<div class="form-group">
|
||||
|
@ -224,9 +225,10 @@
|
|||
-->
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<label>Port bindings:</label>
|
||||
<div ng-repeat="portBinding in config.PortBindings">
|
||||
<div ng-repeat="portBinding in config.HostConfig.PortBindings">
|
||||
<div class="form-group form-inline">
|
||||
<label class="sr-only">Host IP:</label>
|
||||
<input type="text" ng-model="portBinding.ip" class="form-control" placeholder="Host IP Address"/>
|
||||
|
@ -234,10 +236,10 @@
|
|||
<input type="text" ng-model="portBinding.extPort" class="form-control" placeholder="Host Port"/>
|
||||
<label class="sr-only">Container port:</label>
|
||||
<input type="text" ng-model="portBinding.intPort" class="form-control" placeholder="Container Port"/>
|
||||
<button class="btn btn-danger btn-xs form-control" ng-click="removePortBinding(portBinding)">Remove</button>
|
||||
<button class="btn btn-danger btn-xs form-control" ng-click="rmEntry(config.HostConfig.PortBindings, portBinding)">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success btn-sm" ng-click="addPortBinding()">Add Port Binding</button>
|
||||
<button type="button" class="btn btn-success btn-sm" ng-click="addEntry(config.HostConfig.PortBindings, {ip: '', extPort: '', intPort: ''})">Add Port Binding</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</accordion-group>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}));
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue