mirror of https://github.com/portainer/portainer
feat(app): push pull container creation
parent
e00185a160
commit
fd3187abc8
|
@ -2,8 +2,7 @@ angular.module('portainer.docker').component('porImageRegistry', {
|
|||
templateUrl: './porImageRegistry.html',
|
||||
controller: 'porImageRegistryController',
|
||||
bindings: {
|
||||
'image': '=',
|
||||
'registry': '=',
|
||||
'model': '=', // must be of type PorImageRegistryModel
|
||||
'autoComplete': '<',
|
||||
'labelClass': '@',
|
||||
'inputClass': '@'
|
||||
|
|
|
@ -4,37 +4,39 @@
|
|||
Use registry
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input type="checkbox" ng-model="$ctrl.useRegistry"><i></i>
|
||||
<input type="checkbox" ng-model="$ctrl.model.UseRegistry"><i></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- use registry -->
|
||||
<div ng-if="$ctrl.useRegistry">
|
||||
<div ng-if="$ctrl.model.UseRegistry">
|
||||
<div class="form-group">
|
||||
<label for="image_name" ng-class="$ctrl.labelClass" class="control-label text-left">Image</label>
|
||||
<div ng-class="$ctrl.inputClass">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="registry-name">{{$ctrl.registry.URL}}</span>
|
||||
<span class="input-group-addon" id="registry-name">{{$ctrl.model.Registry.URL}}</span>
|
||||
<input type="text" class="form-control" aria-describedby="registry-name" uib-typeahead="image for image in $ctrl.availableImages | filter:$viewValue | limitTo:5"
|
||||
ng-model="$ctrl.image" name="image_name" placeholder="e.g. myImage:myTag" required>
|
||||
ng-model="$ctrl.model.Image" name="image_name" placeholder="e.g. myImage:myTag" required>
|
||||
</div>
|
||||
</div>
|
||||
<label for="image_registry" class="margin-sm-top control-label text-right" ng-class="$ctrl.labelClass">
|
||||
Registry
|
||||
</label>
|
||||
<div ng-class="$ctrl.inputClass" class="margin-sm-top">
|
||||
<select ng-options="registry as registry.Name for registry in $ctrl.availableRegistries" ng-model="$ctrl.registry" id="image_registry"
|
||||
<select ng-options="registry as registry.Name for registry in $ctrl.availableRegistries" ng-model="$ctrl.model.Registry" id="image_registry"
|
||||
class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ! use registry -->
|
||||
<!-- don't use registry -->
|
||||
<div ng-if="!$ctrl.useRegistry">
|
||||
<div ng-if="!$ctrl.model.UseRegistry">
|
||||
<div class="form-group">
|
||||
<label for="image_name" ng-class="$ctrl.labelClass" class="control-label text-left">Image</label>
|
||||
<label for="image_name" ng-class="$ctrl.labelClass" class="control-label text-left">Image
|
||||
<portainer-tooltip position="bottom" message="Image and repository should be publicly available."></portainer-tooltip>
|
||||
</label>
|
||||
<div ng-class="$ctrl.inputClass">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.image" name="image_name" placeholder="e.g. registry:port/myImage:myTag" required>
|
||||
<input type="text" class="form-control" ng-model="$ctrl.model.Image" name="image_name" placeholder="e.g. registry:port/myImage:myTag" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,10 +20,12 @@ class porImageRegistryController {
|
|||
this.autoComplete ? this.ImageService.images() : []]);
|
||||
this.availableImages = this.ImageService.getUniqueTagListFromImages(availableImages);
|
||||
this.availableRegistries = [dockerhub].concat(registries);
|
||||
if (!this.registry.Id) {
|
||||
this.registry = dockerhub;
|
||||
|
||||
const id = this.model.Registry.Id;
|
||||
if (!id) {
|
||||
this.model.Registry = dockerhub;
|
||||
} else {
|
||||
this.registry = _.find(this.availableRegistries, { 'Id': this.registry.Id });
|
||||
this.model.Registry = _.find(this.availableRegistries, { 'Id': id });
|
||||
}
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to retrieve registries');
|
||||
|
@ -31,7 +33,6 @@ class porImageRegistryController {
|
|||
}
|
||||
|
||||
$onInit() {
|
||||
this.useRegistry = true;
|
||||
return this.$async(this.onInit);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// import _ from 'lodash-es';
|
||||
import _ from 'lodash-es';
|
||||
|
||||
angular.module('portainer.docker')
|
||||
.factory('ImageHelper', [function ImageHelperFactory() {
|
||||
|
@ -7,6 +7,7 @@ angular.module('portainer.docker')
|
|||
var helper = {};
|
||||
|
||||
helper.isValidTag = isValidTag;
|
||||
helper.createImageConfigForContainer = createImageConfigForContainer;
|
||||
|
||||
function isValidTag(tag) {
|
||||
return tag.match(/^(?![\.\-])([a-zA-Z0-9\_\.\-])+$/g);
|
||||
|
@ -42,13 +43,30 @@ angular.module('portainer.docker')
|
|||
};
|
||||
};
|
||||
|
||||
helper.createImageConfigForContainer = function (imageName, registry) {
|
||||
void registry;
|
||||
console.log(imageName);
|
||||
return {
|
||||
fromImage: imageName
|
||||
/**
|
||||
*
|
||||
* @param {PorImageRegistryModel} registry
|
||||
*/
|
||||
function createImageConfigForContainer(registry) {
|
||||
console.log('registry', registry);
|
||||
const data = {
|
||||
fromImage: ''
|
||||
};
|
||||
let fullImageName = '';
|
||||
|
||||
if (registry.UseRegistry) {
|
||||
fullImageName = registry.Registry.URL + '/' + registry.Image;
|
||||
if (!_.includes(registry.Image, ':')) {
|
||||
fullImageName += ':latest';
|
||||
}
|
||||
} else {
|
||||
fullImageName = registry.Image;
|
||||
}
|
||||
};
|
||||
|
||||
data.fromImage = fullImageName;
|
||||
console.log('FULL IMAGE NAME', fullImageName);
|
||||
return data;
|
||||
}
|
||||
|
||||
helper.removeDigestFromRepository = function(repository) {
|
||||
return repository.split('@sha')[0];
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* This model should be used with por-image-registry component
|
||||
* And bound to the 'model' attribute
|
||||
*
|
||||
* // viewController.js
|
||||
*
|
||||
* this.imageModel = new PorImageRegistryModel();
|
||||
*
|
||||
* // view.html
|
||||
* <por-image-registry model="$ctrl.imageModel" ... />
|
||||
*/
|
||||
export function PorImageRegistryModel() {
|
||||
this.UseRegistry = true;
|
||||
this.Registry = {};
|
||||
this.Image = '';
|
||||
}
|
|
@ -25,7 +25,8 @@ function ImageFactory($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider, HttpR
|
|||
ignoreLoadingBar: true
|
||||
},
|
||||
create: {
|
||||
method: 'POST', params: {action: 'create', fromImage: '@fromImage', tag: '@tag'},
|
||||
// method: 'POST', params: {action: 'create', fromImage: '@fromImage', tag: '@tag'},
|
||||
method: 'POST', params: {action: 'create', fromImage: '@fromImage'},
|
||||
isArray: true, transformResponse: jsonObjectsToArrayHandler,
|
||||
headers: { 'X-Registry-Auth': HttpRequestHelper.registryAuthenticationHeader },
|
||||
ignoreLoadingBar: true
|
||||
|
|
|
@ -108,7 +108,6 @@ function ContainerServiceFactory($q, Container, ResourceControlService, LogHelpe
|
|||
service.createAndStartContainer = function(configuration) {
|
||||
var deferred = $q.defer();
|
||||
var container;
|
||||
console.log(configuration);
|
||||
service.createContainer(configuration)
|
||||
.then(function success(data) {
|
||||
container = data;
|
||||
|
|
|
@ -127,19 +127,26 @@ angular.module('portainer.docker')
|
|||
return deferred.promise;
|
||||
}
|
||||
|
||||
service.pullImage = function(image, registry, ignoreErrors) {
|
||||
service.pullImage = pullImage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PorImageRegistryModel} registry
|
||||
* @param {bool} ignoreErrors
|
||||
*/
|
||||
function pullImage(registry, ignoreErrors) {
|
||||
// var imageDetails = ImageHelper.extractImageAndRegistryFromRepository(image);
|
||||
// var imageConfiguration = ImageHelper.createImageConfigForContainer(imageDetails.image, registry.URL);
|
||||
var authenticationDetails = registry.Authentication ? RegistryService.encodedCredentials(registry) : '';
|
||||
var authenticationDetails = registry.Registry.Authentication ? RegistryService.encodedCredentials(registry.Registry) : '';
|
||||
HttpRequestHelper.setRegistryAuthenticationHeader(authenticationDetails);
|
||||
|
||||
var imageConfiguration = ImageHelper.createImageConfigForContainer(image, registry.URL);
|
||||
var imageConfiguration = ImageHelper.createImageConfigForContainer(registry);
|
||||
|
||||
if (ignoreErrors) {
|
||||
return pullImageAndIgnoreErrors(imageConfiguration);
|
||||
}
|
||||
return pullImageAndAcknowledgeErrors(imageConfiguration);
|
||||
};
|
||||
}
|
||||
|
||||
service.tagImage = function(id, image, registry) {
|
||||
void registry;
|
||||
|
|
|
@ -2,6 +2,7 @@ import _ from 'lodash-es';
|
|||
import { ContainerCapabilities, ContainerCapability } from '../../../models/containerCapabilities';
|
||||
import { AccessControlFormData } from '../../../../portainer/components/accessControlForm/porAccessControlFormModel';
|
||||
import { ContainerDetailsViewModel } from '../../../models/container';
|
||||
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
|
||||
|
||||
|
||||
angular.module('portainer.docker')
|
||||
|
@ -27,7 +28,8 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
|
|||
NodeName: null,
|
||||
capabilities: [],
|
||||
LogDriverName: '',
|
||||
LogDriverOpts: []
|
||||
LogDriverOpts: [],
|
||||
RegistryModel: new PorImageRegistryModel()
|
||||
};
|
||||
|
||||
$scope.extraNetworks = {};
|
||||
|
@ -129,11 +131,10 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
|
|||
|
||||
$scope.fromContainerMultipleNetworks = false;
|
||||
|
||||
// TODO
|
||||
function prepareImageConfig(config) {
|
||||
var image = config.Image;
|
||||
var registry = $scope.formValues.Registry;
|
||||
var imageConfig = ImageHelper.createImageConfigForContainer(image, registry.URL);
|
||||
config.Image = imageConfig.fromImage ;//+ ':' + imageConfig.tag;
|
||||
const imageConfig = ImageHelper.createImageConfigForContainer($scope.formValues.RegistryModel);
|
||||
config.Image = imageConfig.fromImage;
|
||||
}
|
||||
|
||||
function preparePortBindings(config) {
|
||||
|
@ -295,7 +296,6 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
|
|||
config.Cmd = ContainerHelper.commandStringToArray(config.Cmd);
|
||||
prepareNetworkConfig(config);
|
||||
prepareImageConfig(config);
|
||||
console.log(config);
|
||||
preparePortBindings(config);
|
||||
prepareConsole(config);
|
||||
prepareEnvironmentVariables(config);
|
||||
|
@ -436,13 +436,14 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
|
|||
$scope.config.HostConfig.Devices = path;
|
||||
}
|
||||
|
||||
// TODO
|
||||
function loadFromContainerImageConfig() {
|
||||
var imageInfo = ImageHelper.extractImageAndRegistryFromRepository($scope.config.Image);
|
||||
RegistryService.retrieveRegistryFromRepository($scope.config.Image)
|
||||
.then(function success(data) {
|
||||
if (data) {
|
||||
$scope.config.Image = imageInfo.image;
|
||||
$scope.formValues.Registry = data;
|
||||
$scope.formValues.RegistryModel = data;
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
|
@ -568,7 +569,6 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
|
|||
loadFromContainerSpec();
|
||||
} else {
|
||||
$scope.fromContainer = {};
|
||||
$scope.formValues.Registry = {};
|
||||
$scope.formValues.capabilities = new ContainerCapabilities();
|
||||
}
|
||||
}, function(e) {
|
||||
|
@ -753,7 +753,7 @@ function ($q, $scope, $async, $state, $timeout, $transition$, $filter, Container
|
|||
|
||||
function pullImageIfNeeded() {
|
||||
return $q.when($scope.formValues.alwaysPull &&
|
||||
ImageService.pullImage($scope.config.Image, $scope.formValues.Registry, true));
|
||||
ImageService.pullImage($scope.formValues.RegistryModel, true));
|
||||
}
|
||||
|
||||
function createNewContainer() {
|
||||
|
|
|
@ -21,16 +21,15 @@
|
|||
<div class="col-sm-12 form-section-title">
|
||||
Image configuration
|
||||
</div>
|
||||
<div ng-if="!formValues.Registry && fromContainer">
|
||||
<div ng-if="!formValues.RegistryModel.Registry && fromContainer">
|
||||
<i class="fa fa-exclamation-triangle orange-icon" aria-hidden="true"></i>
|
||||
<span class="small text-danger" style="margin-left: 5px;">The Docker registry for the <code>{{ config.Image }}</code> image is not registered inside Portainer, you will not be able to create a container. Please register that registry first.</span>
|
||||
</div>
|
||||
<div ng-if="formValues.Registry || !fromContainer">
|
||||
<div ng-if="formValues.RegistryModel.Registry || !fromContainer">
|
||||
<!-- image-and-registry -->
|
||||
<por-image-registry
|
||||
image="config.Image"
|
||||
registry="formValues.Registry"
|
||||
ng-if="formValues.Registry"
|
||||
model="formValues.RegistryModel"
|
||||
ng-if="formValues.RegistryModel.Registry"
|
||||
auto-complete="true"
|
||||
label-class="col-sm-1" input-class="col-sm-11 col-md-5"
|
||||
></por-image-registry>
|
||||
|
@ -142,7 +141,9 @@
|
|||
<!-- !autoremove -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-disabled="state.actionInProgress || !config.Image || (!formValues.Registry && fromContainer)" ng-click="create()" button-spinner="state.actionInProgress">
|
||||
<button type="button" class="btn btn-primary btn-sm"
|
||||
ng-disabled="state.actionInProgress || !formValues.RegistryModel.Image || (!formValues.RegistryModel.Registry && fromContainer)"
|
||||
ng-click="create()" button-spinner="state.actionInProgress">
|
||||
<span ng-hide="state.actionInProgress">Deploy the container</span>
|
||||
<span ng-show="state.actionInProgress">Deployment in progress...</span>
|
||||
</button>
|
||||
|
|
|
@ -155,8 +155,7 @@
|
|||
<!-- !tag-description -->
|
||||
<!-- image-and-registry -->
|
||||
<por-image-registry
|
||||
image="config.Image"
|
||||
registry="config.Registry"
|
||||
model="config.RegistryModel"
|
||||
auto-complete="true"
|
||||
label-class="col-sm-1" input-class="col-sm-11 col-md-5"
|
||||
></por-image-registry>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import moment from 'moment';
|
||||
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
|
||||
|
||||
angular.module('portainer.docker')
|
||||
.controller('ContainerController', ['$q', '$scope', '$state','$transition$', '$filter', 'Commit', 'ContainerHelper', 'ContainerService', 'ImageHelper', 'NetworkService', 'Notifications', 'ModalService', 'ResourceControlService', 'RegistryService', 'ImageService', 'HttpRequestHelper', 'Authentication',
|
||||
|
@ -7,8 +8,7 @@ function ($q, $scope, $state, $transition$, $filter, Commit, ContainerHelper, Co
|
|||
$scope.portBindings = [];
|
||||
|
||||
$scope.config = {
|
||||
Image: '',
|
||||
Registry: ''
|
||||
RegistryModel: new PorImageRegistryModel()
|
||||
};
|
||||
|
||||
$scope.state = {
|
||||
|
@ -149,6 +149,7 @@ function ($q, $scope, $state, $transition$, $filter, Commit, ContainerHelper, Co
|
|||
});
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
$scope.commit = function () {
|
||||
const image = $scope.config.Image;
|
||||
$scope.config.Image = '';
|
||||
|
@ -223,15 +224,12 @@ function ($q, $scope, $state, $transition$, $filter, Commit, ContainerHelper, Co
|
|||
if (!pullImage) {
|
||||
return $q.when();
|
||||
}
|
||||
return getRegistry().then(function pullImage(containerRegistery) {
|
||||
return ImageService.pullImage(container.Config.Image, containerRegistery, true);
|
||||
return RegistryService.retrieveRegistryFromRepository(container.Config.Image)
|
||||
.then(function pullImage(containerRegistry) {
|
||||
return ImageService.pullImage(containerRegistry, true);
|
||||
});
|
||||
}
|
||||
|
||||
function getRegistry() {
|
||||
return RegistryService.retrieveRegistryFromRepository(container.Config.Image);
|
||||
}
|
||||
|
||||
function setMainNetworkAndCreateContainer() {
|
||||
var networks = config.NetworkingConfig.EndpointsConfig;
|
||||
var networksNames = Object.keys(networks);
|
||||
|
|
|
@ -64,8 +64,7 @@
|
|||
<form class="form-horizontal">
|
||||
<!-- image-and-registry -->
|
||||
<por-image-registry
|
||||
image="formValues.Image"
|
||||
registry="formValues.Registry"
|
||||
model="formValues.RegistryModel"
|
||||
label-class="col-sm-1" input-class="col-sm-11 col-md-5"
|
||||
></por-image-registry>
|
||||
<!-- !image-and-registry -->
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import _ from 'lodash-es';
|
||||
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
|
||||
|
||||
angular.module('portainer.docker')
|
||||
.controller('ImageController', ['$q', '$scope', '$transition$', '$state', '$timeout', 'ImageService', 'RegistryService', 'Notifications', 'HttpRequestHelper', 'ModalService', 'FileSaver', 'Blob',
|
||||
function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryService, Notifications, HttpRequestHelper, ModalService, FileSaver, Blob) {
|
||||
$scope.formValues = {
|
||||
Image: '',
|
||||
Registry: ''
|
||||
RegistryModel: new PorImageRegistryModel()
|
||||
};
|
||||
|
||||
$scope.state = {
|
||||
|
@ -26,6 +26,7 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
|
|||
$('#layer-command-'+layerId+'-full').toggle();
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
$scope.tagImage = function() {
|
||||
var image = $scope.formValues.Image;
|
||||
var registry = $scope.formValues.Registry;
|
||||
|
@ -40,6 +41,7 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
|
|||
});
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
$scope.pushTag = function(repository) {
|
||||
$('#uploadResourceHint').show();
|
||||
RegistryService.retrieveRegistryFromRepository(repository)
|
||||
|
@ -58,12 +60,13 @@ function ($q, $scope, $transition$, $state, $timeout, ImageService, RegistryServ
|
|||
});
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
$scope.pullTag = function(repository) {
|
||||
$('#downloadResourceHint').show();
|
||||
RegistryService.retrieveRegistryFromRepository(repository)
|
||||
.then(function success(data) {
|
||||
var registry = data;
|
||||
return ImageService.pullImage(repository, registry, false);
|
||||
return ImageService.pullImage(registry, false);
|
||||
})
|
||||
.then(function success() {
|
||||
Notifications.success('Image successfully pulled', repository);
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
<form class="form-horizontal">
|
||||
<!-- image-and-registry -->
|
||||
<por-image-registry
|
||||
image="formValues.Image"
|
||||
registry="formValues.Registry"
|
||||
model="formValues.RegistryModel"
|
||||
label-class="col-sm-1" input-class="col-sm-11 col-md-5"
|
||||
></por-image-registry>
|
||||
<!-- !image-and-registry -->
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import _ from 'lodash-es';
|
||||
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
|
||||
|
||||
angular.module('portainer.docker')
|
||||
.controller('ImagesController', ['$scope', '$state', 'ImageService', 'Notifications', 'ModalService', 'HttpRequestHelper', 'FileSaver', 'Blob', 'EndpointProvider',
|
||||
|
@ -9,22 +10,21 @@ function ($scope, $state, ImageService, Notifications, ModalService, HttpRequest
|
|||
};
|
||||
|
||||
$scope.formValues = {
|
||||
Image: '',
|
||||
Registry: '',
|
||||
RegistryModel: new PorImageRegistryModel(),
|
||||
NodeName: null
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
$scope.pullImage = function() {
|
||||
var image = $scope.formValues.Image;
|
||||
var registry = $scope.formValues.Registry;
|
||||
const registryModel = $scope.formValues.RegistryModel;
|
||||
|
||||
var nodeName = $scope.formValues.NodeName;
|
||||
HttpRequestHelper.setPortainerAgentTargetHeader(nodeName);
|
||||
|
||||
$scope.state.actionInProgress = true;
|
||||
ImageService.pullImage(image, registry, false)
|
||||
ImageService.pullImage(registryModel, false)
|
||||
.then(function success() {
|
||||
Notifications.success('Image successfully pulled', image);
|
||||
Notifications.success('Image successfully pulled', registryModel.Image);
|
||||
$state.reload();
|
||||
})
|
||||
.catch(function error(err) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import _ from 'lodash-es';
|
||||
import { AccessControlFormData } from '../../../../portainer/components/accessControlForm/porAccessControlFormModel';
|
||||
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
|
||||
|
||||
require('./includes/update-restart.html')
|
||||
require('./includes/secret.html')
|
||||
|
@ -12,8 +13,7 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
|
|||
|
||||
$scope.formValues = {
|
||||
Name: '',
|
||||
Image: '',
|
||||
Registry: {},
|
||||
RegistryModel: new PorImageRegistryModel(),
|
||||
Mode: 'replicated',
|
||||
Replicas: 1,
|
||||
Command: '',
|
||||
|
@ -159,9 +159,10 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
|
|||
$scope.formValues.LogDriverOpts.splice(index, 1);
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
function prepareImageConfig(config, input) {
|
||||
var imageConfig = ImageHelper.createImageConfigForContainer(input.Image, input.Registry.URL);
|
||||
config.TaskTemplate.ContainerSpec.Image = imageConfig.fromImage + ':' + imageConfig.tag;
|
||||
var imageConfig = ImageHelper.createImageConfigForContainer(input.RegistryModel);
|
||||
config.TaskTemplate.ContainerSpec.Image = imageConfig.fromImage;
|
||||
}
|
||||
|
||||
function preparePortsConfig(config, input) {
|
||||
|
@ -426,6 +427,7 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
|
|||
return config;
|
||||
}
|
||||
|
||||
// TODO CHANGE
|
||||
function createNewService(config, accessControlData) {
|
||||
|
||||
var registry = $scope.formValues.Registry;
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
</div>
|
||||
<!-- image-and-registry -->
|
||||
<por-image-registry
|
||||
image="formValues.Image"
|
||||
registry="formValues.Registry"
|
||||
model="formValues.RegistryModel"
|
||||
auto-complete="true"
|
||||
label-class="col-sm-1" input-class="col-sm-11 col-md-5"
|
||||
></por-image-registry>
|
||||
|
|
|
@ -1,58 +1,6 @@
|
|||
angular.module('portainer.app').component('templateForm', {
|
||||
templateUrl: './templateForm.html',
|
||||
controller: function() {
|
||||
this.state = {
|
||||
collapseTemplate: false,
|
||||
collapseContainer: false,
|
||||
collapseStack: false,
|
||||
collapseEnv: false
|
||||
};
|
||||
|
||||
this.addPortBinding = function() {
|
||||
this.model.Ports.push({ containerPort: '', protocol: 'tcp' });
|
||||
};
|
||||
|
||||
this.removePortBinding = function(index) {
|
||||
this.model.Ports.splice(index, 1);
|
||||
};
|
||||
|
||||
this.addVolume = function () {
|
||||
this.model.Volumes.push({ container: '', bind: '', readonly: false, type: 'auto' });
|
||||
};
|
||||
|
||||
this.removeVolume = function(index) {
|
||||
this.model.Volumes.splice(index, 1);
|
||||
};
|
||||
|
||||
this.addLabel = function () {
|
||||
this.model.Labels.push({ name: '', value: ''});
|
||||
};
|
||||
|
||||
this.removeLabel = function(index) {
|
||||
this.model.Labels.splice(index, 1);
|
||||
};
|
||||
|
||||
this.addEnvVar = function() {
|
||||
this.model.Env.push({ type: 1, name: '', label: '', description: '', default: '', preset: true, select: [] });
|
||||
};
|
||||
|
||||
this.removeEnvVar = function(index) {
|
||||
this.model.Env.splice(index, 1);
|
||||
};
|
||||
|
||||
this.addEnvVarValue = function(env) {
|
||||
env.select = env.select || [];
|
||||
env.select.push({ name: '', value: '' });
|
||||
};
|
||||
|
||||
this.removeEnvVarValue = function(env, index) {
|
||||
env.select.splice(index, 1);
|
||||
};
|
||||
|
||||
this.changeEnvVarType = function(env) {
|
||||
env.preset = env.type === 1;
|
||||
};
|
||||
},
|
||||
controller: 'TemplateFormController',
|
||||
bindings: {
|
||||
model: '=',
|
||||
categories: '<',
|
||||
|
|
|
@ -203,10 +203,9 @@
|
|||
<!-- container-details -->
|
||||
<div uib-collapse="$ctrl.state.collapseContainer">
|
||||
<por-image-registry
|
||||
image="$ctrl.model.Image"
|
||||
registry="$ctrl.model.Registry"
|
||||
model="$ctrl.model.RegistryModel"
|
||||
auto-complete="true"
|
||||
label-class="col-sm-2" input-class="col-sm-10 col-md-4"
|
||||
label-class="col-sm-1" input-class="col-sm-11 col-md-5"
|
||||
></por-image-registry>
|
||||
<!-- command -->
|
||||
<div class="form-group">
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
angular.module('portainer.app')
|
||||
.controller('TemplateFormController', [function() {
|
||||
this.state = {
|
||||
collapseTemplate: false,
|
||||
collapseContainer: false,
|
||||
collapseStack: false,
|
||||
collapseEnv: false
|
||||
};
|
||||
|
||||
this.addPortBinding = function() {
|
||||
this.model.Ports.push({ containerPort: '', protocol: 'tcp' });
|
||||
};
|
||||
|
||||
this.removePortBinding = function(index) {
|
||||
this.model.Ports.splice(index, 1);
|
||||
};
|
||||
|
||||
this.addVolume = function () {
|
||||
this.model.Volumes.push({ container: '', bind: '', readonly: false, type: 'auto' });
|
||||
};
|
||||
|
||||
this.removeVolume = function(index) {
|
||||
this.model.Volumes.splice(index, 1);
|
||||
};
|
||||
|
||||
this.addLabel = function () {
|
||||
this.model.Labels.push({ name: '', value: ''});
|
||||
};
|
||||
|
||||
this.removeLabel = function(index) {
|
||||
this.model.Labels.splice(index, 1);
|
||||
};
|
||||
|
||||
this.addEnvVar = function() {
|
||||
this.model.Env.push({ type: 1, name: '', label: '', description: '', default: '', preset: true, select: [] });
|
||||
};
|
||||
|
||||
this.removeEnvVar = function(index) {
|
||||
this.model.Env.splice(index, 1);
|
||||
};
|
||||
|
||||
this.addEnvVarValue = function(env) {
|
||||
env.select = env.select || [];
|
||||
env.select.push({ name: '', value: '' });
|
||||
};
|
||||
|
||||
this.removeEnvVarValue = function(env, index) {
|
||||
env.select.splice(index, 1);
|
||||
};
|
||||
|
||||
this.changeEnvVarType = function(env) {
|
||||
env.preset = env.type === 1;
|
||||
};
|
||||
}]);
|
|
@ -1,19 +1,20 @@
|
|||
import _ from 'lodash-es';
|
||||
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
|
||||
|
||||
export function TemplateDefaultModel() {
|
||||
this.Type = 1;
|
||||
this.AdministratorOnly = false;
|
||||
this.Title = '';
|
||||
this.Image = '';
|
||||
this.Description = '';
|
||||
this.Volumes = [];
|
||||
this.Ports = [];
|
||||
this.Env = [];
|
||||
this.Labels = [];
|
||||
this.RestartPolicy = 'always';
|
||||
this.Registry = {};
|
||||
this.RegistryModel = new PorImageRegistryModel();
|
||||
}
|
||||
|
||||
// TODO CHANGE
|
||||
export function TemplateCreateRequest(model) {
|
||||
this.Type = model.Type;
|
||||
this.Name = model.Name;
|
||||
|
@ -24,8 +25,8 @@ export function TemplateCreateRequest(model) {
|
|||
this.Categories = model.Categories;
|
||||
this.Platform = model.Platform;
|
||||
this.Logo = model.Logo;
|
||||
this.Image = model.Image;
|
||||
this.Registry = model.Registry.URL;
|
||||
this.Image = model.RegistryModel.Image;
|
||||
this.Registry = model.RegistryModel.Registry.URL;
|
||||
this.Command = model.Command;
|
||||
this.Network = model.Network && model.Network.Name;
|
||||
this.Privileged = model.Privileged;
|
||||
|
@ -53,6 +54,7 @@ export function TemplateUpdateRequest(model) {
|
|||
this.id = model.Id;
|
||||
}
|
||||
|
||||
// TODO CHANGE
|
||||
export function TemplateViewModel(data) {
|
||||
this.Id = data.Id;
|
||||
this.Title = data.title;
|
||||
|
@ -66,9 +68,9 @@ export function TemplateViewModel(data) {
|
|||
this.Logo = data.logo;
|
||||
this.Repository = data.repository;
|
||||
this.Hostname = data.hostname;
|
||||
this.Registry = data.registry ? { URL: data.registry } : {};
|
||||
this.Image = data.image;
|
||||
this.Registry = data.registry ? data.registry : '';
|
||||
this.Registry = data.registry ? { URL: data.registry } : {}; // CHANGE
|
||||
this.Image = data.image; // CHANGE
|
||||
this.Registry = data.registry ? data.registry : ''; // CHANGE
|
||||
this.Command = data.command ? data.command : '';
|
||||
this.Network = data.network ? data.network : '';
|
||||
this.Privileged = data.privileged ? data.privileged : false;
|
||||
|
|
|
@ -81,6 +81,7 @@ angular.module('portainer.app')
|
|||
|
||||
service.retrieveRegistryFromRepository = function(repository) {
|
||||
var deferred = $q.defer();
|
||||
console.log('registry', repository);
|
||||
|
||||
var imageDetails = ImageHelper.extractImageAndRegistryFromRepository(repository);
|
||||
$q.when(imageDetails.registry ? service.registries() : DockerHubService.dockerhub())
|
||||
|
|
|
@ -10,6 +10,7 @@ function TemplateServiceFactory($q, Templates, TemplateHelper, ImageHelper, Cont
|
|||
'use strict';
|
||||
var service = {};
|
||||
|
||||
// TODO CHANGE
|
||||
service.templates = function() {
|
||||
var deferred = $q.defer();
|
||||
|
||||
|
@ -27,6 +28,7 @@ function TemplateServiceFactory($q, Templates, TemplateHelper, ImageHelper, Cont
|
|||
return deferred.promise;
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
service.template = function(id) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
|
@ -47,18 +49,20 @@ function TemplateServiceFactory($q, Templates, TemplateHelper, ImageHelper, Cont
|
|||
return Templates.remove({ id: id }).$promise;
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
service.create = function(model) {
|
||||
var payload = new TemplateCreateRequest(model);
|
||||
return Templates.create(payload).$promise;
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
service.update = function(model) {
|
||||
var payload = new TemplateUpdateRequest(model);
|
||||
return Templates.update(payload).$promise;
|
||||
};
|
||||
|
||||
service.createTemplateConfiguration = function(template, containerName, network) {
|
||||
var imageConfiguration = ImageHelper.createImageConfigForContainer(template.Image, template.Registry);
|
||||
var imageConfiguration = ImageHelper.createImageConfigForContainer(template.RegistryModel);
|
||||
var containerConfiguration = service.createContainerConfiguration(template, containerName, network);
|
||||
containerConfiguration.Image = imageConfiguration.fromImage + ':' + imageConfiguration.tag;
|
||||
return containerConfiguration;
|
||||
|
|
|
@ -8,6 +8,7 @@ function ($q, $scope, $state, $transition$, TemplateService, TemplateHelper, Net
|
|||
actionInProgress: false
|
||||
};
|
||||
|
||||
// TODO CHANGE
|
||||
$scope.update = function() {
|
||||
var model = $scope.template;
|
||||
|
||||
|
|
Loading…
Reference in New Issue