1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 22:05:23 +02:00

feat(stacks): add the ability to specify env vars when deploying stacks (#1345)

This commit is contained in:
Anthony Lapenna 2017-11-01 10:30:02 +01:00 committed by GitHub
parent 42347d714f
commit 693f1319a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 173 additions and 30 deletions

View file

@ -1,6 +1,6 @@
angular.module('createStack', [])
.controller('CreateStackController', ['$scope', '$state', '$document', 'StackService', 'CodeMirrorService', 'Authentication', 'Notifications', 'FormValidator', 'ResourceControlService',
function ($scope, $state, $document, StackService, CodeMirrorService, Authentication, Notifications, FormValidator, ResourceControlService) {
.controller('CreateStackController', ['$scope', '$state', '$document', 'StackService', 'CodeMirrorService', 'Authentication', 'Notifications', 'FormValidator', 'ResourceControlService', 'FormHelper',
function ($scope, $state, $document, StackService, CodeMirrorService, Authentication, Notifications, FormValidator, ResourceControlService, FormHelper) {
// Store the editor content when switching builder methods
var editorContent = '';
@ -11,6 +11,7 @@ function ($scope, $state, $document, StackService, CodeMirrorService, Authentica
StackFileContent: '# Define or paste the content of your docker-compose file here',
StackFile: null,
RepositoryURL: '',
Env: [],
RepositoryPath: 'docker-compose.yml',
AccessControlData: new AccessControlFormData()
};
@ -20,6 +21,14 @@ function ($scope, $state, $document, StackService, CodeMirrorService, Authentica
formValidationError: ''
};
$scope.addEnvironmentVariable = function() {
$scope.formValues.Env.push({ name: '', value: ''});
};
$scope.removeEnvironmentVariable = function(index) {
$scope.formValues.Env.splice(index, 1);
};
function validateForm(accessControlData, isAdmin) {
$scope.state.formValidationError = '';
var error = '';
@ -34,20 +43,21 @@ function ($scope, $state, $document, StackService, CodeMirrorService, Authentica
function createStack(name) {
var method = $scope.state.Method;
var env = FormHelper.removeInvalidEnvVars($scope.formValues.Env);
if (method === 'editor') {
// The codemirror editor does not work with ng-model so we need to retrieve
// the value directly from the editor.
var stackFileContent = $scope.editor.getValue();
return StackService.createStackFromFileContent(name, stackFileContent);
return StackService.createStackFromFileContent(name, stackFileContent, env);
} else if (method === 'upload') {
var stackFile = $scope.formValues.StackFile;
return StackService.createStackFromFileUpload(name, stackFile);
return StackService.createStackFromFileUpload(name, stackFile, env);
} else if (method === 'repository') {
var gitRepository = $scope.formValues.RepositoryURL;
var pathInRepository = $scope.formValues.RepositoryPath;
return StackService.createStackFromGitRepository(name, gitRepository, pathInRepository);
return StackService.createStackFromGitRepository(name, gitRepository, pathInRepository, env);
}
}

View file

@ -131,6 +131,36 @@
</div>
</div>
</div>
<div class="col-sm-12 form-section-title">
Environment
</div>
<!-- environment-variables -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Environment variables</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addEnvironmentVariable()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add environment variable
</span>
</div>
<!-- environment-variable-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="variable in formValues.Env" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="variable.name" placeholder="e.g. FOO">
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="variable.value" placeholder="e.g. bar">
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeEnvironmentVariable($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
<!-- !environment-variable-input-list -->
</div>
<!-- !environment-variables -->
<!-- !repository -->
<por-access-control-form form-data="formValues.AccessControlData" ng-if="applicationState.application.authentication"></por-access-control-form>
<!-- actions -->

View file

@ -38,6 +38,36 @@
<textarea id="web-editor" class="form-control" ng-model="stackFileContent" placeholder='version: "3"'></textarea>
</div>
</div>
<div class="col-sm-12 form-section-title">
Environment
</div>
<!-- environment-variables -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Environment variables</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addEnvironmentVariable()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add environment variable
</span>
</div>
<!-- environment-variable-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="variable in stack.Env" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="variable.name" placeholder="e.g. FOO">
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="variable.value" placeholder="e.g. bar">
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeEnvironmentVariable($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
<!-- !environment-variable-input-list -->
</div>
<!-- !environment-variables -->
<div class="col-sm-12 form-section-title">
Actions
</div>

View file

@ -1,6 +1,6 @@
angular.module('stack', [])
.controller('StackController', ['$q', '$scope', '$state', '$stateParams', '$document', 'StackService', 'NodeService', 'ServiceService', 'TaskService', 'ServiceHelper', 'CodeMirrorService', 'Notifications',
function ($q, $scope, $state, $stateParams, $document, StackService, NodeService, ServiceService, TaskService, ServiceHelper, CodeMirrorService, Notifications) {
.controller('StackController', ['$q', '$scope', '$state', '$stateParams', '$document', 'StackService', 'NodeService', 'ServiceService', 'TaskService', 'ServiceHelper', 'CodeMirrorService', 'Notifications', 'FormHelper',
function ($q, $scope, $state, $stateParams, $document, StackService, NodeService, ServiceService, TaskService, ServiceHelper, CodeMirrorService, Notifications, FormHelper) {
$scope.deployStack = function () {
$('#createResourceSpinner').show();
@ -8,8 +8,9 @@ function ($q, $scope, $state, $stateParams, $document, StackService, NodeService
// The codemirror editor does not work with ng-model so we need to retrieve
// the value directly from the editor.
var stackFile = $scope.editor.getValue();
var env = FormHelper.removeInvalidEnvVars($scope.stack.Env);
StackService.updateStack($scope.stack.Id, stackFile)
StackService.updateStack($scope.stack.Id, stackFile, env)
.then(function success(data) {
Notifications.success('Stack successfully deployed');
$state.reload();
@ -22,6 +23,14 @@ function ($q, $scope, $state, $stateParams, $document, StackService, NodeService
});
};
$scope.addEnvironmentVariable = function() {
$scope.stack.Env.push({ name: '', value: ''});
};
$scope.removeEnvironmentVariable = function(index) {
$scope.stack.Env.splice(index, 1);
};
function initView() {
$('#loadingViewSpinner').show();
var stackId = $stateParams.id;

18
app/helpers/formHelper.js Normal file
View file

@ -0,0 +1,18 @@
angular.module('portainer.helpers')
.factory('FormHelper', [function FormHelperFactory() {
'use strict';
var helper = {};
helper.removeInvalidEnvVars = function(env) {
for (var i = env.length - 1; i >= 0; i--) {
var envvar = env[i];
if (!envvar.value || !envvar.name) {
env.splice(i, 1);
}
}
return env;
};
return helper;
}]);

View file

@ -2,6 +2,7 @@ function StackViewModel(data) {
this.Id = data.Id;
this.Name = data.Name;
this.Checked = false;
this.Env = data.Env;
if (data.ResourceControl && data.ResourceControl.Id !== 0) {
this.ResourceControl = new ResourceControlViewModel(data.ResourceControl);
}

View file

@ -100,13 +100,19 @@ function StackServiceFactory($q, Stack, ResourceControlService, FileUploadServic
return deferred.promise;
};
service.createStackFromFileContent = function(name, stackFileContent) {
service.createStackFromFileContent = function(name, stackFileContent, env) {
var deferred = $q.defer();
SwarmService.swarm()
.then(function success(data) {
var swarm = data;
return Stack.create({ method: 'string' }, { Name: name, SwarmID: swarm.Id, StackFileContent: stackFileContent }).$promise;
var payload = {
Name: name,
SwarmID: swarm.Id,
StackFileContent: stackFileContent,
Env: env
};
return Stack.create({ method: 'string' }, payload).$promise;
})
.then(function success(data) {
deferred.resolve(data);
@ -118,13 +124,20 @@ function StackServiceFactory($q, Stack, ResourceControlService, FileUploadServic
return deferred.promise;
};
service.createStackFromGitRepository = function(name, gitRepository, pathInRepository) {
service.createStackFromGitRepository = function(name, gitRepository, pathInRepository, env) {
var deferred = $q.defer();
SwarmService.swarm()
.then(function success(data) {
var swarm = data;
return Stack.create({ method: 'repository' }, { Name: name, SwarmID: swarm.Id, GitRepository: gitRepository, PathInRepository: pathInRepository }).$promise;
var payload = {
Name: name,
SwarmID: swarm.Id,
GitRepository: gitRepository,
PathInRepository: pathInRepository,
Env: env
};
return Stack.create({ method: 'repository' }, payload).$promise;
})
.then(function success(data) {
deferred.resolve(data);
@ -136,13 +149,13 @@ function StackServiceFactory($q, Stack, ResourceControlService, FileUploadServic
return deferred.promise;
};
service.createStackFromFileUpload = function(name, stackFile) {
service.createStackFromFileUpload = function(name, stackFile, env) {
var deferred = $q.defer();
SwarmService.swarm()
.then(function success(data) {
var swarm = data;
return FileUploadService.createStack(name, swarm.Id, stackFile);
return FileUploadService.createStack(name, swarm.Id, stackFile, env);
})
.then(function success(data) {
deferred.resolve(data.data);
@ -154,8 +167,8 @@ function StackServiceFactory($q, Stack, ResourceControlService, FileUploadServic
return deferred.promise;
};
service.updateStack = function(id, stackFile) {
return Stack.update({ id: id, StackFileContent: stackFile }).$promise;
service.updateStack = function(id, stackFile, env) {
return Stack.update({ id: id, StackFileContent: stackFile, Env: env }).$promise;
};
return service;

View file

@ -8,9 +8,9 @@ angular.module('portainer.services')
return Upload.upload({ url: url, data: { file: file }});
}
service.createStack = function(stackName, swarmId, file) {
service.createStack = function(stackName, swarmId, file, env) {
var endpointID = EndpointProvider.endpointID();
return Upload.upload({ url: 'api/endpoints/' + endpointID + '/stacks?method=file', data: { file: file, Name: stackName, SwarmID: swarmId } });
return Upload.upload({ url: 'api/endpoints/' + endpointID + '/stacks?method=file', data: { file: file, Name: stackName, SwarmID: swarmId, Env: Upload.json(env) } });
};
service.uploadLDAPTLSFiles = function(TLSCAFile, TLSCertFile, TLSKeyFile) {