* feat(custom-templates): introduce types * feat(custom-templates): introduce data layer service * feat(custom-templates): introduce http handler * feat(custom-templates): create routes and view stubs * feat(custom-templates): add create custom template ui * feat(custom-templates): add json keys * feat(custom-templates): introduce custom templates list page * feat(custom-templates): introduce update page * feat(stack): create template from stack * feat(stacks): create stack from custom template * feat(custom-templates): disable edit/delete of templates * fix(custom-templates): fail update on non admin/owner * fix(custom-templates): add ng-inject decorator * chore(plop): revert template * feat(stacks): remove actions column * feat(stack): add button to create template from stack * feat(stacks): add empty state for templates * feat(custom-templates): show templates in a list * feat(custom-template): replace table with list * feat(custom-templates): move create template button * refactor(custom-templates): introduce more fields * feat(custom-templates): use stack type when creating template * feat(custom-templates): use same type as stack * feat(custom-templates): add edit and delete buttons to template item * feat(custom-templates): customize stack before deploy * feat(stack): show template details * feat(custom-templates): move customize * feat(custom-templates): create description required * fix(template): show platform icon * fix(custom-templates): show spinner when creating stack * feat(custom-templates): prevent user from edit templates * feat(custom-templates): use resource control for custom templates * feat(custom-templates): show created templates * feat(custom-templates): filter templates by stack type * fix(custom-templates): create swarm or standalone stack * feat(stacks): filter templates by type * feat(resource-control): disable resource control on public * feat(custom-template): apply access control on edit * feat(custom-template): add form validation * feat(stack): disable create custom template from external task * refactor(custom-templates): create template from file and type * feat(templates): introduce a file handler that returns template docker file * feat(template): introduce template duplication * feat(custom-template): enforce unique template name * fix(template): rename copy button * fix(custom-template): clear access control selection between templates * fix(custom-templates): show required fields * refactor(filesystem): use a constant for temp path
92 lines
3.9 KiB
JavaScript
92 lines
3.9 KiB
JavaScript
import _ from 'lodash-es';
|
|
import { TemplateViewModel } from '../../models/template';
|
|
|
|
angular.module('portainer.app').factory('TemplateService', [
|
|
'$q',
|
|
'Templates',
|
|
'TemplateHelper',
|
|
'RegistryService',
|
|
'DockerHubService',
|
|
'ImageHelper',
|
|
'ContainerHelper',
|
|
function TemplateServiceFactory($q, Templates, TemplateHelper, RegistryService, DockerHubService, ImageHelper, ContainerHelper) {
|
|
'use strict';
|
|
var service = {};
|
|
|
|
service.templates = function () {
|
|
const deferred = $q.defer();
|
|
|
|
$q.all({
|
|
templates: Templates.query().$promise,
|
|
registries: RegistryService.registries(),
|
|
dockerhub: DockerHubService.dockerhub(),
|
|
})
|
|
.then(function success(data) {
|
|
const version = data.templates.version;
|
|
const templates = _.map(data.templates.templates, (item) => {
|
|
try {
|
|
const template = new TemplateViewModel(item, version);
|
|
const registry = RegistryService.retrievePorRegistryModelFromRepositoryWithRegistries(template.RegistryModel.Registry.URL, data.registries, data.dockerhub);
|
|
registry.Image = template.RegistryModel.Image;
|
|
template.RegistryModel = registry;
|
|
return template;
|
|
} catch (err) {
|
|
deferred.reject({ msg: 'Unable to retrieve templates', err: err });
|
|
}
|
|
});
|
|
deferred.resolve(templates);
|
|
})
|
|
.catch(function error(err) {
|
|
deferred.reject({ msg: 'Unable to retrieve templates', err: err });
|
|
});
|
|
|
|
return deferred.promise;
|
|
};
|
|
|
|
service.templateFile = templateFile;
|
|
function templateFile(repositoryUrl, composeFilePathInRepository) {
|
|
return Templates.file({ repositoryUrl, composeFilePathInRepository }).$promise;
|
|
}
|
|
|
|
service.createTemplateConfiguration = function (template, containerName, network) {
|
|
var imageConfiguration = ImageHelper.createImageConfigForContainer(template.RegistryModel);
|
|
var containerConfiguration = createContainerConfiguration(template, containerName, network);
|
|
containerConfiguration.Image = imageConfiguration.fromImage;
|
|
return containerConfiguration;
|
|
};
|
|
|
|
function createContainerConfiguration(template, containerName, network) {
|
|
var configuration = TemplateHelper.getDefaultContainerConfiguration();
|
|
configuration.HostConfig.NetworkMode = network.Name;
|
|
configuration.HostConfig.Privileged = template.Privileged;
|
|
configuration.HostConfig.RestartPolicy = { Name: template.RestartPolicy };
|
|
configuration.HostConfig.ExtraHosts = template.Hosts ? template.Hosts : [];
|
|
configuration.name = containerName;
|
|
configuration.Hostname = template.Hostname;
|
|
configuration.Env = TemplateHelper.EnvToStringArray(template.Env);
|
|
configuration.Cmd = ContainerHelper.commandStringToArray(template.Command);
|
|
var portConfiguration = TemplateHelper.portArrayToPortConfiguration(template.Ports);
|
|
configuration.HostConfig.PortBindings = portConfiguration.bindings;
|
|
configuration.ExposedPorts = portConfiguration.exposedPorts;
|
|
var consoleConfiguration = TemplateHelper.getConsoleConfiguration(template.Interactive);
|
|
configuration.OpenStdin = consoleConfiguration.openStdin;
|
|
configuration.Tty = consoleConfiguration.tty;
|
|
configuration.Labels = TemplateHelper.updateContainerConfigurationWithLabels(template.Labels);
|
|
return configuration;
|
|
}
|
|
|
|
service.updateContainerConfigurationWithVolumes = function (configuration, template, generatedVolumesPile) {
|
|
var volumes = template.Volumes;
|
|
TemplateHelper.createVolumeBindings(volumes, generatedVolumesPile);
|
|
volumes.forEach(function (volume) {
|
|
if (volume.binding) {
|
|
configuration.Volumes[volume.container] = {};
|
|
configuration.HostConfig.Binds.push(volume.binding);
|
|
}
|
|
});
|
|
};
|
|
|
|
return service;
|
|
},
|
|
]);
|