2016-07-06 00:19:09 +00:00
|
|
|
angular.module('createContainer', [])
|
2016-10-20 03:43:09 +00:00
|
|
|
.controller('CreateContainerController', ['$scope', '$state', '$stateParams', 'Config', 'Info', 'Container', 'Image', 'Volume', 'Network', 'TemplateHelper', 'Messages',
|
|
|
|
function ($scope, $state, $stateParams, Config, Info, Container, Image, Volume, Network, TemplateHelper, Messages) {
|
2016-07-06 00:19:09 +00:00
|
|
|
|
2016-10-20 03:43:09 +00:00
|
|
|
if ($stateParams.template) {
|
|
|
|
$scope.template = $stateParams.template;
|
|
|
|
}
|
2016-07-06 00:19:09 +00:00
|
|
|
|
|
|
|
$scope.formValues = {
|
2016-10-20 03:43:09 +00:00
|
|
|
alwaysPull: true,
|
2016-07-06 00:19:09 +00:00
|
|
|
Console: 'none',
|
2016-10-20 03:43:09 +00:00
|
|
|
Volumes: $scope.template && $scope.template.volumes ? TemplateHelper.getVolumeBindings($scope.template.volumes) : [],
|
2016-07-08 03:50:16 +00:00
|
|
|
Registry: ''
|
2016-07-06 00:19:09 +00:00
|
|
|
};
|
|
|
|
|
2016-07-08 03:31:09 +00:00
|
|
|
$scope.imageConfig = {};
|
2016-07-08 03:40:13 +00:00
|
|
|
|
2016-07-06 00:19:09 +00:00
|
|
|
$scope.config = {
|
2016-10-20 03:43:09 +00:00
|
|
|
Image: $scope.template ? $scope.template.image : '',
|
|
|
|
Env: $scope.template && $scope.template.env ? TemplateHelper.getEnvBindings($scope.template.env) : [],
|
2016-08-17 07:03:36 +00:00
|
|
|
ExposedPorts: {},
|
2016-07-06 00:19:09 +00:00
|
|
|
HostConfig: {
|
|
|
|
RestartPolicy: {
|
|
|
|
Name: 'no'
|
|
|
|
},
|
2016-10-20 03:43:09 +00:00
|
|
|
PortBindings: $scope.template ? TemplateHelper.getPortBindings($scope.template.ports) : [],
|
2016-07-06 00:19:09 +00:00
|
|
|
Binds: [],
|
|
|
|
NetworkMode: 'bridge',
|
|
|
|
Privileged: false
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.addVolume = function() {
|
2016-07-06 07:04:45 +00:00
|
|
|
$scope.formValues.Volumes.push({ name: '', containerPath: '' });
|
2016-07-06 00:19:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
$scope.removeVolume = function(index) {
|
|
|
|
$scope.formValues.Volumes.splice(index, 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.addEnvironmentVariable = function() {
|
|
|
|
$scope.config.Env.push({ name: '', value: ''});
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.removeEnvironmentVariable = function(index) {
|
|
|
|
$scope.config.Env.splice(index, 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.addPortBinding = function() {
|
|
|
|
$scope.config.HostConfig.PortBindings.push({ hostPort: '', containerPort: '', protocol: 'tcp' });
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.removePortBinding = function(index) {
|
|
|
|
$scope.config.HostConfig.PortBindings.splice(index, 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
Config.$promise.then(function (c) {
|
|
|
|
var swarm = c.swarm;
|
2016-09-23 04:54:58 +00:00
|
|
|
Info.get({}, function(info) {
|
2016-09-23 06:02:03 +00:00
|
|
|
if (swarm && !_.startsWith(info.ServerVersion, 'swarm')) {
|
2016-09-23 04:54:58 +00:00
|
|
|
$scope.swarm_mode = true;
|
|
|
|
}
|
|
|
|
});
|
2016-07-06 00:19:09 +00:00
|
|
|
|
|
|
|
Volume.query({}, function (d) {
|
2016-08-17 06:42:56 +00:00
|
|
|
$scope.availableVolumes = d.Volumes;
|
2016-07-06 00:19:09 +00:00
|
|
|
}, function (e) {
|
2016-09-02 05:40:03 +00:00
|
|
|
Messages.error("Failure", e, "Unable to retrieve volumes");
|
2016-07-06 00:19:09 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
Network.query({}, function (d) {
|
|
|
|
var networks = d;
|
|
|
|
if (swarm) {
|
|
|
|
networks = d.filter(function (network) {
|
|
|
|
if (network.Scope === 'global') {
|
|
|
|
return network;
|
|
|
|
}
|
|
|
|
});
|
2016-07-06 07:04:45 +00:00
|
|
|
$scope.globalNetworkCount = networks.length;
|
2016-07-06 00:19:09 +00:00
|
|
|
networks.push({Name: "bridge"});
|
|
|
|
networks.push({Name: "host"});
|
|
|
|
networks.push({Name: "none"});
|
|
|
|
}
|
|
|
|
$scope.availableNetworks = networks;
|
|
|
|
}, function (e) {
|
2016-09-02 05:40:03 +00:00
|
|
|
Messages.error("Failure", e, "Unable to retrieve networks");
|
2016-07-06 00:19:09 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-08-31 06:03:41 +00:00
|
|
|
// TODO: centralize, already present in templatesController
|
2016-07-06 00:19:09 +00:00
|
|
|
function createContainer(config) {
|
|
|
|
Container.create(config, function (d) {
|
2016-09-02 03:25:20 +00:00
|
|
|
if (d.message) {
|
|
|
|
$('#createContainerSpinner').hide();
|
2016-09-02 05:40:03 +00:00
|
|
|
Messages.error('Error', {}, d.message);
|
2016-09-02 03:25:20 +00:00
|
|
|
} else {
|
2016-09-02 01:51:49 +00:00
|
|
|
Container.start({id: d.Id}, {}, function (cd) {
|
2016-09-02 03:25:20 +00:00
|
|
|
if (cd.message) {
|
|
|
|
$('#createContainerSpinner').hide();
|
2016-09-02 05:40:03 +00:00
|
|
|
Messages.error('Error', {}, cd.message);
|
2016-09-02 03:25:20 +00:00
|
|
|
} else {
|
|
|
|
$('#createContainerSpinner').hide();
|
|
|
|
Messages.send('Container Started', d.Id);
|
|
|
|
$state.go('containers', {}, {reload: true});
|
|
|
|
}
|
2016-07-06 00:19:09 +00:00
|
|
|
}, function (e) {
|
2016-07-07 00:44:58 +00:00
|
|
|
$('#createContainerSpinner').hide();
|
2016-09-02 05:40:03 +00:00
|
|
|
Messages.error("Failure", e, 'Unable to start container');
|
2016-07-06 00:19:09 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}, function (e) {
|
2016-07-07 00:44:58 +00:00
|
|
|
$('#createContainerSpinner').hide();
|
2016-09-02 05:40:03 +00:00
|
|
|
Messages.error("Failure", e, 'Unable to create container');
|
2016-07-06 00:19:09 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-08-31 06:03:41 +00:00
|
|
|
// TODO: centralize, already present in templatesController
|
2016-07-06 00:19:09 +00:00
|
|
|
function pullImageAndCreateContainer(config) {
|
2016-07-08 03:31:09 +00:00
|
|
|
Image.create($scope.imageConfig, function (data) {
|
2016-08-31 06:03:41 +00:00
|
|
|
var err = data.length > 0 && data[data.length - 1].hasOwnProperty('error');
|
|
|
|
if (err) {
|
|
|
|
var detail = data[data.length - 1];
|
|
|
|
$('#createContainerSpinner').hide();
|
2016-09-02 05:40:03 +00:00
|
|
|
Messages.error('Error', {}, detail.error);
|
2016-08-31 06:03:41 +00:00
|
|
|
} else {
|
|
|
|
createContainer(config);
|
|
|
|
}
|
2016-07-06 00:19:09 +00:00
|
|
|
}, function (e) {
|
2016-07-07 00:44:58 +00:00
|
|
|
$('#createContainerSpinner').hide();
|
2016-09-02 05:40:03 +00:00
|
|
|
Messages.error('Failure', e, 'Unable to pull image');
|
2016-07-06 00:19:09 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-07-08 03:31:09 +00:00
|
|
|
function createImageConfig(imageName, registry) {
|
|
|
|
var imageNameAndTag = imageName.split(':');
|
|
|
|
var image = imageNameAndTag[0];
|
|
|
|
if (registry) {
|
|
|
|
image = registry + '/' + imageNameAndTag[0];
|
|
|
|
}
|
|
|
|
var imageConfig = {
|
|
|
|
fromImage: image,
|
|
|
|
tag: imageNameAndTag[1] ? imageNameAndTag[1] : 'latest'
|
|
|
|
};
|
|
|
|
return imageConfig;
|
|
|
|
}
|
|
|
|
|
|
|
|
function prepareImageConfig(config) {
|
|
|
|
var image = _.toLower(config.Image);
|
|
|
|
var registry = $scope.formValues.Registry;
|
|
|
|
var imageConfig = createImageConfig(image, registry);
|
|
|
|
config.Image = imageConfig.fromImage + ':' + imageConfig.tag;
|
|
|
|
$scope.imageConfig = imageConfig;
|
|
|
|
}
|
|
|
|
|
2016-07-06 00:19:09 +00:00
|
|
|
function preparePortBindings(config) {
|
|
|
|
var bindings = {};
|
|
|
|
config.HostConfig.PortBindings.forEach(function (portBinding) {
|
2016-10-07 05:08:07 +00:00
|
|
|
if (portBinding.containerPort) {
|
2016-07-06 00:19:09 +00:00
|
|
|
var key = portBinding.containerPort + "/" + portBinding.protocol;
|
2016-08-17 07:31:06 +00:00
|
|
|
var binding = {};
|
2016-10-07 05:08:07 +00:00
|
|
|
if (portBinding.hostPort && portBinding.hostPort.indexOf(':') > -1) {
|
2016-08-17 07:31:06 +00:00
|
|
|
var hostAndPort = portBinding.hostPort.split(':');
|
|
|
|
binding.HostIp = hostAndPort[0];
|
|
|
|
binding.HostPort = hostAndPort[1];
|
|
|
|
} else {
|
|
|
|
binding.HostPort = portBinding.hostPort;
|
|
|
|
}
|
|
|
|
bindings[key] = [binding];
|
2016-08-17 07:03:36 +00:00
|
|
|
config.ExposedPorts[key] = {};
|
2016-07-06 00:19:09 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
config.HostConfig.PortBindings = bindings;
|
|
|
|
}
|
|
|
|
|
|
|
|
function prepareConsole(config) {
|
|
|
|
var value = $scope.formValues.Console;
|
|
|
|
var openStdin = true;
|
|
|
|
var tty = true;
|
|
|
|
if (value === 'tty') {
|
|
|
|
openStdin = false;
|
|
|
|
} else if (value === 'interactive') {
|
|
|
|
tty = false;
|
|
|
|
} else if (value === 'none') {
|
|
|
|
openStdin = false;
|
|
|
|
tty = false;
|
|
|
|
}
|
|
|
|
config.OpenStdin = openStdin;
|
|
|
|
config.Tty = tty;
|
|
|
|
}
|
|
|
|
|
|
|
|
function prepareEnvironmentVariables(config) {
|
|
|
|
var env = [];
|
|
|
|
config.Env.forEach(function (v) {
|
|
|
|
if (v.name && v.value) {
|
|
|
|
env.push(v.name + "=" + v.value);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
config.Env = env;
|
|
|
|
}
|
|
|
|
|
|
|
|
function prepareVolumes(config) {
|
|
|
|
var binds = [];
|
|
|
|
var volumes = {};
|
|
|
|
|
|
|
|
$scope.formValues.Volumes.forEach(function (volume) {
|
|
|
|
var name = volume.name;
|
|
|
|
var containerPath = volume.containerPath;
|
|
|
|
if (name && containerPath) {
|
|
|
|
var bind = name + ':' + containerPath;
|
|
|
|
volumes[containerPath] = {};
|
|
|
|
if (volume.readOnly) {
|
|
|
|
bind += ':ro';
|
|
|
|
}
|
|
|
|
binds.push(bind);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
config.HostConfig.Binds = binds;
|
|
|
|
config.Volumes = volumes;
|
|
|
|
}
|
|
|
|
|
|
|
|
function prepareConfiguration() {
|
|
|
|
var config = angular.copy($scope.config);
|
2016-07-08 03:31:09 +00:00
|
|
|
prepareImageConfig(config);
|
2016-07-06 00:19:09 +00:00
|
|
|
preparePortBindings(config);
|
|
|
|
prepareConsole(config);
|
|
|
|
prepareEnvironmentVariables(config);
|
|
|
|
prepareVolumes(config);
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
|
|
|
|
$scope.create = function () {
|
|
|
|
var config = prepareConfiguration();
|
2016-08-31 06:03:41 +00:00
|
|
|
$('#createContainerSpinner').show();
|
2016-10-20 03:43:09 +00:00
|
|
|
if ($scope.formValues.alwaysPull) {
|
2016-07-06 00:19:09 +00:00
|
|
|
pullImageAndCreateContainer(config);
|
|
|
|
} else {
|
|
|
|
createContainer(config);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}]);
|