1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 00:09:40 +02:00

feat(secrets): add secret management (#894)

This commit is contained in:
Anthony Lapenna 2017-05-27 09:23:49 +02:00 committed by GitHub
parent 128601bb58
commit 42d28db47a
21 changed files with 730 additions and 27 deletions

View file

@ -1,8 +1,8 @@
// @@OLD_SERVICE_CONTROLLER: this service should be rewritten to use services.
// See app/components/templates/templatesController.js as a reference.
angular.module('createService', [])
.controller('CreateServiceController', ['$scope', '$state', 'Service', 'ServiceHelper', 'Volume', 'Network', 'ImageHelper', 'Authentication', 'ResourceControlService', 'Notifications', 'ControllerDataPipeline', 'FormValidator',
function ($scope, $state, Service, ServiceHelper, Volume, Network, ImageHelper, Authentication, ResourceControlService, Notifications, ControllerDataPipeline, FormValidator) {
.controller('CreateServiceController', ['$q', '$scope', '$state', 'Service', 'ServiceHelper', 'SecretHelper', 'SecretService', 'VolumeService', 'NetworkService', 'ImageHelper', 'Authentication', 'ResourceControlService', 'Notifications', 'ControllerDataPipeline', 'FormValidator',
function ($q, $scope, $state, Service, ServiceHelper, SecretHelper, SecretService, VolumeService, NetworkService, ImageHelper, Authentication, ResourceControlService, Notifications, ControllerDataPipeline, FormValidator) {
$scope.formValues = {
Name: '',
@ -24,7 +24,8 @@ function ($scope, $state, Service, ServiceHelper, Volume, Network, ImageHelper,
Parallelism: 1,
PlacementConstraints: [],
UpdateDelay: 0,
FailureAction: 'pause'
FailureAction: 'pause',
Secrets: []
};
$scope.state = {
@ -55,6 +56,14 @@ function ($scope, $state, Service, ServiceHelper, Volume, Network, ImageHelper,
$scope.formValues.Volumes.splice(index, 1);
};
$scope.addSecret = function() {
$scope.formValues.Secrets.push({});
};
$scope.removeSecret = function(index) {
$scope.formValues.Secrets.splice(index, 1);
};
$scope.addEnvironmentVariable = function() {
$scope.formValues.Env.push({ name: '', value: ''});
};
@ -62,18 +71,23 @@ function ($scope, $state, Service, ServiceHelper, Volume, Network, ImageHelper,
$scope.removeEnvironmentVariable = function(index) {
$scope.formValues.Env.splice(index, 1);
};
$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({ key: '', operator: '==', value: '' });
};
$scope.removePlacementPreference = function(index) {
$scope.formValues.PlacementPreferences.splice(index, 1);
};
$scope.addLabel = function() {
$scope.formValues.Labels.push({ name: '', value: ''});
};
@ -203,6 +217,18 @@ function ($scope, $state, Service, ServiceHelper, Volume, Network, ImageHelper,
config.TaskTemplate.Placement.Constraints = ServiceHelper.translateKeyValueToPlacementConstraints(input.PlacementConstraints);
}
function prepareSecretConfig(config, input) {
if (input.Secrets) {
var secrets = [];
angular.forEach(input.Secrets, function(secret) {
if (secret.model) {
secrets.push(SecretHelper.secretConfig(secret.model));
}
});
config.TaskTemplate.ContainerSpec.Secrets = secrets;
}
}
function prepareConfiguration() {
var input = $scope.formValues;
var config = {
@ -225,6 +251,7 @@ function ($scope, $state, Service, ServiceHelper, Volume, Network, ImageHelper,
prepareVolumes(config, input);
prepareNetworks(config, input);
prepareUpdateConfig(config, input);
prepareSecretConfig(config, input);
preparePlacementConfig(config, input);
return config;
}
@ -277,20 +304,22 @@ function ($scope, $state, Service, ServiceHelper, Volume, Network, ImageHelper,
};
function initView() {
Volume.query({}, function (d) {
$scope.availableVolumes = d.Volumes;
}, function (e) {
Notifications.error('Failure', e, 'Unable to retrieve volumes');
});
Network.query({}, function (d) {
$scope.availableNetworks = d.filter(function (network) {
if (network.Scope === 'swarm') {
return network;
}
});
}, function (e) {
Notifications.error('Failure', e, 'Unable to retrieve networks');
$('#loadingViewSpinner').show();
$q.all({
volumes: VolumeService.volumes(),
networks: NetworkService.retrieveSwarmNetworks(),
secrets: SecretService.secrets()
})
.then(function success(data) {
$scope.availableVolumes = data.volumes;
$scope.availableNetworks = data.networks;
$scope.availableSecrets = data.secrets;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to initialize view');
})
.finally(function final() {
$('#loadingViewSpinner').hide();
});
}

View file

@ -1,5 +1,7 @@
<rd-header>
<rd-header-title title="Create service"></rd-header-title>
<rd-header-title title="Create service">
<i id="loadingViewSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>
<a ui-sref="services">Services</a> > Add service
</rd-header-content>
@ -140,6 +142,7 @@
<li class="interactive"><a data-target="#network" data-toggle="tab">Network</a></li>
<li class="interactive"><a data-target="#labels" data-toggle="tab">Labels</a></li>
<li class="interactive"><a data-target="#update-config" data-toggle="tab">Update config</a></li>
<li class="interactive"><a data-target="#secrets" data-toggle="tab" ng-if="applicationState.endpoint.apiVersion >= 1.25">Secrets</a></li>
<li class="interactive"><a data-target="#placement" data-toggle="tab">Placement</a></li>
</ul>
<!-- tab-content -->
@ -422,7 +425,9 @@
</form>
</div>
<!-- !tab-update-config -->
<!-- tab-secrets -->
<div class="tab-pane" id="secrets" ng-if="applicationState.endpoint.apiVersion >= 1.25" ng-include="'app/components/createService/includes/secret.html'"></div>
<!-- !tab-secrets -->
<!-- tab-placement -->
<div class="tab-pane" id="placement" ng-include="'app/components/createService/includes/placement.html'"></div>
<!-- !tab-placement -->

View file

@ -2,7 +2,7 @@
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Placement constraints</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addPlacementConstraint(service)">
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addPlacementConstraint()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> placement constraint
</span>
</div>

View file

@ -0,0 +1,28 @@
<form class="form-horizontal" style="margin-top: 15px;">
<div class="form-group">
<div class="col-sm-12 small text-muted">
Secrets will be available under <code>/run/secrets/$SECRET_NAME</code> in containers.
</div>
</div>
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Secrets</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addSecret()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add a secret
</span>
</div>
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="secret in formValues.Secrets" style="margin-top: 2px;">
<div class="input-group col-sm-4 input-group-sm">
<span class="input-group-addon">secret</span>
<select class="form-control" ng-model="secret.model" ng-options="secret.Name for secret in availableSecrets">
<option value="" selected="selected">Select a secret</option>
</select>
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeSecret($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
</form>