chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,634 @@
|
||||
import _ from 'lodash-es';
|
||||
|
||||
import * as envVarsUtils from '@/react/components/form-components/EnvironmentVariablesFieldset/utils';
|
||||
import { PorImageRegistryModel } from '@/docker/models/porImageRegistry';
|
||||
import { AccessControlFormData } from '../../../../portainer/components/accessControlForm/porAccessControlFormModel';
|
||||
|
||||
require('./includes/update-restart.html');
|
||||
require('./includes/secret.html');
|
||||
require('./includes/config.html');
|
||||
require('./includes/resources-placement.html');
|
||||
|
||||
angular.module('portainer.docker').controller('CreateServiceController', [
|
||||
'$q',
|
||||
'$scope',
|
||||
'$state',
|
||||
'$timeout',
|
||||
'ServiceService',
|
||||
'ServiceHelper',
|
||||
'ConfigService',
|
||||
'ConfigHelper',
|
||||
'SecretHelper',
|
||||
'SecretService',
|
||||
'VolumeService',
|
||||
'NetworkService',
|
||||
'ImageHelper',
|
||||
'LabelHelper',
|
||||
'Authentication',
|
||||
'ResourceControlService',
|
||||
'Notifications',
|
||||
'FormValidator',
|
||||
'PluginService',
|
||||
'NodeService',
|
||||
'WebhookService',
|
||||
'endpoint',
|
||||
function (
|
||||
$q,
|
||||
$scope,
|
||||
$state,
|
||||
$timeout,
|
||||
ServiceService,
|
||||
ServiceHelper,
|
||||
ConfigService,
|
||||
ConfigHelper,
|
||||
SecretHelper,
|
||||
SecretService,
|
||||
VolumeService,
|
||||
NetworkService,
|
||||
ImageHelper,
|
||||
LabelHelper,
|
||||
Authentication,
|
||||
ResourceControlService,
|
||||
Notifications,
|
||||
FormValidator,
|
||||
PluginService,
|
||||
NodeService,
|
||||
WebhookService,
|
||||
endpoint
|
||||
) {
|
||||
$scope.endpoint = endpoint;
|
||||
|
||||
$scope.formValues = {
|
||||
Name: '',
|
||||
RegistryModel: new PorImageRegistryModel(),
|
||||
Mode: 'replicated',
|
||||
Replicas: 1,
|
||||
Command: '',
|
||||
EntryPoint: '',
|
||||
WorkingDir: '',
|
||||
User: '',
|
||||
Env: [],
|
||||
Labels: [],
|
||||
ContainerLabels: [],
|
||||
Volumes: [],
|
||||
Network: '',
|
||||
ExtraNetworks: [],
|
||||
HostsEntries: [],
|
||||
Ports: [],
|
||||
Parallelism: 1,
|
||||
PlacementConstraints: [],
|
||||
PlacementPreferences: [],
|
||||
UpdateDelay: '0s',
|
||||
UpdateOrder: 'stop-first',
|
||||
FailureAction: 'pause',
|
||||
Secrets: [],
|
||||
Configs: [],
|
||||
AccessControlData: new AccessControlFormData(),
|
||||
CpuLimit: 0,
|
||||
CpuReservation: 0,
|
||||
MemoryLimit: 0,
|
||||
MemoryReservation: 0,
|
||||
MemoryLimitUnit: 'MB',
|
||||
MemoryReservationUnit: 'MB',
|
||||
RestartCondition: 'any',
|
||||
RestartDelay: '5s',
|
||||
RestartMaxAttempts: 0,
|
||||
RestartWindow: '0s',
|
||||
LogDriverName: '',
|
||||
LogDriverOpts: [],
|
||||
Webhook: false,
|
||||
};
|
||||
|
||||
$scope.state = {
|
||||
formValidationError: '',
|
||||
actionInProgress: false,
|
||||
pullImageValidity: false,
|
||||
};
|
||||
|
||||
$scope.allowBindMounts = false;
|
||||
|
||||
$scope.handleWebHookChange = handleWebHookChange;
|
||||
|
||||
function handleWebHookChange(checked) {
|
||||
return $scope.$evalAsync(() => {
|
||||
$scope.formValues.Webhook = checked;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.handleEnvVarChange = handleEnvVarChange;
|
||||
function handleEnvVarChange(value) {
|
||||
$scope.formValues.Env = value;
|
||||
}
|
||||
|
||||
$scope.refreshSlider = function () {
|
||||
$timeout(function () {
|
||||
$scope.$broadcast('rzSliderForceRender');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.setPullImageValidity = setPullImageValidity;
|
||||
function setPullImageValidity(validity) {
|
||||
$scope.state.pullImageValidity = validity;
|
||||
}
|
||||
|
||||
$scope.addPortBinding = function () {
|
||||
$scope.formValues.Ports.push({ PublishedPort: '', TargetPort: '', Protocol: 'tcp', PublishMode: 'ingress' });
|
||||
};
|
||||
|
||||
$scope.removePortBinding = function (index) {
|
||||
$scope.formValues.Ports.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.addExtraNetwork = function () {
|
||||
$scope.formValues.ExtraNetworks.push({ Name: '' });
|
||||
};
|
||||
|
||||
$scope.removeExtraNetwork = function (index) {
|
||||
$scope.formValues.ExtraNetworks.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.addHostsEntry = function () {
|
||||
$scope.formValues.HostsEntries.push({});
|
||||
};
|
||||
|
||||
$scope.removeHostsEntry = function (index) {
|
||||
$scope.formValues.HostsEntries.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.addVolume = function () {
|
||||
$scope.formValues.Volumes.push({ Source: null, Target: '', ReadOnly: false, Type: 'volume' });
|
||||
};
|
||||
|
||||
$scope.removeVolume = function (index) {
|
||||
$scope.formValues.Volumes.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.addConfig = function () {
|
||||
$scope.formValues.Configs.push({});
|
||||
};
|
||||
|
||||
$scope.removeConfig = function (index) {
|
||||
$scope.formValues.Configs.splice(index, 1);
|
||||
$scope.checkIfConfigDuplicated();
|
||||
};
|
||||
|
||||
$scope.addSecret = function () {
|
||||
$scope.formValues.Secrets.push({ overrideTarget: false });
|
||||
};
|
||||
|
||||
$scope.removeSecret = function (index) {
|
||||
$scope.formValues.Secrets.splice(index, 1);
|
||||
$scope.checkIfSecretDuplicated();
|
||||
};
|
||||
|
||||
$scope.addPlacementConstraint = function () {
|
||||
$scope.formValues.PlacementConstraints.push({ key: '', operator: '==', value: '' });
|
||||
};
|
||||
|
||||
$scope.removePlacementConstraint = function (index) {
|
||||
$scope.formValues.PlacementConstraints.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.addPlacementPreference = function () {
|
||||
$scope.formValues.PlacementPreferences.push({ strategy: 'spread', value: '' });
|
||||
};
|
||||
|
||||
$scope.removePlacementPreference = function (index) {
|
||||
$scope.formValues.PlacementPreferences.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.addLabel = function () {
|
||||
$scope.formValues.Labels.push({ key: '', value: '' });
|
||||
};
|
||||
|
||||
$scope.removeLabel = function (index) {
|
||||
$scope.formValues.Labels.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.addContainerLabel = function () {
|
||||
$scope.formValues.ContainerLabels.push({ key: '', value: '' });
|
||||
};
|
||||
|
||||
$scope.removeContainerLabel = function (index) {
|
||||
$scope.formValues.ContainerLabels.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.addLogDriverOpt = function () {
|
||||
$scope.formValues.LogDriverOpts.push({ name: '', value: '' });
|
||||
};
|
||||
|
||||
$scope.removeLogDriverOpt = function (index) {
|
||||
$scope.formValues.LogDriverOpts.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.checkIfSecretDuplicated = function () {
|
||||
$scope.formValues.Secrets.$invalid = false;
|
||||
[...$scope.formValues.Secrets]
|
||||
.sort((a, b) => a.model.Id.localeCompare(b.model.Id))
|
||||
.sort((a, b) => {
|
||||
if (a.model.Id === b.model.Id) {
|
||||
$scope.formValues.Secrets.$invalid = true;
|
||||
$scope.formValues.Secrets.$error = 'Secret ' + a.model.Name + ' cannot be assigned multiple times.';
|
||||
}
|
||||
});
|
||||
if (!$scope.formValues.Secrets.$invalid) {
|
||||
$scope.formValues.Secrets.$error = '';
|
||||
}
|
||||
};
|
||||
|
||||
$scope.checkIfConfigDuplicated = function () {
|
||||
$scope.formValues.Configs.$invalid = false;
|
||||
[...$scope.formValues.Configs]
|
||||
.sort((a, b) => a.model.Id.localeCompare(b.model.Id))
|
||||
.sort((a, b) => {
|
||||
if (a.model.Id === b.model.Id) {
|
||||
$scope.formValues.Configs.$invalid = true;
|
||||
$scope.formValues.Configs.$error = 'Config ' + a.model.Name + ' cannot be assigned multiple times.';
|
||||
}
|
||||
});
|
||||
if (!$scope.formValues.Configs.$invalid) {
|
||||
$scope.formValues.Configs.$error = '';
|
||||
}
|
||||
};
|
||||
|
||||
function prepareImageConfig(config, input) {
|
||||
var imageConfig = ImageHelper.createImageConfigForContainer(input.RegistryModel);
|
||||
config.TaskTemplate.ContainerSpec.Image = imageConfig.fromImage;
|
||||
}
|
||||
|
||||
function preparePortsConfig(config, input) {
|
||||
let ports = [];
|
||||
input.Ports.forEach(function (binding) {
|
||||
const port = {
|
||||
Protocol: binding.Protocol,
|
||||
PublishMode: binding.PublishMode,
|
||||
};
|
||||
if (binding.TargetPort) {
|
||||
port.TargetPort = +binding.TargetPort;
|
||||
if (binding.PublishedPort) {
|
||||
port.PublishedPort = +binding.PublishedPort;
|
||||
}
|
||||
ports.push(port);
|
||||
}
|
||||
});
|
||||
config.EndpointSpec.Ports = ports;
|
||||
}
|
||||
|
||||
function prepareSchedulingConfig(config, input) {
|
||||
if (input.Mode === 'replicated') {
|
||||
config.Mode.Replicated = {
|
||||
Replicas: input.Replicas,
|
||||
};
|
||||
} else {
|
||||
config.Mode.Global = {};
|
||||
}
|
||||
}
|
||||
|
||||
function commandToArray(cmd) {
|
||||
var tokens = [].concat
|
||||
.apply(
|
||||
[],
|
||||
cmd.split("'").map(function (v, i) {
|
||||
return i % 2 ? v : v.split(' ');
|
||||
})
|
||||
)
|
||||
.filter(Boolean);
|
||||
return tokens;
|
||||
}
|
||||
|
||||
function prepareCommandConfig(config, input) {
|
||||
if (input.EntryPoint) {
|
||||
config.TaskTemplate.ContainerSpec.Command = commandToArray(input.EntryPoint);
|
||||
}
|
||||
if (input.Command) {
|
||||
config.TaskTemplate.ContainerSpec.Args = commandToArray(input.Command);
|
||||
}
|
||||
if (input.User) {
|
||||
config.TaskTemplate.ContainerSpec.User = input.User;
|
||||
}
|
||||
if (input.WorkingDir) {
|
||||
config.TaskTemplate.ContainerSpec.Dir = input.WorkingDir;
|
||||
}
|
||||
}
|
||||
|
||||
function prepareEnvConfig(config, input) {
|
||||
config.TaskTemplate.ContainerSpec.Env = envVarsUtils.convertToArrayOfStrings(input.Env);
|
||||
}
|
||||
|
||||
function prepareLabelsConfig(config, input) {
|
||||
config.Labels = LabelHelper.fromKeyValueToLabelHash(input.Labels);
|
||||
config.TaskTemplate.ContainerSpec.Labels = LabelHelper.fromKeyValueToLabelHash(input.ContainerLabels);
|
||||
}
|
||||
|
||||
function createMountObjectFromVolume(volumeObject, target, readonly) {
|
||||
return {
|
||||
Target: target,
|
||||
Source: volumeObject.Id,
|
||||
Type: 'volume',
|
||||
ReadOnly: readonly,
|
||||
VolumeOptions: {
|
||||
Labels: volumeObject.Labels,
|
||||
DriverConfig: {
|
||||
Name: volumeObject.Driver,
|
||||
Options: volumeObject.Options,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function prepareVolumes(config, input) {
|
||||
input.Volumes.forEach(function (volume) {
|
||||
if (volume.Source && volume.Target) {
|
||||
if (volume.Type !== 'volume') {
|
||||
config.TaskTemplate.ContainerSpec.Mounts.push(volume);
|
||||
} else {
|
||||
var volumeObject = volume.Source;
|
||||
var mount = createMountObjectFromVolume(volumeObject, volume.Target, volume.ReadOnly);
|
||||
config.TaskTemplate.ContainerSpec.Mounts.push(mount);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function prepareNetworks(config, input) {
|
||||
var networks = [];
|
||||
if (input.Network) {
|
||||
networks.push({ Target: input.Network });
|
||||
}
|
||||
input.ExtraNetworks.forEach(function (network) {
|
||||
networks.push({ Target: network.Name });
|
||||
});
|
||||
config.TaskTemplate.Networks = _.uniqWith(networks, _.isEqual);
|
||||
}
|
||||
|
||||
function prepareHostsEntries(config, input) {
|
||||
var hostsEntries = [];
|
||||
if (input.HostsEntries) {
|
||||
input.HostsEntries.forEach(function (host_ip) {
|
||||
if (host_ip.value && host_ip.value.indexOf(':') && host_ip.value.split(':').length === 2) {
|
||||
var keyVal = host_ip.value.split(':');
|
||||
// Hosts file format, IP_address canonical_hostname
|
||||
hostsEntries.push(keyVal[1] + ' ' + keyVal[0]);
|
||||
}
|
||||
});
|
||||
if (hostsEntries.length > 0) {
|
||||
config.TaskTemplate.ContainerSpec.Hosts = hostsEntries;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function prepareUpdateConfig(config, input) {
|
||||
config.UpdateConfig = {
|
||||
Parallelism: input.Parallelism || 0,
|
||||
Delay: ServiceHelper.translateHumanDurationToNanos(input.UpdateDelay) || 0,
|
||||
FailureAction: input.FailureAction,
|
||||
Order: input.UpdateOrder,
|
||||
};
|
||||
}
|
||||
|
||||
function prepareRestartPolicy(config, input) {
|
||||
config.TaskTemplate.RestartPolicy = {
|
||||
Condition: input.RestartCondition || 'any',
|
||||
Delay: ServiceHelper.translateHumanDurationToNanos(input.RestartDelay) || 5000000000,
|
||||
MaxAttempts: input.RestartMaxAttempts || 0,
|
||||
Window: ServiceHelper.translateHumanDurationToNanos(input.RestartWindow) || 0,
|
||||
};
|
||||
}
|
||||
|
||||
function preparePlacementConfig(config, input) {
|
||||
config.TaskTemplate.Placement.Constraints = ServiceHelper.translateKeyValueToPlacementConstraints(input.PlacementConstraints);
|
||||
config.TaskTemplate.Placement.Preferences = ServiceHelper.translateKeyValueToPlacementPreferences(input.PlacementPreferences);
|
||||
}
|
||||
|
||||
function prepareConfigConfig(config, input) {
|
||||
if (input.Configs) {
|
||||
var configs = [];
|
||||
angular.forEach(input.Configs, function (config) {
|
||||
if (config.model) {
|
||||
var s = ConfigHelper.configConfig(config.model);
|
||||
s.File.Name = config.FileName || s.File.Name;
|
||||
configs.push(s);
|
||||
}
|
||||
});
|
||||
config.TaskTemplate.ContainerSpec.Configs = configs;
|
||||
}
|
||||
}
|
||||
|
||||
function prepareSecretConfig(config, input) {
|
||||
if (input.Secrets) {
|
||||
var secrets = [];
|
||||
angular.forEach(input.Secrets, function (secret) {
|
||||
if (secret.model) {
|
||||
var s = SecretHelper.secretConfig(secret.model);
|
||||
s.File.Name = s.SecretName;
|
||||
if (secret.overrideTarget && secret.target && secret.target !== '') {
|
||||
s.File.Name = secret.target;
|
||||
}
|
||||
secrets.push(s);
|
||||
}
|
||||
});
|
||||
config.TaskTemplate.ContainerSpec.Secrets = secrets;
|
||||
}
|
||||
}
|
||||
|
||||
function prepareResourcesCpuConfig(config, input) {
|
||||
// CPU Limit
|
||||
if (input.CpuLimit > 0) {
|
||||
config.TaskTemplate.Resources.Limits.NanoCPUs = input.CpuLimit * 1000000000;
|
||||
}
|
||||
// CPU Reservation
|
||||
if (input.CpuReservation > 0) {
|
||||
config.TaskTemplate.Resources.Reservations.NanoCPUs = input.CpuReservation * 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
function prepareResourcesMemoryConfig(config, input) {
|
||||
// Memory Limit - Round to 0.125
|
||||
var memoryLimit = (Math.round(input.MemoryLimit * 8) / 8).toFixed(3);
|
||||
memoryLimit *= 1024 * 1024;
|
||||
if (input.MemoryLimitUnit === 'GB') {
|
||||
memoryLimit *= 1024;
|
||||
}
|
||||
if (memoryLimit > 0) {
|
||||
config.TaskTemplate.Resources.Limits.MemoryBytes = memoryLimit;
|
||||
}
|
||||
// Memory Resevation - Round to 0.125
|
||||
var memoryReservation = (Math.round(input.MemoryReservation * 8) / 8).toFixed(3);
|
||||
memoryReservation *= 1024 * 1024;
|
||||
if (input.MemoryReservationUnit === 'GB') {
|
||||
memoryReservation *= 1024;
|
||||
}
|
||||
if (memoryReservation > 0) {
|
||||
config.TaskTemplate.Resources.Reservations.MemoryBytes = memoryReservation;
|
||||
}
|
||||
}
|
||||
|
||||
function prepareLogDriverConfig(config, input) {
|
||||
var logOpts = {};
|
||||
if (input.LogDriverName) {
|
||||
config.TaskTemplate.LogDriver = { Name: input.LogDriverName };
|
||||
if (input.LogDriverName !== 'none') {
|
||||
input.LogDriverOpts.forEach(function (opt) {
|
||||
if (opt.name) {
|
||||
logOpts[opt.name] = opt.value;
|
||||
}
|
||||
});
|
||||
if (Object.keys(logOpts).length !== 0 && logOpts.constructor === Object) {
|
||||
config.TaskTemplate.LogDriver.Options = logOpts;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function prepareConfiguration() {
|
||||
var input = $scope.formValues;
|
||||
var config = {
|
||||
Name: input.Name,
|
||||
TaskTemplate: {
|
||||
ContainerSpec: {
|
||||
Mounts: [],
|
||||
},
|
||||
Placement: {},
|
||||
Resources: {
|
||||
Limits: {},
|
||||
Reservations: {},
|
||||
},
|
||||
},
|
||||
Mode: {},
|
||||
EndpointSpec: {},
|
||||
};
|
||||
prepareSchedulingConfig(config, input);
|
||||
prepareImageConfig(config, input);
|
||||
preparePortsConfig(config, input);
|
||||
prepareCommandConfig(config, input);
|
||||
prepareEnvConfig(config, input);
|
||||
prepareLabelsConfig(config, input);
|
||||
prepareVolumes(config, input);
|
||||
prepareNetworks(config, input);
|
||||
prepareHostsEntries(config, input);
|
||||
prepareUpdateConfig(config, input);
|
||||
prepareConfigConfig(config, input);
|
||||
prepareSecretConfig(config, input);
|
||||
preparePlacementConfig(config, input);
|
||||
prepareResourcesCpuConfig(config, input);
|
||||
prepareResourcesMemoryConfig(config, input);
|
||||
prepareRestartPolicy(config, input);
|
||||
prepareLogDriverConfig(config, input);
|
||||
return config;
|
||||
}
|
||||
|
||||
function createNewService(config, accessControlData) {
|
||||
const registryModel = $scope.formValues.RegistryModel;
|
||||
|
||||
ServiceService.create(config, registryModel.Registry.Authentication ? registryModel.Registry.Id : 0)
|
||||
.then(function success(data) {
|
||||
const serviceId = data.ID;
|
||||
const resourceControl = data.Portainer.ResourceControl;
|
||||
const userId = Authentication.getUserDetails().ID;
|
||||
const rcPromise = ResourceControlService.applyResourceControl(userId, accessControlData, resourceControl);
|
||||
const registryID = $scope.formValues.RegistryModel.Registry.Id;
|
||||
const webhookPromise = $q.when(endpoint.Type !== 4 && $scope.formValues.Webhook && WebhookService.createServiceWebhook(serviceId, endpoint.Id, registryID));
|
||||
return $q.all([rcPromise, webhookPromise]);
|
||||
})
|
||||
.then(function success() {
|
||||
Notifications.success('Success', 'Service successfully created');
|
||||
$state.go('docker.services', {}, { reload: true });
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to create service');
|
||||
})
|
||||
.finally(function final() {
|
||||
$scope.state.actionInProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
function validateForm(accessControlData, isAdmin) {
|
||||
$scope.state.formValidationError = '';
|
||||
var error = FormValidator.validateAccessControl(accessControlData, isAdmin) || $scope.formValues.Secrets.$error || $scope.formValues.Configs.$error;
|
||||
|
||||
if (error) {
|
||||
$scope.state.formValidationError = error;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$scope.volumesAreValid = volumesAreValid;
|
||||
function volumesAreValid() {
|
||||
const volumes = $scope.formValues.Volumes;
|
||||
return volumes.every((volume) => volume.Target && volume.Source);
|
||||
}
|
||||
|
||||
$scope.create = function createService() {
|
||||
var accessControlData = $scope.formValues.AccessControlData;
|
||||
|
||||
if (!validateForm(accessControlData, $scope.isAdmin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.state.actionInProgress = true;
|
||||
var config = prepareConfiguration();
|
||||
createNewService(config, accessControlData);
|
||||
};
|
||||
|
||||
function initSlidersMaxValuesBasedOnNodeData(nodes) {
|
||||
var maxCpus = 0;
|
||||
var maxMemory = 0;
|
||||
for (var n in nodes) {
|
||||
if (nodes[n].CPUs && nodes[n].CPUs > maxCpus) {
|
||||
maxCpus = nodes[n].CPUs;
|
||||
}
|
||||
if (nodes[n].Memory && nodes[n].Memory > maxMemory) {
|
||||
maxMemory = nodes[n].Memory;
|
||||
}
|
||||
}
|
||||
if (maxCpus > 0) {
|
||||
$scope.state.sliderMaxCpu = maxCpus / 1000000000;
|
||||
} else {
|
||||
$scope.state.sliderMaxCpu = 32;
|
||||
}
|
||||
if (maxMemory > 0) {
|
||||
$scope.state.sliderMaxMemory = Math.floor(maxMemory / 1000 / 1000);
|
||||
} else {
|
||||
$scope.state.sliderMaxMemory = 32768;
|
||||
}
|
||||
}
|
||||
|
||||
function initView() {
|
||||
var apiVersion = $scope.applicationState.endpoint.apiVersion;
|
||||
|
||||
$q.all({
|
||||
volumes: VolumeService.volumes(),
|
||||
networks: NetworkService.networks(true, true, false),
|
||||
secrets: apiVersion >= 1.25 ? SecretService.secrets() : [],
|
||||
configs: apiVersion >= 1.3 ? ConfigService.configs(endpoint.Id) : [],
|
||||
nodes: NodeService.nodes(),
|
||||
availableLoggingDrivers: PluginService.loggingPlugins(apiVersion < 1.25),
|
||||
allowBindMounts: checkIfAllowedBindMounts(),
|
||||
})
|
||||
.then(function success(data) {
|
||||
$scope.availableVolumes = data.volumes;
|
||||
$scope.availableNetworks = data.networks;
|
||||
$scope.availableSecrets = data.secrets;
|
||||
$scope.availableConfigs = data.configs;
|
||||
$scope.availableLoggingDrivers = data.availableLoggingDrivers;
|
||||
initSlidersMaxValuesBasedOnNodeData(data.nodes);
|
||||
$scope.isAdmin = Authentication.isAdmin();
|
||||
$scope.allowBindMounts = data.allowBindMounts;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to initialize view');
|
||||
});
|
||||
}
|
||||
|
||||
initView();
|
||||
|
||||
async function checkIfAllowedBindMounts() {
|
||||
const isAdmin = Authentication.isAdmin();
|
||||
|
||||
const { allowBindMountsForRegularUsers } = endpoint.SecuritySettings;
|
||||
|
||||
return isAdmin || allowBindMountsForRegularUsers;
|
||||
}
|
||||
},
|
||||
]);
|
||||
Reference in New Issue
Block a user