2017-03-12 16:24:15 +00:00
|
|
|
// @@OLD_SERVICE_CONTROLLER: this service should be rewritten to use services.
|
|
|
|
// See app/components/templates/templatesController.js as a reference.
|
2016-07-06 00:19:09 +00:00
|
|
|
angular.module('createContainer', [])
|
2017-08-11 07:46:55 +00:00
|
|
|
.controller('CreateContainerController', ['$q', '$scope', '$state', '$stateParams', '$filter', 'Container', 'ContainerHelper', 'Image', 'ImageHelper', 'Volume', 'NetworkService', 'ResourceControlService', 'Authentication', 'Notifications', 'ContainerService', 'ImageService', 'FormValidator',
|
|
|
|
function ($q, $scope, $state, $stateParams, $filter, Container, ContainerHelper, Image, ImageHelper, Volume, NetworkService, ResourceControlService, Authentication, Notifications, ContainerService, ImageService, FormValidator) {
|
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-27 06:55:44 +00:00
|
|
|
Volumes: [],
|
2016-11-16 01:52:05 +00:00
|
|
|
Registry: '',
|
2016-12-25 20:33:14 +00:00
|
|
|
NetworkContainer: '',
|
2017-02-15 21:48:40 +00:00
|
|
|
Labels: [],
|
2017-04-25 20:32:27 +00:00
|
|
|
ExtraHosts: [],
|
|
|
|
IPv4: '',
|
2017-07-12 07:51:51 +00:00
|
|
|
IPv6: '',
|
|
|
|
AccessControlData: new AccessControlFormData()
|
2016-07-06 00:19:09 +00:00
|
|
|
};
|
|
|
|
|
2017-05-23 18:56:10 +00:00
|
|
|
$scope.state = {
|
|
|
|
formValidationError: ''
|
|
|
|
};
|
2016-07-08 03:40:13 +00:00
|
|
|
|
2016-07-06 00:19:09 +00:00
|
|
|
$scope.config = {
|
2016-10-27 06:55:44 +00:00
|
|
|
Image: '',
|
|
|
|
Env: [],
|
2017-02-10 05:21:07 +00:00
|
|
|
Cmd: '',
|
2016-08-17 07:03:36 +00:00
|
|
|
ExposedPorts: {},
|
2016-07-06 00:19:09 +00:00
|
|
|
HostConfig: {
|
|
|
|
RestartPolicy: {
|
|
|
|
Name: 'no'
|
|
|
|
},
|
2016-10-27 06:55:44 +00:00
|
|
|
PortBindings: [],
|
2017-02-11 23:23:13 +00:00
|
|
|
PublishAllPorts: false,
|
2016-07-06 00:19:09 +00:00
|
|
|
Binds: [],
|
|
|
|
NetworkMode: 'bridge',
|
2017-02-15 21:48:40 +00:00
|
|
|
Privileged: false,
|
2017-04-16 07:57:47 +00:00
|
|
|
ExtraHosts: [],
|
|
|
|
Devices:[]
|
2016-12-25 20:33:14 +00:00
|
|
|
},
|
2017-04-25 20:32:27 +00:00
|
|
|
NetworkingConfig: {
|
|
|
|
EndpointsConfig: {}
|
|
|
|
},
|
2016-12-25 20:33:14 +00:00
|
|
|
Labels: {}
|
2016-07-06 00:19:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
$scope.addVolume = function() {
|
2017-03-27 12:44:39 +00:00
|
|
|
$scope.formValues.Volumes.push({ name: '', containerPath: '', readOnly: false, type: 'volume' });
|
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);
|
|
|
|
};
|
|
|
|
|
2016-12-25 20:33:14 +00:00
|
|
|
$scope.addLabel = function() {
|
|
|
|
$scope.formValues.Labels.push({ name: '', value: ''});
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.removeLabel = function(index) {
|
|
|
|
$scope.formValues.Labels.splice(index, 1);
|
|
|
|
};
|
|
|
|
|
2017-02-15 21:48:40 +00:00
|
|
|
$scope.addExtraHost = function() {
|
|
|
|
$scope.formValues.ExtraHosts.push({ value: '' });
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.removeExtraHost = function(index) {
|
|
|
|
$scope.formValues.ExtraHosts.splice(index, 1);
|
|
|
|
};
|
2017-05-23 18:56:10 +00:00
|
|
|
|
2017-04-16 07:57:47 +00:00
|
|
|
$scope.addDevice = function() {
|
|
|
|
$scope.config.HostConfig.Devices.push({ pathOnHost: '', pathInContainer: '' });
|
|
|
|
};
|
2017-02-15 21:48:40 +00:00
|
|
|
|
2017-04-16 07:57:47 +00:00
|
|
|
$scope.removeDevice = function(index) {
|
|
|
|
$scope.config.HostConfig.Devices.splice(index, 1);
|
|
|
|
};
|
2017-02-15 21:48:40 +00:00
|
|
|
|
2016-07-08 03:31:09 +00:00
|
|
|
function prepareImageConfig(config) {
|
2016-12-31 00:25:42 +00:00
|
|
|
var image = config.Image;
|
2016-07-08 03:31:09 +00:00
|
|
|
var registry = $scope.formValues.Registry;
|
2017-06-20 11:00:32 +00:00
|
|
|
var imageConfig = ImageHelper.createImageConfigForContainer(image, registry.URL);
|
2016-07-08 03:31:09 +00:00
|
|
|
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) {
|
2017-05-23 18:56:10 +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) {
|
2017-05-23 18:56:10 +00:00
|
|
|
env.push(v.name + '=' + v.value);
|
2016-07-06 00:19:09 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-11-16 01:52:05 +00:00
|
|
|
function prepareNetworkConfig(config) {
|
|
|
|
var mode = config.HostConfig.NetworkMode;
|
|
|
|
var container = $scope.formValues.NetworkContainer;
|
|
|
|
var containerName = container;
|
|
|
|
if (container && typeof container === 'object') {
|
|
|
|
containerName = $filter('trimcontainername')(container.Names[0]);
|
2017-01-22 23:14:34 +00:00
|
|
|
if ($scope.applicationState.endpoint.mode.provider === 'DOCKER_SWARM') {
|
2016-11-16 01:52:05 +00:00
|
|
|
containerName = $filter('swarmcontainername')(container);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var networkMode = mode;
|
|
|
|
if (containerName) {
|
|
|
|
networkMode += ':' + containerName;
|
|
|
|
}
|
|
|
|
config.HostConfig.NetworkMode = networkMode;
|
2017-03-12 16:24:15 +00:00
|
|
|
|
2017-04-25 20:32:27 +00:00
|
|
|
config.NetworkingConfig.EndpointsConfig[networkMode] = {
|
|
|
|
IPAMConfig: {
|
|
|
|
IPv4Address: $scope.formValues.IPv4,
|
|
|
|
IPv6Address: $scope.formValues.IPv6
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-02-15 21:48:40 +00:00
|
|
|
$scope.formValues.ExtraHosts.forEach(function (v) {
|
|
|
|
if (v.value) {
|
|
|
|
config.HostConfig.ExtraHosts.push(v.value);
|
|
|
|
}
|
|
|
|
});
|
2016-11-16 01:52:05 +00:00
|
|
|
}
|
|
|
|
|
2016-12-25 20:33:14 +00:00
|
|
|
function prepareLabels(config) {
|
|
|
|
var labels = {};
|
|
|
|
$scope.formValues.Labels.forEach(function (label) {
|
|
|
|
if (label.name && label.value) {
|
|
|
|
labels[label.name] = label.value;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
config.Labels = labels;
|
|
|
|
}
|
2017-05-23 18:56:10 +00:00
|
|
|
|
2017-04-16 07:57:47 +00:00
|
|
|
function prepareDevices(config) {
|
|
|
|
var path = [];
|
|
|
|
config.HostConfig.Devices.forEach(function (p) {
|
|
|
|
if (p.pathOnHost) {
|
|
|
|
if(p.pathInContainer === '') {
|
|
|
|
p.pathInContainer = p.pathOnHost;
|
|
|
|
}
|
2017-05-23 18:56:10 +00:00
|
|
|
path.push({PathOnHost:p.pathOnHost,PathInContainer:p.pathInContainer,CgroupPermissions:'rwm'});
|
2017-04-16 07:57:47 +00:00
|
|
|
}
|
|
|
|
});
|
2017-05-23 18:56:10 +00:00
|
|
|
config.HostConfig.Devices = path;
|
2017-04-16 07:57:47 +00:00
|
|
|
}
|
2016-12-25 20:33:14 +00:00
|
|
|
|
2016-07-06 00:19:09 +00:00
|
|
|
function prepareConfiguration() {
|
|
|
|
var config = angular.copy($scope.config);
|
2017-02-10 05:21:07 +00:00
|
|
|
config.Cmd = ContainerHelper.commandStringToArray(config.Cmd);
|
2016-11-16 01:52:05 +00:00
|
|
|
prepareNetworkConfig(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);
|
2016-12-25 20:33:14 +00:00
|
|
|
prepareLabels(config);
|
2017-04-16 07:57:47 +00:00
|
|
|
prepareDevices(config);
|
2016-07-06 00:19:09 +00:00
|
|
|
return config;
|
|
|
|
}
|
|
|
|
|
2017-05-23 18:56:10 +00:00
|
|
|
function initView() {
|
2017-06-01 08:14:55 +00:00
|
|
|
Volume.query({}, function (d) {
|
|
|
|
$scope.availableVolumes = d.Volumes;
|
|
|
|
}, function (e) {
|
|
|
|
Notifications.error('Failure', e, 'Unable to retrieve volumes');
|
2017-05-23 18:56:10 +00:00
|
|
|
});
|
2017-06-01 08:14:55 +00:00
|
|
|
|
2017-08-11 07:46:55 +00:00
|
|
|
var provider = $scope.applicationState.endpoint.mode.provider;
|
|
|
|
var apiVersion = $scope.applicationState.endpoint.apiVersion;
|
|
|
|
NetworkService.networks(
|
|
|
|
provider === 'DOCKER_STANDALONE' || provider === 'DOCKER_SWARM_MODE',
|
|
|
|
false,
|
|
|
|
provider === 'DOCKER_SWARM_MODE' && apiVersion >= 1.25,
|
|
|
|
provider === 'DOCKER_SWARM'
|
|
|
|
)
|
|
|
|
.then(function success(data) {
|
|
|
|
var networks = data;
|
|
|
|
networks.push({ Name: 'container' });
|
2017-06-01 08:14:55 +00:00
|
|
|
$scope.availableNetworks = networks;
|
2017-08-11 07:46:55 +00:00
|
|
|
|
|
|
|
if (_.find(networks, {'Name': 'nat'})) {
|
2017-06-01 08:14:55 +00:00
|
|
|
$scope.config.HostConfig.NetworkMode = 'nat';
|
|
|
|
}
|
2017-08-11 07:46:55 +00:00
|
|
|
})
|
|
|
|
.catch(function error(err) {
|
|
|
|
Notifications.error('Failure', err, 'Unable to retrieve networks');
|
2017-06-01 08:14:55 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
Container.query({}, function (d) {
|
|
|
|
var containers = d;
|
|
|
|
$scope.runningContainers = containers;
|
|
|
|
}, function(e) {
|
|
|
|
Notifications.error('Failure', e, 'Unable to retrieve running containers');
|
|
|
|
});
|
|
|
|
|
2017-05-23 18:56:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function validateForm(accessControlData, isAdmin) {
|
|
|
|
$scope.state.formValidationError = '';
|
|
|
|
var error = '';
|
|
|
|
error = FormValidator.validateAccessControl(accessControlData, isAdmin);
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
$scope.state.formValidationError = error;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-07-06 00:19:09 +00:00
|
|
|
$scope.create = function () {
|
2016-08-31 06:03:41 +00:00
|
|
|
$('#createContainerSpinner').show();
|
2017-05-23 18:56:10 +00:00
|
|
|
|
2017-07-12 07:51:51 +00:00
|
|
|
var accessControlData = $scope.formValues.AccessControlData;
|
2017-05-23 18:56:10 +00:00
|
|
|
var userDetails = Authentication.getUserDetails();
|
|
|
|
var isAdmin = userDetails.role === 1 ? true : false;
|
|
|
|
|
|
|
|
if (!validateForm(accessControlData, isAdmin)) {
|
|
|
|
$('#createContainerSpinner').hide();
|
|
|
|
return;
|
2016-07-06 00:19:09 +00:00
|
|
|
}
|
2017-05-23 18:56:10 +00:00
|
|
|
|
|
|
|
var config = prepareConfiguration();
|
|
|
|
createContainer(config, accessControlData);
|
2016-07-06 00:19:09 +00:00
|
|
|
};
|
2017-05-23 18:56:10 +00:00
|
|
|
|
|
|
|
function createContainer(config, accessControlData) {
|
2017-06-29 14:05:39 +00:00
|
|
|
$q.when(!$scope.formValues.alwaysPull || ImageService.pullImage($scope.config.Image, $scope.formValues.Registry, true))
|
2017-05-23 18:56:10 +00:00
|
|
|
.finally(function final() {
|
2017-06-05 05:55:18 +00:00
|
|
|
ContainerService.createAndStartContainer(config)
|
|
|
|
.then(function success(data) {
|
|
|
|
var containerIdentifier = data.Id;
|
|
|
|
var userId = Authentication.getUserDetails().ID;
|
|
|
|
return ResourceControlService.applyResourceControl('container', containerIdentifier, userId, accessControlData, []);
|
|
|
|
})
|
|
|
|
.then(function success() {
|
|
|
|
Notifications.success('Container successfully created');
|
|
|
|
$state.go('containers', {}, {reload: true});
|
|
|
|
})
|
|
|
|
.catch(function error(err) {
|
|
|
|
Notifications.error('Failure', err, 'Unable to create container');
|
|
|
|
})
|
|
|
|
.finally(function final() {
|
|
|
|
$('#createContainerSpinner').hide();
|
|
|
|
});
|
2017-05-23 18:56:10 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
initView();
|
2016-07-06 00:19:09 +00:00
|
|
|
}]);
|