mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 13:55:21 +02:00
Merge branch 'develop' into oath-poc
This commit is contained in:
commit
508352f4ea
53 changed files with 626 additions and 452 deletions
|
@ -30,7 +30,7 @@ function ($rootScope, $state, Authentication, authManager, StateManager, Endpoin
|
|||
};
|
||||
|
||||
$transitions.onBefore({ to: 'docker.**' }, function() {
|
||||
HttpRequestHelper.resetAgentTargetQueue();
|
||||
HttpRequestHelper.resetAgentHeaders();
|
||||
});
|
||||
}]);
|
||||
|
||||
|
@ -45,7 +45,7 @@ function initAuthentication(authManager, Authentication, $rootScope, $state) {
|
|||
// to have more controls on which URL should trigger the unauthenticated state.
|
||||
$rootScope.$on('unauthenticated', function (event, data) {
|
||||
if (!_.includes(data.config.url, '/v2/')) {
|
||||
$state.go('portainer.auth', {error: 'Your session has expired'});
|
||||
$state.go('portainer.auth', {error: 'Your session has expired', redirect: $state.current.name});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@ angular.module('portainer')
|
|||
request: function(config) {
|
||||
if (config.url.indexOf('/docker/') > -1) {
|
||||
config.headers['X-PortainerAgent-Target'] = HttpRequestHelper.portainerAgentTargetHeader();
|
||||
if (HttpRequestHelper.portainerAgentManagerOperation()) {
|
||||
config.headers['X-PortainerAgent-ManagerOperation'] = '1';
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,17 @@ angular.module('portainer.docker', ['portainer.app'])
|
|||
var docker = {
|
||||
name: 'docker',
|
||||
parent: 'root',
|
||||
abstract: true
|
||||
abstract: true,
|
||||
resolve: {
|
||||
endpointID: ['EndpointProvider', '$state',
|
||||
function (EndpointProvider, $state) {
|
||||
var id = EndpointProvider.endpointID();
|
||||
if (!id) {
|
||||
return $state.go('portainer.home');
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var configs = {
|
||||
|
|
|
@ -38,12 +38,12 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr dir-paginate="(key, value) in $ctrl.dataset | itemsPerPage: $ctrl.state.paginatedItemLimit" ng-class="{active: item.Checked}">
|
||||
<td><a ui-sref="docker.networks.network({ id: value.NetworkID, nodeName: $ctrl.nodeName })">{{ key }}</a></td>
|
||||
<td><a ui-sref="docker.networks.network({ id: key, nodeName: $ctrl.nodeName })">{{ key }}</a></td>
|
||||
<td>{{ value.IPAddress || '-' }}</td>
|
||||
<td>{{ value.Gateway || '-' }}</td>
|
||||
<td>{{ value.MacAddress || '-' }}</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-xs btn-danger" ng-disabled="$ctrl.leaveNetworkActionInProgress" button-spinner="$ctrl.leaveNetworkActionInProgress" ng-click="$ctrl.leaveNetworkAction($ctrl.container, value.NetworkID)">
|
||||
<button type="button" class="btn btn-xs btn-danger" ng-disabled="$ctrl.leaveNetworkActionInProgress" button-spinner="$ctrl.leaveNetworkActionInProgress" ng-click="$ctrl.leaveNetworkAction($ctrl.container, key)">
|
||||
<span ng-hide="$ctrl.leaveNetworkActionInProgress"><i class="fa fa-trash-alt space-right" aria-hidden="true"></i> Leave network</span>
|
||||
<span ng-show="$ctrl.leaveNetworkActionInProgress">Leaving network...</span>
|
||||
</button>
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
angular.module('portainer.docker')
|
||||
.factory('ContainerHelper', [function ContainerHelperFactory() {
|
||||
angular.module('portainer.docker').factory('ContainerHelper', [function ContainerHelperFactory() {
|
||||
'use strict';
|
||||
var helper = {};
|
||||
|
||||
helper.commandStringToArray = function(command) {
|
||||
return splitargs(command, undefined, true);
|
||||
return splitargs(command);
|
||||
};
|
||||
|
||||
helper.commandArrayToString = function(array) {
|
||||
|
|
|
@ -493,6 +493,19 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
|
|||
$scope.formValues.capabilities.push(new ContainerCapability(cap, false));
|
||||
});
|
||||
}
|
||||
|
||||
function hasCapability(item) {
|
||||
return item.capability === cap.capability;
|
||||
}
|
||||
|
||||
var capabilities = new ContainerCapabilities();
|
||||
for (var i = 0; i < capabilities.length; i++) {
|
||||
var cap = capabilities[i];
|
||||
if (!_.find($scope.formValues.capabilities, hasCapability)) {
|
||||
$scope.formValues.capabilities.push(cap);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.formValues.capabilities.sort(function(a, b) {
|
||||
return a.capability < b.capability ? -1 : 1;
|
||||
});
|
||||
|
@ -509,6 +522,7 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
|
|||
$scope.fromContainer = fromContainer;
|
||||
$scope.config = ContainerHelper.configFromContainer(fromContainer.Model);
|
||||
loadFromContainerCmd(d);
|
||||
loadFromContainerLogging(d);
|
||||
loadFromContainerPortBindings(d);
|
||||
loadFromContainerVolumes(d);
|
||||
loadFromContainerNetworkConfig(d);
|
||||
|
@ -525,6 +539,17 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
|
|||
});
|
||||
}
|
||||
|
||||
function loadFromContainerLogging(config) {
|
||||
var logConfig = config.HostConfig.LogConfig;
|
||||
$scope.formValues.LogDriverName = logConfig.Type;
|
||||
$scope.formValues.LogDriverOpts = _.map(logConfig.Config, function (value, name) {
|
||||
return {
|
||||
name: name,
|
||||
value: value
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function initView() {
|
||||
var nodeName = $transition$.params().nodeName;
|
||||
$scope.formValues.NodeName = nodeName;
|
||||
|
@ -621,9 +646,9 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
|
|||
function create() {
|
||||
var oldContainer = null;
|
||||
|
||||
|
||||
HttpRequestHelper.setPortainerAgentTargetHeader($scope.formValues.NodeName);
|
||||
return findCurrentContainer()
|
||||
.then(setOldContainer)
|
||||
.then(confirmCreateContainer)
|
||||
.then(startCreationProcess)
|
||||
.catch(notifyOnError)
|
||||
|
@ -633,6 +658,11 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
|
|||
$scope.state.actionInProgress = false;
|
||||
}
|
||||
|
||||
function setOldContainer(container) {
|
||||
oldContainer = container;
|
||||
return container;
|
||||
}
|
||||
|
||||
function findCurrentContainer() {
|
||||
return Container.query({ all: 1, filters: { name: ['^/' + $scope.config.name + '$'] } })
|
||||
.$promise
|
||||
|
@ -640,8 +670,7 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
|
|||
if (!containers.length) {
|
||||
return;
|
||||
}
|
||||
oldContainer = containers[0];
|
||||
return oldContainer;
|
||||
return containers[0];
|
||||
})
|
||||
.catch(notifyOnError);
|
||||
|
||||
|
@ -664,7 +693,36 @@ function ($q, $scope, $state, $timeout, $transition$, $filter, Container, Contai
|
|||
.then(applyResourceControl)
|
||||
.then(connectToExtraNetworks)
|
||||
.then(removeOldContainer)
|
||||
.then(onSuccess);
|
||||
.then(onSuccess)
|
||||
.catch(onCreationProcessFail);
|
||||
}
|
||||
|
||||
function onCreationProcessFail(error) {
|
||||
var deferred = $q.defer();
|
||||
removeNewContainer()
|
||||
.then(restoreOldContainerName)
|
||||
.then(function() {
|
||||
deferred.reject(error);
|
||||
})
|
||||
.catch(function(restoreError) {
|
||||
deferred.reject(restoreError);
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function removeNewContainer() {
|
||||
return findCurrentContainer().then(function onContainerLoaded(container) {
|
||||
if (container && (!oldContainer || container.Id !== oldContainer.Id)) {
|
||||
return ContainerService.remove(container, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function restoreOldContainerName() {
|
||||
if (!oldContainer) {
|
||||
return;
|
||||
}
|
||||
return ContainerService.renameContainer(oldContainer.Id, oldContainer.Names[0].substring(1));
|
||||
}
|
||||
|
||||
function confirmCreateContainer(container) {
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
<form class="form-horizontal" style="margin-top: 15px;">
|
||||
<!-- command-input -->
|
||||
<div class="form-group">
|
||||
<label for="container_command" class="col-sm-2 col-lg-1 control-label text-left">Command & logging</label>
|
||||
<label for="container_command" class="col-sm-2 col-lg-1 control-label text-left">Command</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" ng-model="config.Cmd" id="container_command" placeholder="e.g. /usr/bin/nginx -t -c /mynginx.conf">
|
||||
</div>
|
||||
|
@ -320,7 +320,7 @@
|
|||
<span class="input-group-addon">volume</span>
|
||||
<select class="form-control" ng-model="volume.name">
|
||||
<option selected disabled hidden value="">Select a volume</option>
|
||||
<option ng-repeat="vol in availableVolumes" ng-value="vol.Name">{{ vol.Name|truncate:30}}</option>
|
||||
<option ng-repeat="vol in availableVolumes" ng-value="vol.Name">{{ vol.Name|truncate:30}} - {{ vol.Driver|truncate:30}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- !volume -->
|
||||
|
|
|
@ -126,6 +126,7 @@ angular.module('portainer.docker')
|
|||
|
||||
function createNetwork(context) {
|
||||
HttpRequestHelper.setPortainerAgentTargetHeader(context.nodeName);
|
||||
HttpRequestHelper.setPortainerAgentManagerOperation(context.managerOperation);
|
||||
|
||||
$scope.state.actionInProgress = true;
|
||||
NetworkService.create(context.networkConfiguration)
|
||||
|
@ -162,12 +163,17 @@ angular.module('portainer.docker')
|
|||
|
||||
var creationContext = {
|
||||
nodeName: $scope.formValues.NodeName,
|
||||
managerOperation: false,
|
||||
networkConfiguration: networkConfiguration,
|
||||
userDetails: userDetails,
|
||||
accessControlData: accessControlData,
|
||||
reload: true
|
||||
};
|
||||
|
||||
if ($scope.applicationState.endpoint.mode.agentProxy && $scope.applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE' && $scope.config.Driver === 'overlay') {
|
||||
creationContext.managerOperation = true;
|
||||
}
|
||||
|
||||
if ($scope.config.Driver === 'macvlan') {
|
||||
if ($scope.formValues.Macvlan.Scope === 'local') {
|
||||
modifyNetworkConfigurationForMacvlanConfigOnly(networkConfiguration);
|
||||
|
@ -205,4 +211,4 @@ angular.module('portainer.docker')
|
|||
|
||||
initView();
|
||||
}
|
||||
]);
|
||||
]);
|
||||
|
|
|
@ -39,13 +39,9 @@
|
|||
<td>Internal</td>
|
||||
<td>{{ network.Internal }}</td>
|
||||
</tr>
|
||||
<tr ng-if="network.IPAM.Config[0].Subnet">
|
||||
<td>Subnet</td>
|
||||
<td>{{ network.IPAM.Config[0].Subnet }}</td>
|
||||
</tr>
|
||||
<tr ng-if="network.IPAM.Config[0].Gateway">
|
||||
<td>Gateway</td>
|
||||
<td>{{ network.IPAM.Config[0].Gateway }}</td>
|
||||
<tr ng-if="network.IPAM.Config.length > 0" ng-repeat="config in network.IPAM.Config">
|
||||
<td>Subnet - {{ config.Subnet }}</td>
|
||||
<td>Gateway - {{ config.Gateway }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -315,8 +315,9 @@
|
|||
<!-- volume -->
|
||||
<div class="input-group input-group-sm col-sm-6" ng-if="volume.Type === 'volume'">
|
||||
<span class="input-group-addon">volume</span>
|
||||
<select class="form-control" ng-model="volume.Source" ng-options="vol.Id|truncate:30 for vol in availableVolumes">
|
||||
<select class="form-control" ng-model="volume.Source">
|
||||
<option selected disabled hidden value="">Select a volume</option>
|
||||
<option ng-repeat="vol in availableVolumes" ng-value="vol.Id">{{ vol.Id|truncate:30}} - {{ vol.Driver|truncate:30}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- !volume -->
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
angular.module('portainer.extensions.registrymanagement')
|
||||
.factory('RegistryCatalog', ['$resource', 'API_ENDPOINT_REGISTRIES', function RegistryCatalogFactory($resource, API_ENDPOINT_REGISTRIES) {
|
||||
.factory('RegistryCatalog', ['$resource', 'API_ENDPOINT_REGISTRIES',
|
||||
function RegistryCatalogFactory($resource, API_ENDPOINT_REGISTRIES) {
|
||||
'use strict';
|
||||
return $resource(API_ENDPOINT_REGISTRIES + '/:id/v2/:action', {},
|
||||
{
|
||||
get: {
|
||||
method: 'GET',
|
||||
params: { id: '@id', action: '_catalog' }
|
||||
params: { id: '@id', action: '_catalog' },
|
||||
transformResponse: linkGetResponse
|
||||
},
|
||||
ping: {
|
||||
method: 'GET',
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
function linkGetResponse(data, headers) {
|
||||
var response = angular.fromJson(data);
|
||||
var link = headers('link');
|
||||
if (link) {
|
||||
var queryString = link.substring(link.indexOf('?') + 1).split('>;')[0];
|
||||
var queries = queryString.split('&');
|
||||
for (var i = 0; i < queries.length; i++) {
|
||||
var kv = queries[i].split('=');
|
||||
response[kv[0]] = kv[1];
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
|
@ -11,16 +11,33 @@ function RegistryV2ServiceFactory($q, RegistryCatalog, RegistryTags, RegistryMan
|
|||
return RegistryCatalog.ping({ id: id }).$promise;
|
||||
};
|
||||
|
||||
function getCatalog(id) {
|
||||
var deferred = $q.defer();
|
||||
var repositories = [];
|
||||
|
||||
_getCatalogPage({id: id}, deferred, repositories);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function _getCatalogPage(params, deferred, repositories) {
|
||||
RegistryCatalog.get(params).$promise.then(function(data) {
|
||||
repositories = _.concat(repositories, data.repositories);
|
||||
if (data.last && data.n) {
|
||||
_getCatalogPage({id: params.id, n: data.n, last: data.last}, deferred, repositories);
|
||||
} else {
|
||||
deferred.resolve(repositories);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
service.repositories = function (id) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
RegistryCatalog.get({
|
||||
id: id
|
||||
}).$promise
|
||||
.then(function success(data) {
|
||||
getCatalog(id).then(function success(data) {
|
||||
var promises = [];
|
||||
for (var i = 0; i < data.repositories.length; i++) {
|
||||
var repository = data.repositories[i];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var repository = data[i];
|
||||
promises.push(RegistryTags.get({
|
||||
id: id,
|
||||
repository: repository
|
||||
|
|
|
@ -81,9 +81,17 @@ angular.module('portainer.app')
|
|||
});
|
||||
return $q.all(promises);
|
||||
})
|
||||
.then(function success() {
|
||||
.then(function success(data) {
|
||||
Notifications.success('Success', 'Tags successfully deleted');
|
||||
$state.reload();
|
||||
if (data.length === 0) {
|
||||
$state.go('portainer.registries.registry.repositories', {
|
||||
id: $scope.registryId
|
||||
}, {
|
||||
reload: true
|
||||
});
|
||||
} else {
|
||||
$state.reload();
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to delete tags');
|
||||
|
@ -127,9 +135,9 @@ angular.module('portainer.app')
|
|||
})
|
||||
.then(function success(data) {
|
||||
$scope.registry = data.registry;
|
||||
$scope.repository.Tags = data.tags;
|
||||
$scope.repository.Tags = [].concat(data.tags || []);
|
||||
$scope.tags = [];
|
||||
for (var i = 0; i < data.tags.length; i++) {
|
||||
for (var i = 0; i < $scope.repository.Tags.length; i++) {
|
||||
var tag = data.tags[i];
|
||||
RegistryV2Service.tag(registryId, repository, tag)
|
||||
.then(function success(data) {
|
||||
|
|
|
@ -48,7 +48,7 @@ angular.module('portainer.app', [])
|
|||
|
||||
var authentication = {
|
||||
name: 'portainer.auth',
|
||||
url: '/auth',
|
||||
url: '/auth?redirect',
|
||||
params: {
|
||||
logout: false,
|
||||
error: ''
|
||||
|
@ -87,7 +87,7 @@ angular.module('portainer.app', [])
|
|||
}
|
||||
};
|
||||
|
||||
var endpointCreation = {
|
||||
var endpointCreation = {
|
||||
name: 'portainer.endpoints.new',
|
||||
url: '/new',
|
||||
views: {
|
||||
|
@ -242,7 +242,7 @@ angular.module('portainer.app', [])
|
|||
}
|
||||
};
|
||||
|
||||
var registryCreation = {
|
||||
var registryCreation = {
|
||||
name: 'portainer.registries.new',
|
||||
url: '/new',
|
||||
views: {
|
||||
|
@ -286,7 +286,7 @@ angular.module('portainer.app', [])
|
|||
}
|
||||
};
|
||||
|
||||
var scheduleCreation = {
|
||||
var scheduleCreation = {
|
||||
name: 'portainer.schedules.new',
|
||||
url: '/new',
|
||||
views: {
|
||||
|
@ -327,6 +327,16 @@ angular.module('portainer.app', [])
|
|||
templateUrl: 'app/portainer/views/stacks/stacks.html',
|
||||
controller: 'StacksController'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
endpointID: ['EndpointProvider', '$state',
|
||||
function (EndpointProvider, $state) {
|
||||
var id = EndpointProvider.endpointID();
|
||||
if (!id) {
|
||||
return $state.go('portainer.home');
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -342,7 +352,7 @@ angular.module('portainer.app', [])
|
|||
};
|
||||
|
||||
var stackCreation = {
|
||||
name: 'portainer.newstack',
|
||||
name: 'portainer.stacks.newstack',
|
||||
url: '/newstack',
|
||||
views: {
|
||||
'content@': {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.removeAction($ctrl.state.selectedItems)">
|
||||
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-primary" ui-sref="portainer.newstack">
|
||||
<button type="button" class="btn btn-sm btn-primary" ui-sref="portainer.stacks.newstack">
|
||||
<i class="fa fa-plus space-right" aria-hidden="true"></i>Add stack
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
</span>
|
||||
<span>
|
||||
|
||||
<span class="small">
|
||||
<span class="small" ng-if="$ctrl.model.GroupName">
|
||||
Group: {{ $ctrl.model.GroupName }}
|
||||
</span>
|
||||
<button
|
||||
ng-if="$ctrl.isAdmin"
|
||||
ng-if="$ctrl.isAdmin"
|
||||
class="btn btn-link btn-xs"
|
||||
ng-click="$ctrl.editEndpoint($event)"><i class="fa fa-pencil-alt"></i>
|
||||
</button>
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
</span>
|
||||
<span>
|
||||
<span class="label label-primary" ng-if="!$ctrl.model.Enabled && !$ctrl.model.Available">coming soon</span>
|
||||
<span class="label label-warning" ng-if="!$ctrl.model.Enabled && $ctrl.model.Deal">deal</span>
|
||||
<span class="label label-danger" ng-if="$ctrl.model.Enabled && $ctrl.model.Expired">expired</span>
|
||||
<span class="label label-success" ng-if="$ctrl.model.Enabled && !$ctrl.model.Expired">enabled</span>
|
||||
<span class="label label-primary" ng-if="$ctrl.model.Enabled && $ctrl.model.UpdateAvailable && !$ctrl.model.Expired">update available</span>
|
||||
<span class="label label-warning" ng-if="!$ctrl.model.Enabled && $ctrl.model.Deal && !$ctrl.model.License.Expiration">deal</span>
|
||||
<span class="label label-danger" ng-if="!$ctrl.model.Enabled && $ctrl.model.License.Expiration && !$ctrl.model.License.Valid">expired</span>
|
||||
<span class="label label-success" ng-if="$ctrl.model.Enabled && $ctrl.model.License.Valid">enabled</span>
|
||||
<span class="label label-primary" ng-if="$ctrl.model.Enabled && $ctrl.model.License.Valid && $ctrl.model.UpdateAvailable">update available</span>
|
||||
</span>
|
||||
</div>
|
||||
<!-- !blocklist-item-line1 -->
|
||||
|
|
|
@ -3,7 +3,6 @@ angular.module('portainer.app')
|
|||
function($state) {
|
||||
|
||||
var ctrl = this;
|
||||
ctrl.$onInit = $onInit;
|
||||
ctrl.goToExtensionView = goToExtensionView;
|
||||
|
||||
function goToExtensionView() {
|
||||
|
@ -11,10 +10,4 @@ angular.module('portainer.app')
|
|||
$state.go('portainer.extensions.extension', { id: ctrl.model.Id });
|
||||
}
|
||||
}
|
||||
|
||||
function $onInit() {
|
||||
if (ctrl.currentDate === ctrl.model.License.Expiration) {
|
||||
ctrl.model.Expired = true;
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="blocklist-item-box">
|
||||
<!-- extension-image -->
|
||||
<span class="blocklist-item-logo">
|
||||
<img class="blocklist-item-logo" src="images/support_{{ $ctrl.model.Id }}.png" />
|
||||
<img class="blocklist-item-logo" ng-src="images/support_{{ $ctrl.model.Id }}.png" />
|
||||
</span>
|
||||
<!-- !extension-image -->
|
||||
<!-- extension-details -->
|
||||
|
@ -15,11 +15,6 @@
|
|||
{{ $ctrl.model.Name }}
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span class="label label-danger" ng-if="$ctrl.model.Enabled && $ctrl.model.Expired">expired</span>
|
||||
<span class="label label-success" ng-if="$ctrl.model.Enabled && !$ctrl.model.Expired">enabled</span>
|
||||
<span class="label label-primary" ng-if="$ctrl.model.Enabled && $ctrl.model.UpdateAvailable && !$ctrl.model.Expired">update available</span>
|
||||
</span>
|
||||
</div>
|
||||
<!-- !blocklist-item-line1 -->
|
||||
<!-- blocklist-item-line2 -->
|
||||
|
@ -29,9 +24,6 @@
|
|||
{{ $ctrl.model.ShortDescription }}
|
||||
</span>
|
||||
</span>
|
||||
<span ng-if="$ctrl.model.License.Company">
|
||||
<span class="small text-muted">Licensed to {{ $ctrl.model.License.Company }} - Expires on {{ $ctrl.model.License.Expiration }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<!-- !blocklist-item-line2 -->
|
||||
</span>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
angular.module('portainer.app')
|
||||
.factory('EndpointStatusInterceptor', ['$q', '$injector', 'EndpointProvider', function ($q, $injector, EndpointProvider) {
|
||||
.factory('EndpointStatusInterceptor', ['$q', 'EndpointProvider', function ($q, EndpointProvider) {
|
||||
'use strict';
|
||||
var interceptor = {};
|
||||
|
||||
|
@ -18,21 +18,17 @@ angular.module('portainer.app')
|
|||
}
|
||||
|
||||
function responseInterceptor(response) {
|
||||
var EndpointService = $injector.get('EndpointService');
|
||||
var url = response.config.url;
|
||||
if (response.status === 200 && canBeOffline(url) && EndpointProvider.offlineMode()) {
|
||||
EndpointProvider.setOfflineMode(false);
|
||||
EndpointService.updateEndpoint(EndpointProvider.endpointID(), {Status: EndpointProvider.endpointStatusFromOfflineMode(false)});
|
||||
}
|
||||
return response || $q.when(response);
|
||||
}
|
||||
|
||||
function responseErrorInterceptor(rejection) {
|
||||
var EndpointService = $injector.get('EndpointService');
|
||||
var url = rejection.config.url;
|
||||
if ((rejection.status === 502 || rejection.status === 503 || rejection.status === -1) && canBeOffline(url) && !EndpointProvider.offlineMode()) {
|
||||
EndpointProvider.setOfflineMode(true);
|
||||
EndpointService.updateEndpoint(EndpointProvider.endpointID(), {Status: EndpointProvider.endpointStatusFromOfflineMode(true)});
|
||||
}
|
||||
return $q.reject(rejection);
|
||||
}
|
||||
|
|
|
@ -64,10 +64,6 @@ angular.module('portainer.app')
|
|||
return endpoint.OfflineMode;
|
||||
};
|
||||
|
||||
service.endpointStatusFromOfflineMode = function(isOffline) {
|
||||
return isOffline ? 2 : 1;
|
||||
};
|
||||
|
||||
service.setOfflineMode = function(isOffline) {
|
||||
endpoint.OfflineMode = isOffline;
|
||||
LocalStorage.storeOfflineMode(isOffline);
|
||||
|
|
|
@ -5,6 +5,7 @@ angular.module('portainer.app')
|
|||
var service = {};
|
||||
var headers = {};
|
||||
headers.agentTargetQueue = [];
|
||||
headers.agentManagerOperation = false;
|
||||
|
||||
service.registryAuthenticationHeader = function() {
|
||||
return headers.registryAuthentication;
|
||||
|
@ -36,9 +37,18 @@ angular.module('portainer.app')
|
|||
}
|
||||
};
|
||||
|
||||
service.resetAgentTargetQueue = function() {
|
||||
service.setPortainerAgentManagerOperation = function(set) {
|
||||
headers.agentManagerOperation = set;
|
||||
};
|
||||
|
||||
service.portainerAgentManagerOperation = function() {
|
||||
return headers.agentManagerOperation;
|
||||
};
|
||||
|
||||
service.resetAgentHeaders = function() {
|
||||
headers.agentTargetQueue = [];
|
||||
delete headers.agentTargetLastValue;
|
||||
headers.agentManagerOperation = false;
|
||||
};
|
||||
|
||||
return service;
|
||||
|
|
|
@ -1,126 +1,125 @@
|
|||
angular.module('portainer.app')
|
||||
.controller('AuthenticationController', ['urlHelper','$q', '$scope', '$state', '$stateParams', '$sanitize', 'Authentication', 'UserService', 'EndpointService', 'StateManager', 'Notifications', 'SettingsService',
|
||||
function (urlHelper, $q, $scope, $state, $stateParams, $sanitize, Authentication, UserService, EndpointService, StateManager, Notifications, SettingsService) {
|
||||
$scope.logo = StateManager.getState().application.logo;
|
||||
angular.module('portainer.app').controller('AuthenticationController', ['$q', '$scope', '$state', '$stateParams', '$sanitize', 'Authentication', 'UserService', 'EndpointService', 'StateManager', 'Notifications', 'SettingsService', 'urlHelper',
|
||||
function($q, $scope, $state, $stateParams, $sanitize, Authentication, UserService, EndpointService, StateManager, Notifications, SettingsService, urlHelper) {
|
||||
$scope.logo = StateManager.getState().application.logo;
|
||||
|
||||
$scope.formValues = {
|
||||
Username: '',
|
||||
Password: ''
|
||||
};
|
||||
$scope.formValues = {
|
||||
Username: '',
|
||||
Password: ''
|
||||
};
|
||||
|
||||
$scope.state = {
|
||||
AuthenticationError: ''
|
||||
};
|
||||
$scope.state = {
|
||||
AuthenticationError: ''
|
||||
};
|
||||
|
||||
$scope.authenticateUser = function() {
|
||||
var username = $scope.formValues.Username;
|
||||
var password = $scope.formValues.Password;
|
||||
$scope.authenticateUser = function() {
|
||||
var username = $scope.formValues.Username;
|
||||
var password = $scope.formValues.Password;
|
||||
|
||||
Authentication.login(username, password)
|
||||
.then(function success() {
|
||||
checkForEndpoints();
|
||||
})
|
||||
.catch(function error() {
|
||||
Authentication.login(username, password)
|
||||
.then(function success() {
|
||||
checkForEndpoints();
|
||||
})
|
||||
.catch(function error() {
|
||||
SettingsService.publicSettings()
|
||||
.then(function success(settings) {
|
||||
if (settings.AuthenticationMethod === 1) {
|
||||
return Authentication.login($sanitize(username), $sanitize(password));
|
||||
}
|
||||
return $q.reject();
|
||||
})
|
||||
.then(function success() {
|
||||
$state.go('portainer.updatePassword');
|
||||
})
|
||||
.catch(function error() {
|
||||
$scope.state.AuthenticationError = 'Invalid credentials';
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function unauthenticatedFlow() {
|
||||
EndpointService.endpoints()
|
||||
.then(function success(endpoints) {
|
||||
if (endpoints.length === 0) {
|
||||
$state.go('portainer.init.endpoint');
|
||||
} else {
|
||||
$state.go($stateParams.redirect || 'portainer.home');
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve endpoints');
|
||||
});
|
||||
}
|
||||
|
||||
function authenticatedFlow() {
|
||||
UserService.administratorExists()
|
||||
.then(function success(exists) {
|
||||
if (!exists) {
|
||||
$state.go('portainer.init.admin');
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to verify administrator account existence');
|
||||
});
|
||||
}
|
||||
|
||||
function checkForEndpoints() {
|
||||
EndpointService.endpoints()
|
||||
.then(function success(data) {
|
||||
var endpoints = data;
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
|
||||
if (endpoints.length === 0 && userDetails.role === 1) {
|
||||
$state.go('portainer.init.endpoint');
|
||||
} else {
|
||||
$state.go($stateParams.redirect || 'portainer.home');
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve endpoints');
|
||||
});
|
||||
}
|
||||
|
||||
function initView() {
|
||||
SettingsService.publicSettings()
|
||||
.then(function success(settings) {
|
||||
if (settings.AuthenticationMethod === 1) {
|
||||
return Authentication.login($sanitize(username), $sanitize(password));
|
||||
}
|
||||
return $q.reject();
|
||||
})
|
||||
.then(function success() {
|
||||
$state.go('portainer.updatePassword');
|
||||
})
|
||||
.catch(function error() {
|
||||
$scope.state.AuthenticationError = 'Invalid credentials';
|
||||
});
|
||||
});
|
||||
};
|
||||
.then(function success(settings) {
|
||||
$scope.AuthenticationMethod = settings.AuthenticationMethod;
|
||||
$scope.OAuthLoginURI = settings.OAuthLoginURI;
|
||||
});
|
||||
|
||||
function unauthenticatedFlow() {
|
||||
EndpointService.endpoints()
|
||||
.then(function success(endpoints) {
|
||||
if (endpoints.length === 0) {
|
||||
$state.go('portainer.init.endpoint');
|
||||
} else {
|
||||
if ($stateParams.logout || $stateParams.error) {
|
||||
Authentication.logout();
|
||||
$scope.state.AuthenticationError = $stateParams.error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Authentication.isAuthenticated()) {
|
||||
$state.go('portainer.home');
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve endpoints');
|
||||
});
|
||||
}
|
||||
|
||||
function authenticatedFlow() {
|
||||
UserService.administratorExists()
|
||||
.then(function success(exists) {
|
||||
if (!exists) {
|
||||
$state.go('portainer.init.admin');
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to verify administrator account existence');
|
||||
});
|
||||
}
|
||||
|
||||
function checkForEndpoints() {
|
||||
EndpointService.endpoints()
|
||||
.then(function success(data) {
|
||||
var endpoints = data;
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
|
||||
if (endpoints.length === 0 && userDetails.role === 1) {
|
||||
$state.go('portainer.init.endpoint');
|
||||
var authenticationEnabled = $scope.applicationState.application.authentication;
|
||||
if (!authenticationEnabled) {
|
||||
unauthenticatedFlow();
|
||||
} else {
|
||||
$state.go('portainer.home');
|
||||
authenticatedFlow();
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve endpoints');
|
||||
});
|
||||
}
|
||||
|
||||
function initView() {
|
||||
SettingsService.publicSettings()
|
||||
.then(function success(settings) {
|
||||
$scope.AuthenticationMethod = settings.AuthenticationMethod;
|
||||
$scope.OAuthLoginURI = settings.OAuthLoginURI;
|
||||
});
|
||||
|
||||
if ($stateParams.logout || $stateParams.error) {
|
||||
Authentication.logout();
|
||||
$scope.state.AuthenticationError = $stateParams.error;
|
||||
return;
|
||||
var code = urlHelper.getParameter('code');
|
||||
if (code) {
|
||||
oAuthLogin(code);
|
||||
}
|
||||
}
|
||||
|
||||
if (Authentication.isAuthenticated()) {
|
||||
$state.go('portainer.home');
|
||||
function oAuthLogin(code) {
|
||||
return Authentication.OAuthLogin(code)
|
||||
.then(function success() {
|
||||
urlHelper.cleanParameters();
|
||||
$state.go('portainer.home');
|
||||
})
|
||||
.catch(function error() {
|
||||
$scope.state.AuthenticationError = 'Failed to authenticate with OAuth2 Provider';
|
||||
});
|
||||
}
|
||||
|
||||
var authenticationEnabled = $scope.applicationState.application.authentication;
|
||||
if (!authenticationEnabled) {
|
||||
unauthenticatedFlow();
|
||||
} else {
|
||||
authenticatedFlow();
|
||||
}
|
||||
|
||||
var code = urlHelper.getParameter('code');
|
||||
if (code) {
|
||||
oAuthLogin(code);
|
||||
}
|
||||
}
|
||||
|
||||
function oAuthLogin(code) {
|
||||
return Authentication.OAuthLogin(code)
|
||||
.then(function success() {
|
||||
urlHelper.cleanParameters();
|
||||
$state.go('portainer.home');
|
||||
})
|
||||
.catch(function error() {
|
||||
$scope.state.AuthenticationError = 'Failed to authenticate with OAuth2 Provider';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
initView();
|
||||
}]);
|
||||
initView();
|
||||
}]);
|
||||
|
|
|
@ -20,7 +20,7 @@ function ($q, $scope, $state, $filter, clipboard, EndpointService, GroupService,
|
|||
};
|
||||
|
||||
$scope.copyAgentCommand = function() {
|
||||
clipboard.copyText('curl -L https://portainer.io/download/agent-stack.yml -o agent-stack.yml && docker stack deploy --compose-file=agent-stack.yml portainer-agent');
|
||||
clipboard.copyText('curl -L https://downloads.portainer.io/agent-stack.yml -o agent-stack.yml && docker stack deploy --compose-file=agent-stack.yml portainer-agent');
|
||||
$('#copyNotification').show();
|
||||
$('#copyNotification').fadeOut(2000);
|
||||
};
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
Ensure that you have deployed the Portainer agent in your cluster first. You can use execute the following command on any manager node to deploy it.
|
||||
<div style="margin-top: 10px;">
|
||||
<code>
|
||||
curl -L https://portainer.io/download/agent-stack.yml -o agent-stack.yml && docker stack deploy --compose-file=agent-stack.yml portainer-agent
|
||||
curl -L https://downloads.portainer.io/agent-stack.yml -o agent-stack.yml && docker stack deploy --compose-file=agent-stack.yml portainer-agent
|
||||
</code>
|
||||
<span class="btn btn-primary btn-sm space-left" ng-click="copyAgentCommand()"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy</span>
|
||||
<span>
|
||||
|
|
|
@ -36,7 +36,9 @@
|
|||
<div class="form-group" style="margin-left: 40px;">
|
||||
|
||||
<div style="font-size: 125%; border-bottom: 2px solid #2d3e63; padding-bottom: 5px;">
|
||||
{{ extension.Enabled ? 'Enabled' : extension.Price }}
|
||||
<span ng-if="extension.Enabled">Enabled</span>
|
||||
<span ng-if="!extension.Enabled && extension.License.Expiration && !extension.License.Valid">Expired</span>
|
||||
<span ng-if="!extension.Enabled && !extension.License.Expiration">{{ extension.Price }}</span>
|
||||
</div>
|
||||
|
||||
<div class="small text-muted col-sm-12" style="margin: 15px 0 15px 0;" ng-if="!extension.Enabled">
|
||||
|
|
|
@ -1,139 +1,139 @@
|
|||
angular.module('portainer.app')
|
||||
.controller('HomeController', ['$q', '$scope', '$state', 'Authentication', 'EndpointService', 'EndpointHelper', 'GroupService', 'Notifications', 'EndpointProvider', 'StateManager', 'LegacyExtensionManager', 'ModalService', 'MotdService', 'SystemService',
|
||||
function ($q, $scope, $state, Authentication, EndpointService, EndpointHelper, GroupService, Notifications, EndpointProvider, StateManager, LegacyExtensionManager, ModalService, MotdService, SystemService) {
|
||||
.controller('HomeController', ['$q', '$scope', '$state', 'Authentication', 'EndpointService', 'EndpointHelper', 'GroupService', 'Notifications', 'EndpointProvider', 'StateManager', 'LegacyExtensionManager', 'ModalService', 'MotdService', 'SystemService',
|
||||
function($q, $scope, $state, Authentication, EndpointService, EndpointHelper, GroupService, Notifications, EndpointProvider, StateManager, LegacyExtensionManager, ModalService, MotdService, SystemService) {
|
||||
|
||||
$scope.goToEdit = function(id) {
|
||||
$state.go('portainer.endpoints.endpoint', { id: id });
|
||||
};
|
||||
$scope.goToEdit = function(id) {
|
||||
$state.go('portainer.endpoints.endpoint', { id: id });
|
||||
};
|
||||
|
||||
$scope.goToDashboard = function (endpoint) {
|
||||
if (endpoint.Type === 3) {
|
||||
return switchToAzureEndpoint(endpoint);
|
||||
}
|
||||
$scope.goToDashboard = function(endpoint) {
|
||||
if (endpoint.Type === 3) {
|
||||
return switchToAzureEndpoint(endpoint);
|
||||
}
|
||||
|
||||
checkEndpointStatus(endpoint)
|
||||
.then(function sucess() {
|
||||
return switchToDockerEndpoint(endpoint);
|
||||
}).catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to verify endpoint status');
|
||||
});
|
||||
};
|
||||
checkEndpointStatus(endpoint)
|
||||
.then(function sucess() {
|
||||
return switchToDockerEndpoint(endpoint);
|
||||
}).catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to verify endpoint status');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.dismissImportantInformation = function (hash) {
|
||||
StateManager.dismissImportantInformation(hash);
|
||||
};
|
||||
$scope.dismissImportantInformation = function(hash) {
|
||||
StateManager.dismissImportantInformation(hash);
|
||||
};
|
||||
|
||||
$scope.dismissInformationPanel = function (id) {
|
||||
StateManager.dismissInformationPanel(id);
|
||||
};
|
||||
$scope.dismissInformationPanel = function(id) {
|
||||
StateManager.dismissInformationPanel(id);
|
||||
};
|
||||
|
||||
$scope.triggerSnapshot = function () {
|
||||
ModalService.confirmEndpointSnapshot(function (result) {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
triggerSnapshot();
|
||||
});
|
||||
};
|
||||
$scope.triggerSnapshot = function() {
|
||||
ModalService.confirmEndpointSnapshot(function(result) {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
triggerSnapshot();
|
||||
});
|
||||
};
|
||||
|
||||
function checkEndpointStatus(endpoint) {
|
||||
var deferred = $q.defer();
|
||||
function checkEndpointStatus(endpoint) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
var status = 1;
|
||||
SystemService.ping(endpoint.Id)
|
||||
.then(function sucess() {
|
||||
status = 1;
|
||||
}).catch(function error() {
|
||||
status = 2;
|
||||
}).finally(function() {
|
||||
if (endpoint.Status === status) {
|
||||
deferred.resolve(endpoint);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
EndpointService.updateEndpoint(endpoint.Id, { Status: status })
|
||||
.then(function sucess() {
|
||||
deferred.resolve(endpoint);
|
||||
}).catch(function error(err) {
|
||||
deferred.reject({ msg: 'Unable to update endpoint status', err: err });
|
||||
});
|
||||
});
|
||||
|
||||
var status = 1;
|
||||
SystemService.ping(endpoint.Id)
|
||||
.then(function sucess() {
|
||||
status = 1;
|
||||
}).catch(function error() {
|
||||
status = 2;
|
||||
}).finally(function () {
|
||||
if (endpoint.Status === status) {
|
||||
deferred.resolve(endpoint);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
EndpointService.updateEndpoint(endpoint.Id, { Status: status })
|
||||
.then(function sucess() {
|
||||
deferred.resolve(endpoint);
|
||||
}).catch(function error(err) {
|
||||
deferred.reject({msg: 'Unable to update endpoint status', err: err});
|
||||
});
|
||||
});
|
||||
function switchToAzureEndpoint(endpoint) {
|
||||
EndpointProvider.setEndpointID(endpoint.Id);
|
||||
EndpointProvider.setEndpointPublicURL(endpoint.PublicURL);
|
||||
EndpointProvider.setOfflineModeFromStatus(endpoint.Status);
|
||||
StateManager.updateEndpointState(endpoint, [])
|
||||
.then(function success() {
|
||||
$state.go('azure.dashboard');
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to connect to the Azure endpoint');
|
||||
});
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
function switchToDockerEndpoint(endpoint) {
|
||||
if (endpoint.Status === 2 && endpoint.Snapshots[0] && endpoint.Snapshots[0].Swarm === true) {
|
||||
Notifications.error('Failure', '', 'Endpoint is unreachable. Connect to another swarm manager.');
|
||||
return;
|
||||
} else if (endpoint.Status === 2 && !endpoint.Snapshots[0]) {
|
||||
Notifications.error('Failure', '', 'Endpoint is unreachable and there is no snapshot available for offline browsing.');
|
||||
return;
|
||||
}
|
||||
|
||||
function switchToAzureEndpoint(endpoint) {
|
||||
EndpointProvider.setEndpointID(endpoint.Id);
|
||||
EndpointProvider.setEndpointPublicURL(endpoint.PublicURL);
|
||||
EndpointProvider.setOfflineModeFromStatus(endpoint.Status);
|
||||
StateManager.updateEndpointState(endpoint.Name, endpoint.Type, [])
|
||||
.then(function success() {
|
||||
$state.go('azure.dashboard');
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to connect to the Azure endpoint');
|
||||
});
|
||||
}
|
||||
EndpointProvider.setEndpointID(endpoint.Id);
|
||||
EndpointProvider.setEndpointPublicURL(endpoint.PublicURL);
|
||||
EndpointProvider.setOfflineModeFromStatus(endpoint.Status);
|
||||
LegacyExtensionManager.initEndpointExtensions(endpoint)
|
||||
.then(function success(data) {
|
||||
var extensions = data;
|
||||
return StateManager.updateEndpointState(endpoint, extensions);
|
||||
})
|
||||
.then(function success() {
|
||||
$state.go('docker.dashboard');
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to connect to the Docker endpoint');
|
||||
});
|
||||
}
|
||||
|
||||
function switchToDockerEndpoint(endpoint) {
|
||||
if (endpoint.Status === 2 && endpoint.Snapshots[0] && endpoint.Snapshots[0].Swarm === true) {
|
||||
Notifications.error('Failure', '', 'Endpoint is unreachable. Connect to another swarm manager.');
|
||||
return;
|
||||
} else if (endpoint.Status === 2 && !endpoint.Snapshots[0]) {
|
||||
Notifications.error('Failure', '', 'Endpoint is unreachable and there is no snapshot available for offline browsing.');
|
||||
return;
|
||||
}
|
||||
function triggerSnapshot() {
|
||||
EndpointService.snapshotEndpoints()
|
||||
.then(function success() {
|
||||
Notifications.success('Success', 'Endpoints updated');
|
||||
$state.reload();
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'An error occured during endpoint snapshot');
|
||||
});
|
||||
}
|
||||
|
||||
EndpointProvider.setEndpointID(endpoint.Id);
|
||||
EndpointProvider.setEndpointPublicURL(endpoint.PublicURL);
|
||||
EndpointProvider.setOfflineModeFromStatus(endpoint.Status);
|
||||
LegacyExtensionManager.initEndpointExtensions(endpoint)
|
||||
.then(function success(data) {
|
||||
var extensions = data;
|
||||
return StateManager.updateEndpointState(endpoint, extensions);
|
||||
})
|
||||
.then(function success() {
|
||||
$state.go('docker.dashboard');
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to connect to the Docker endpoint');
|
||||
});
|
||||
}
|
||||
function initView() {
|
||||
$scope.isAdmin = Authentication.getUserDetails().role === 1;
|
||||
|
||||
function triggerSnapshot() {
|
||||
EndpointService.snapshotEndpoints()
|
||||
.then(function success() {
|
||||
Notifications.success('Success', 'Endpoints updated');
|
||||
$state.reload();
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'An error occured during endpoint snapshot');
|
||||
});
|
||||
}
|
||||
MotdService.motd()
|
||||
.then(function success(data) {
|
||||
$scope.motd = data;
|
||||
});
|
||||
|
||||
function initView() {
|
||||
$scope.isAdmin = Authentication.getUserDetails().role === 1;
|
||||
$q.all({
|
||||
endpoints: EndpointService.endpoints(),
|
||||
groups: GroupService.groups()
|
||||
})
|
||||
.then(function success(data) {
|
||||
var endpoints = data.endpoints;
|
||||
var groups = data.groups;
|
||||
EndpointHelper.mapGroupNameToEndpoint(endpoints, groups);
|
||||
$scope.endpoints = endpoints;
|
||||
EndpointProvider.setEndpoints(endpoints);
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve endpoint information');
|
||||
});
|
||||
}
|
||||
|
||||
MotdService.motd()
|
||||
.then(function success(data) {
|
||||
$scope.motd = data;
|
||||
});
|
||||
|
||||
$q.all({
|
||||
endpoints: EndpointService.endpoints(),
|
||||
groups: GroupService.groups()
|
||||
})
|
||||
.then(function success(data) {
|
||||
var endpoints = data.endpoints;
|
||||
var groups = data.groups;
|
||||
EndpointHelper.mapGroupNameToEndpoint(endpoints, groups);
|
||||
$scope.endpoints = endpoints;
|
||||
EndpointProvider.setEndpoints(endpoints);
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve endpoint information');
|
||||
});
|
||||
}
|
||||
|
||||
initView();
|
||||
}]);
|
||||
initView();
|
||||
}]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('portainer.app')
|
||||
.controller('TeamsController', ['$q', '$scope', '$state', '$sanitize', 'TeamService', 'UserService', 'ModalService', 'Notifications', 'Authentication',
|
||||
function ($q, $scope, $state, $sanitize, TeamService, UserService, ModalService, Notifications, Authentication) {
|
||||
.controller('TeamsController', ['$q', '$scope', '$state', 'TeamService', 'UserService', 'ModalService', 'Notifications', 'Authentication',
|
||||
function ($q, $scope, $state, TeamService, UserService, ModalService, Notifications, Authentication) {
|
||||
$scope.state = {
|
||||
actionInProgress: false
|
||||
};
|
||||
|
@ -22,7 +22,7 @@ function ($q, $scope, $state, $sanitize, TeamService, UserService, ModalService,
|
|||
};
|
||||
|
||||
$scope.addTeam = function() {
|
||||
var teamName = $sanitize($scope.formValues.Name);
|
||||
var teamName = $scope.formValues.Name;
|
||||
var leaderIds = [];
|
||||
angular.forEach($scope.formValues.Leaders, function(user) {
|
||||
leaderIds.push(user.Id);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue