Skip to content

Commit

Permalink
Implemented remaining container creation options.
Browse files Browse the repository at this point in the history
  • Loading branch information
kevana committed Jan 25, 2015
1 parent c8213bb commit 4682ae4
Show file tree
Hide file tree
Showing 8 changed files with 346 additions and 196 deletions.
2 changes: 1 addition & 1 deletion app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ angular.module('dockerui', ['dockerui.templates', 'ngRoute', 'dockerui.services'
}])
// 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_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.6.0')
.constant('DOCKER_API_VERSION', 'v1.16');
143 changes: 83 additions & 60 deletions app/components/startContainer/startContainerController.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
angular.module('startContainer', [])
angular.module('startContainer', ['ui.bootstrap'])
.controller('StartContainerController', ['$scope', '$routeParams', '$location', 'Container', 'Messages', 'containernameFilter',
function($scope, $routeParams, $location, Container, Messages, containernameFilter) {
$scope.template = 'app/components/startContainer/startcontainer.html';
Expand All @@ -10,81 +10,94 @@ function($scope, $routeParams, $location, Container, Messages, containernameFilt
});

$scope.config = {
name: '',
memory: 0,
memorySwap: 0,
cpuShares: 1024,
env: [],
commands: '',
volumesFrom: [],
portBindings: []
Env: [],
Volumes: [],
SecurityOpts: [],
PortBindings: [],
HostConfig: {
Binds: [],
Links: [],
Dns: [],
DnsSearch: [],
VolumesFrom: [],
CapAdd: [],
CapDrop: []
}
};
$scope.commandPlaceholder = '["/bin/echo", "Hello world"]';

function failedRequestHandler(e, Messages) {
Messages.send({class: 'text-error', data: e.data});
}

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() {
var cmds = null;
if ($scope.config.commands !== '') {
cmds = angular.fromJson($scope.config.commands);
// 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);
}
var id = $routeParams.id;
var ctor = Container;
var loc = $location;
var s = $scope;

var volumesFrom = $scope.config.volumesFrom.map(function(volume) {
return volume.name;
});
config.Env = config.Env.map(function(envar) {return envar.name + '=' + envar.value;});

var env = $scope.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);

var exposedPorts = {};
var portBindings = {};
var ExposedPorts = {};
var PortBindings = {};
// TODO: consider using compatibility library
$scope.config.portBindings.forEach(function(portBinding) {
config.PortBindings.forEach(function(portBinding) {
var intPort = portBinding.intPort + "/tcp";
var binding = {
HostIp: portBinding.ip,
HostPort: portBinding.extPort
};
if (portBinding.intPort) {
exposedPorts[intPort] = {};
if (intPort in portBindings) {
portBindings[intPort].push(binding);
ExposedPorts[intPort] = {};
if (intPort in PortBindings) {
PortBindings[intPort].push(binding);
} else {
portBindings[intPort] = [binding];
PortBindings[intPort] = [binding];
}
} else {
// TODO: Send warning message? Internal port need to be specified.
}
});
config.ExposedPorts = ExposedPorts;
delete config.PortBindings;
config.HostConfig.PortBindings = PortBindings;

Container.create({
Image: id,
name: $scope.config.name,
Memory: $scope.config.memory,
MemorySwap: $scope.config.memorySwap,
CpuShares: $scope.config.cpuShares,
Cmd: cmds,
VolumesFrom: volumesFrom,
Env: env,
ExposedPorts: exposedPorts,
HostConfig: {
PortBindings: portBindings
}
}, function(d) {
// 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) {
ctor.start({
id: d.Id,
HostConfig: {
PortBindings: portBindings
}
}, function(cd) {
ctor.start({id: d.Id}, function(cd) {
$('#create-modal').modal('hide');
loc.path('/containers/' + d.Id + '/');
}, function(e) {
Expand All @@ -99,29 +112,39 @@ function($scope, $routeParams, $location, Container, Messages, containernameFilt
};

$scope.addPortBinding = function() {
$scope.config.portBindings.push({ip: '', extPort: '', intPort: ''});
$scope.config.PortBindings.push({ip: '', extPort: '', intPort: ''});
};

$scope.removePortBinding = function(portBinding) {
var idx = $scope.config.portBindings.indexOf(portBinding);
$scope.config.portBindings.splice(idx, 1);
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.config.Env.push({name: '', value: ''});
};

$scope.removeEnv = function(envar) {
var idx = $scope.config.env.indexOf(envar);
$scope.config.env.splice(idx, 1);
$scope.config.Env.splice(idx, 1);
};

$scope.addVolume = function() {
$scope.config.volumesFrom.push({name: ''});
// Todo: refactor out
$scope.addVolumeFrom = function() {
$scope.config.HostConfig.volumesFrom.push({name: ''});
};

$scope.removeVolume = function(volume) {
var idx = $scope.config.volumesFrom.indexOf(volume);
$scope.config.volumesFrom.splice(idx, 1);
$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);
};
$scope.rmEntry = function(array, entry) {
var idx = array.indexOf(entry);
array.splice(idx, 1);
};
}]);
119 changes: 37 additions & 82 deletions app/components/startContainer/startContainerController.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,28 @@ describe('startContainerController', function() {
$httpBackend = _$httpBackend_;
});
}));

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"
}],
"Status": "Up 2 minutes"
}]);
}
describe('Create and start a container with port bindings', function() {
it('should issue a correct create request to the Docker remote API', function() {
var controller = createController();
var id = '6abd8bfba81cf8a05a76a4bdefcb36c4b66cd02265f4bfcd0e236468696ebc6c';
var expectedBody = {
"name": "container-name",
"Memory": 0,
"MemorySwap": 0,
"CpuShares": 1024,
"Cmd": null,
"VolumesFrom": [],
"Env": [],
"ExposedPorts": {
"9000/tcp": {},
},
Expand All @@ -44,32 +53,19 @@ describe('startContainerController', function() {
}
};

$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"
}],
"Status": "Up 2 minutes"
}]);

$httpBackend.expectPOST('/dockerapi/containers/create?name=container-name', expectedBody).respond({
expectGetContainers();

$httpBackend.expectPOST('dockerapi/containers/create?name=container-name', expectedBody).respond({
"Id": id,
"Warnings": null
});
$httpBackend.expectPOST('/dockerapi/containers/' + id + '/start?').respond({
$httpBackend.expectPOST('dockerapi/containers/' + id + '/start?').respond({
"Id": id,
"Warnings": null
});

scope.config.name = 'container-name';
scope.config.portBindings = [{
scope.config.PortBindings = [{
ip: '10.20.10.15',
extPort: '9999',
intPort: '9000'
Expand All @@ -86,44 +82,22 @@ describe('startContainerController', function() {
var id = '6abd8bfba81cf8a05a76a4bdefcb36c4b66cd02265f4bfcd0e236468696ebc6c';
var expectedBody = {
"name": "container-name",
"Memory": 0,
"MemorySwap": 0,
"CpuShares": 1024,
"Cmd": null,
"VolumesFrom": [],
"Env": ["SHELL=/bin/bash", "TERM=xterm-256color"],
"ExposedPorts": {},
"HostConfig": {
"PortBindings": {}
}
"Env": ["SHELL=/bin/bash", "TERM=xterm-256color"]
};

$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"
}],
"Status": "Up 2 minutes"
}]);

$httpBackend.expectPOST('/dockerapi/containers/create?name=container-name', expectedBody).respond({
expectGetContainers();

$httpBackend.expectPOST('dockerapi/containers/create?name=container-name', expectedBody).respond({
"Id": id,
"Warnings": null
});
$httpBackend.expectPOST('/dockerapi/containers/' + id + '/start?').respond({
$httpBackend.expectPOST('dockerapi/containers/' + id + '/start?').respond({
"Id": id,
"Warnings": null
});

scope.config.name = 'container-name';
scope.config.env = [{
scope.config.Env = [{
name: 'SHELL',
value: '/bin/bash'
}, {
Expand All @@ -141,45 +115,26 @@ describe('startContainerController', function() {
var controller = createController();
var id = '6abd8bfba81cf8a05a76a4bdefcb36c4b66cd02265f4bfcd0e236468696ebc6c';
var expectedBody = {
"name": "container-name",
"Memory": 0,
"MemorySwap": 0,
"CpuShares": 1024,
"Cmd": null,
"VolumesFrom": ["parent", "other:ro"],
"Env": [],
"ExposedPorts": {},
"HostConfig": {
"PortBindings": {}
}
HostConfig: {
"VolumesFrom": ["parent", "other:ro"]
},
"name": "container-name"
};

$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"
}],
"Status": "Up 2 minutes"
}]);

$httpBackend.expectPOST('/dockerapi/containers/create?name=container-name', expectedBody).respond({
expectGetContainers();


$httpBackend.expectPOST('dockerapi/containers/create?name=container-name', expectedBody).respond({
"Id": id,
"Warnings": null
});
$httpBackend.expectPOST('/dockerapi/containers/' + id + '/start?').respond({
$httpBackend.expectPOST('dockerapi/containers/' + id + '/start?').respond({
"Id": id,
"Warnings": null
});

scope.config.name = 'container-name';
scope.config.volumesFrom = [{name: "parent"}, {name:"other:ro"}];
scope.config.HostConfig.VolumesFrom = [{name: "parent"}, {name:"other:ro"}];

scope.create();
$httpBackend.flush();
Expand Down
Loading

0 comments on commit 4682ae4

Please sign in to comment.