refactor(endpoints): remove endpointProvider from views [EE-1136] (#5359)

[EE-1136]
pull/6279/head
Chaim Lev-Ari 2021-12-14 09:34:54 +02:00 committed by GitHub
parent 7088da5157
commit eb9f6c77f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 408 additions and 429 deletions

View File

@ -141,8 +141,11 @@ export class HostBrowserController {
return this.$async(this.onFileSelectedForUploadAsync, file); return this.$async(this.onFileSelectedForUploadAsync, file);
} }
async onFileSelectedForUploadAsync(file) { async onFileSelectedForUploadAsync(file) {
if (!this.endpointId) {
throw new Error('missing endpoint id');
}
try { try {
await this.HostBrowserService.upload(this.state.path, file); await this.HostBrowserService.upload(this.endpointId, this.state.path, file);
this.onFileUploaded(); this.onFileUploaded();
} catch (err) { } catch (err) {
this.Notifications.error('Failure', err, 'Unable to upload file'); this.Notifications.error('Failure', err, 'Unable to upload file');

View File

@ -4,4 +4,7 @@ import { HostBrowserController } from './hostBrowserController';
angular.module('portainer.agent').component('hostBrowser', { angular.module('portainer.agent').component('hostBrowser', {
controller: HostBrowserController, controller: HostBrowserController,
templateUrl: './hostBrowser.html', templateUrl: './hostBrowser.html',
bindings: {
endpointId: '<',
},
}); });

View File

@ -9,5 +9,6 @@ angular.module('portainer.agent').component('volumeBrowser', {
volumeId: '<', volumeId: '<',
nodeName: '<', nodeName: '<',
isUploadEnabled: '<', isUploadEnabled: '<',
endpointId: '<',
}, },
}); });

View File

@ -111,7 +111,7 @@ export class VolumeBrowserController {
} }
async onFileSelectedForUploadAsync(file) { async onFileSelectedForUploadAsync(file) {
try { try {
await this.VolumeBrowserService.upload(this.state.path, file, this.volumeId); await this.VolumeBrowserService.upload(this.endpointId, this.state.path, file, this.volumeId);
this.onFileUploaded(); this.onFileUploaded();
} catch (err) { } catch (err) {
this.Notifications.error('Failure', err, 'Unable to upload file'); this.Notifications.error('Failure', err, 'Unable to upload file');

View File

@ -2,7 +2,8 @@ import angular from 'angular';
angular.module('portainer.agent').factory('HostBrowserService', HostBrowserServiceFactory); angular.module('portainer.agent').factory('HostBrowserService', HostBrowserServiceFactory);
function HostBrowserServiceFactory(Browse, Upload, API_ENDPOINT_ENDPOINTS, EndpointProvider, StateManager) { /* @ngInject */
function HostBrowserServiceFactory(Browse, Upload, API_ENDPOINT_ENDPOINTS, StateManager) {
return { ls, get, delete: deletePath, rename, upload }; return { ls, get, delete: deletePath, rename, upload };
function ls(path) { function ls(path) {
@ -25,14 +26,14 @@ function HostBrowserServiceFactory(Browse, Upload, API_ENDPOINT_ENDPOINTS, Endpo
return Browse.rename({}, payload).$promise; return Browse.rename({}, payload).$promise;
} }
function upload(path, file, onProgress) { function upload(endpointId, Path, file, onProgress) {
const agentVersion = StateManager.getAgentApiVersion(); const agentVersion = StateManager.getAgentApiVersion();
const url = `${API_ENDPOINT_ENDPOINTS}/${EndpointProvider.endpointID()}/docker${agentVersion > 1 ? '/v' + agentVersion : ''}/browse/put`; const url = `${API_ENDPOINT_ENDPOINTS}/${endpointId}/docker${agentVersion > 1 ? '/v' + agentVersion : ''}/browse/put`;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Upload.upload({ Upload.upload({
url: url, url: url,
data: { file: file, Path: path }, data: { file, Path },
}).then(resolve, reject, onProgress); }).then(resolve, reject, onProgress);
}); });
} }

View File

@ -2,7 +2,8 @@ import angular from 'angular';
angular.module('portainer.agent').factory('VolumeBrowserService', VolumeBrowserServiceFactory); angular.module('portainer.agent').factory('VolumeBrowserService', VolumeBrowserServiceFactory);
function VolumeBrowserServiceFactory(StateManager, Browse, BrowseVersion1, API_ENDPOINT_ENDPOINTS, EndpointProvider, Upload) { /* @ngInject */
function VolumeBrowserServiceFactory(StateManager, Browse, BrowseVersion1, API_ENDPOINT_ENDPOINTS, Upload) {
return { return {
ls, ls,
get, get,
@ -41,13 +42,13 @@ function VolumeBrowserServiceFactory(StateManager, Browse, BrowseVersion1, API_E
return getBrowseService().rename({ volumeID: volumeId, version: getAgentApiVersion() }, payload).$promise; return getBrowseService().rename({ volumeID: volumeId, version: getAgentApiVersion() }, payload).$promise;
} }
function upload(path, file, volumeId, onProgress) { function upload(endpointId, path, file, volumeId, onProgress) {
const agentVersion = StateManager.getAgentApiVersion(); const agentVersion = StateManager.getAgentApiVersion();
if (agentVersion < 2) { if (agentVersion < 2) {
throw new Error('upload is not supported on this agent version'); throw new Error('upload is not supported on this agent version');
} }
const url = `${API_ENDPOINT_ENDPOINTS}/${EndpointProvider.endpointID()}/docker/v${agentVersion}/browse/put?volumeID=${volumeId}`; const url = `${API_ENDPOINT_ENDPOINTS}/${endpointId}/docker/v${agentVersion}/browse/put?volumeID=${volumeId}`;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Upload.upload({ Upload.upload({

View File

@ -264,7 +264,7 @@
ng-if="item.Ports.length > 0" ng-if="item.Ports.length > 0"
ng-repeat="p in item.Ports | unique: 'public'" ng-repeat="p in item.Ports | unique: 'public'"
class="image-tag" class="image-tag"
ng-href="http://{{ $ctrl.state.publicURL || p.host }}:{{ p.public }}" ng-href="http://{{ $ctrl.endpointPublicUrl || p.host }}:{{ p.public }}"
target="_blank" target="_blank"
> >
<i class="fa fa-external-link-alt" aria-hidden="true"></i> {{ p.public }}:{{ p.private }} <i class="fa fa-external-link-alt" aria-hidden="true"></i> {{ p.public }}:{{ p.private }}

View File

@ -13,5 +13,6 @@ angular.module('portainer.docker').component('containersDatatable', {
offlineMode: '<', offlineMode: '<',
refreshCallback: '<', refreshCallback: '<',
notAutoFocus: '<', notAutoFocus: '<',
endpointPublicUrl: '<',
}, },
}); });

View File

@ -4,8 +4,7 @@ angular.module('portainer.docker').controller('ContainersDatatableController', [
'$scope', '$scope',
'$controller', '$controller',
'DatatableService', 'DatatableService',
'EndpointProvider', function ($scope, $controller, DatatableService) {
function ($scope, $controller, DatatableService, EndpointProvider) {
angular.extend(this, $controller('GenericDatatableController', { $scope: $scope })); angular.extend(this, $controller('GenericDatatableController', { $scope: $scope }));
var ctrl = this; var ctrl = this;
@ -14,7 +13,6 @@ angular.module('portainer.docker').controller('ContainersDatatableController', [
noStoppedItemsSelected: true, noStoppedItemsSelected: true,
noRunningItemsSelected: true, noRunningItemsSelected: true,
noPausedItemsSelected: true, noPausedItemsSelected: true,
publicURL: EndpointProvider.endpointPublicURL(),
}); });
this.settings = Object.assign(this.settings, { this.settings = Object.assign(this.settings, {

View File

@ -6,5 +6,6 @@ angular.module('portainer.docker').component('servicesDatatableActions', {
selectedItemCount: '=', selectedItemCount: '=',
showUpdateAction: '<', showUpdateAction: '<',
showAddAction: '<', showAddAction: '<',
endpointId: '<',
}, },
}); });

View File

@ -7,8 +7,9 @@ angular.module('portainer.docker').controller('ServicesDatatableActionsControlle
'ModalService', 'ModalService',
'ImageHelper', 'ImageHelper',
'WebhookService', 'WebhookService',
'EndpointProvider', function ($q, $state, ServiceService, ServiceHelper, Notifications, ModalService, ImageHelper, WebhookService) {
function ($q, $state, ServiceService, ServiceHelper, Notifications, ModalService, ImageHelper, WebhookService, EndpointProvider) { const ctrl = this;
this.scaleAction = function scaleService(service) { this.scaleAction = function scaleService(service) {
var config = ServiceHelper.serviceToConfig(service.Model); var config = ServiceHelper.serviceToConfig(service.Model);
config.Mode.Replicated.Replicas = service.Replicas; config.Mode.Replicated.Replicas = service.Replicas;
@ -84,7 +85,7 @@ angular.module('portainer.docker').controller('ServicesDatatableActionsControlle
angular.forEach(services, function (service) { angular.forEach(services, function (service) {
ServiceService.remove(service) ServiceService.remove(service)
.then(function success() { .then(function success() {
return WebhookService.webhooks(service.Id, EndpointProvider.endpointID()); return WebhookService.webhooks(service.Id, ctrl.endpointId);
}) })
.then(function success(data) { .then(function success(data) {
return $q.when(data.length !== 0 && WebhookService.deleteWebhook(data[0].Id)); return $q.when(data.length !== 0 && WebhookService.deleteWebhook(data[0].Id));

View File

@ -47,6 +47,7 @@
selected-item-count="$ctrl.state.selectedItemCount" selected-item-count="$ctrl.state.selectedItemCount"
show-add-action="$ctrl.showAddAction" show-add-action="$ctrl.showAddAction"
show-update-action="$ctrl.showUpdateAction" show-update-action="$ctrl.showUpdateAction"
endpoint-id="$ctrl.endpointId"
></services-datatable-actions> ></services-datatable-actions>
<div class="searchBar"> <div class="searchBar">
<i class="fa fa-search searchIcon" aria-hidden="true"></i> <i class="fa fa-search searchIcon" aria-hidden="true"></i>
@ -171,7 +172,7 @@
ng-if="item.Ports && item.Ports.length > 0 && p.PublishedPort" ng-if="item.Ports && item.Ports.length > 0 && p.PublishedPort"
ng-repeat="p in item.Ports" ng-repeat="p in item.Ports"
class="image-tag" class="image-tag"
ng-href="http://{{ $ctrl.state.publicURL }}:{{ p.PublishedPort }}" ng-href="http://{{ $ctrl.endpointPublicUrl }}:{{ p.PublishedPort }}"
target="_blank" target="_blank"
ng-click="$event.stopPropagation();" ng-click="$event.stopPropagation();"
> >

View File

@ -16,5 +16,7 @@ angular.module('portainer.docker').component('servicesDatatable', {
showTaskLogsButton: '<', showTaskLogsButton: '<',
refreshCallback: '<', refreshCallback: '<',
notAutoFocus: '<', notAutoFocus: '<',
endpointPublicUrl: '<',
endpointId: '<',
}, },
}); });

View File

@ -4,8 +4,7 @@ angular.module('portainer.docker').controller('ServicesDatatableController', [
'$scope', '$scope',
'$controller', '$controller',
'DatatableService', 'DatatableService',
'EndpointProvider', function ($scope, $controller, DatatableService) {
function ($scope, $controller, DatatableService, EndpointProvider) {
angular.extend(this, $controller('GenericDatatableController', { $scope: $scope })); angular.extend(this, $controller('GenericDatatableController', { $scope: $scope }));
var ctrl = this; var ctrl = this;
@ -13,7 +12,6 @@ angular.module('portainer.docker').controller('ServicesDatatableController', [
this.state = Object.assign(this.state, { this.state = Object.assign(this.state, {
expandAll: false, expandAll: false,
expandedItems: [], expandedItems: [],
publicURL: EndpointProvider.endpointPublicURL(),
}); });
this.expandAll = function () { this.expandAll = function () {

View File

@ -3,10 +3,10 @@ import { baseHref } from '@/portainer/helpers/pathHelper';
angular.module('portainer.docker').controller('ContainerConsoleController', [ angular.module('portainer.docker').controller('ContainerConsoleController', [
'$scope', '$scope',
'$state',
'$transition$', '$transition$',
'ContainerService', 'ContainerService',
'ImageService', 'ImageService',
'EndpointProvider',
'Notifications', 'Notifications',
'ContainerHelper', 'ContainerHelper',
'ExecService', 'ExecService',
@ -15,10 +15,10 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
'CONSOLE_COMMANDS_LABEL_PREFIX', 'CONSOLE_COMMANDS_LABEL_PREFIX',
function ( function (
$scope, $scope,
$state,
$transition$, $transition$,
ContainerService, ContainerService,
ImageService, ImageService,
EndpointProvider,
Notifications, Notifications,
ContainerHelper, ContainerHelper,
ExecService, ExecService,
@ -65,7 +65,7 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
const params = { const params = {
token: LocalStorage.getJWT(), token: LocalStorage.getJWT(),
endpointId: EndpointProvider.endpointID(), endpointId: $state.params.endpointId,
id: attachId, id: attachId,
}; };
@ -106,7 +106,7 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
.then(function success(data) { .then(function success(data) {
const params = { const params = {
token: LocalStorage.getJWT(), token: LocalStorage.getJWT(),
endpointId: EndpointProvider.endpointID(), endpointId: $state.params.endpointId,
id: data.Id, id: data.Id,
}; };

View File

@ -19,6 +19,7 @@
show-add-action="true" show-add-action="true"
offline-mode="offlineMode" offline-mode="offlineMode"
refresh-callback="getContainers" refresh-callback="getContainers"
endpoint-public-url="endpoint.PublicURL"
></containers-datatable> ></containers-datatable>
</div> </div>
</div> </div>

View File

@ -1,29 +1,26 @@
angular.module('portainer.docker').controller('ContainersController', [ angular.module('portainer.docker').controller('ContainersController', ContainersController);
'$scope',
'ContainerService',
'Notifications',
'EndpointProvider',
function ($scope, ContainerService, Notifications, EndpointProvider) {
$scope.offlineMode = false;
$scope.getContainers = getContainers; /* @ngInject */
function ContainersController($scope, ContainerService, Notifications, endpoint) {
$scope.offlineMode = endpoint.Status !== 1;
$scope.endpoint = endpoint;
function getContainers() { $scope.getContainers = getContainers;
ContainerService.containers(1)
.then(function success(data) {
$scope.containers = data;
$scope.offlineMode = EndpointProvider.offlineMode();
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve containers');
$scope.containers = [];
});
}
function initView() { function getContainers() {
getContainers(); ContainerService.containers(1)
} .then(function success(data) {
$scope.containers = data;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve containers');
$scope.containers = [];
});
}
initView(); function initView() {
}, getContainers();
]); }
initView();
}

View File

@ -1,6 +1,8 @@
import angular from 'angular'; import angular from 'angular';
import _ from 'lodash'; import _ from 'lodash';
import { isOfflineEndpoint } from '@/portainer/helpers/endpointHelper';
angular.module('portainer.docker').controller('DashboardController', [ angular.module('portainer.docker').controller('DashboardController', [
'$scope', '$scope',
'$q', '$q',
@ -12,9 +14,7 @@ angular.module('portainer.docker').controller('DashboardController', [
'SystemService', 'SystemService',
'ServiceService', 'ServiceService',
'StackService', 'StackService',
'EndpointService',
'Notifications', 'Notifications',
'EndpointProvider',
'StateManager', 'StateManager',
'TagService', 'TagService',
'endpoint', 'endpoint',
@ -29,9 +29,7 @@ angular.module('portainer.docker').controller('DashboardController', [
SystemService, SystemService,
ServiceService, ServiceService,
StackService, StackService,
EndpointService,
Notifications, Notifications,
EndpointProvider,
StateManager, StateManager,
TagService, TagService,
endpoint endpoint
@ -45,8 +43,7 @@ angular.module('portainer.docker').controller('DashboardController', [
async function initView() { async function initView() {
const endpointMode = $scope.applicationState.endpoint.mode; const endpointMode = $scope.applicationState.endpoint.mode;
const endpointId = EndpointProvider.endpointID(); $scope.endpoint = endpoint;
$scope.endpointId = endpointId;
$scope.showStacks = await shouldShowStacks(); $scope.showStacks = await shouldShowStacks();
@ -56,9 +53,8 @@ angular.module('portainer.docker').controller('DashboardController', [
volumes: VolumeService.volumes(), volumes: VolumeService.volumes(),
networks: NetworkService.networks(true, true, true), networks: NetworkService.networks(true, true, true),
services: endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER' ? ServiceService.services() : [], services: endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER' ? ServiceService.services() : [],
stacks: StackService.stacks(true, endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER', endpointId), stacks: StackService.stacks(true, endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER', endpoint.Id),
info: SystemService.info(), info: SystemService.info(),
endpoint: EndpointService.endpoint(endpointId),
tags: TagService.tags(), tags: TagService.tags(),
}) })
.then(function success(data) { .then(function success(data) {
@ -69,11 +65,10 @@ angular.module('portainer.docker').controller('DashboardController', [
$scope.serviceCount = data.services.length; $scope.serviceCount = data.services.length;
$scope.stackCount = data.stacks.length; $scope.stackCount = data.stacks.length;
$scope.info = data.info; $scope.info = data.info;
$scope.endpoint = data.endpoint; $scope.endpointTags = endpoint.TagIds.length
$scope.endpointTags = $scope.endpoint.TagIds.length
? _.join( ? _.join(
_.filter( _.filter(
_.map($scope.endpoint.TagIds, (id) => { _.map(endpoint.TagIds, (id) => {
const tag = data.tags.find((tag) => tag.Id === id); const tag = data.tags.find((tag) => tag.Id === id);
return tag ? tag.Name : ''; return tag ? tag.Name : '';
}), }),
@ -82,7 +77,7 @@ angular.module('portainer.docker').controller('DashboardController', [
', ' ', '
) )
: '-'; : '-';
$scope.offlineMode = EndpointProvider.offlineMode(); $scope.offlineMode = isOfflineEndpoint(endpoint);
}) })
.catch(function error(err) { .catch(function error(err) {
Notifications.error('Failure', err, 'Unable to load dashboard data'); Notifications.error('Failure', err, 'Unable to load dashboard data');

View File

@ -7,6 +7,6 @@
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<host-browser ng-if="$ctrl.host"></host-browser> <host-browser ng-if="$ctrl.host" endpoint-id="$ctrl.endpoint.Id"></host-browser>
</div> </div>
</div> </div>

View File

@ -1,4 +1,7 @@
angular.module('portainer.docker').component('hostBrowserView', { angular.module('portainer.docker').component('hostBrowserView', {
templateUrl: './host-browser-view.html', templateUrl: './host-browser-view.html',
controller: 'HostBrowserViewController', controller: 'HostBrowserViewController',
bindings: {
endpoint: '<',
},
}); });

View File

@ -1,3 +1,5 @@
import { isOfflineEndpoint } from '@/portainer/helpers/endpointHelper';
angular.module('portainer.docker').controller('HostViewController', [ angular.module('portainer.docker').controller('HostViewController', [
'$q', '$q',
'SystemService', 'SystemService',
@ -6,8 +8,7 @@ angular.module('portainer.docker').controller('HostViewController', [
'AgentService', 'AgentService',
'ContainerService', 'ContainerService',
'Authentication', 'Authentication',
'EndpointProvider', function HostViewController($q, SystemService, Notifications, StateManager, AgentService, ContainerService, Authentication) {
function HostViewController($q, SystemService, Notifications, StateManager, AgentService, ContainerService, Authentication, EndpointProvider) {
var ctrl = this; var ctrl = this;
this.$onInit = initView; this.$onInit = initView;
@ -39,7 +40,7 @@ angular.module('portainer.docker').controller('HostViewController', [
.then(function success(data) { .then(function success(data) {
ctrl.engineDetails = buildEngineDetails(data); ctrl.engineDetails = buildEngineDetails(data);
ctrl.hostDetails = buildHostDetails(data.info); ctrl.hostDetails = buildHostDetails(data.info);
ctrl.state.offlineMode = EndpointProvider.offlineMode(); ctrl.state.offlineMode = isOfflineEndpoint(ctrl.endpoint);
ctrl.jobs = data.jobs; ctrl.jobs = data.jobs;
if (ctrl.state.isAgent && agentApiVersion > 1) { if (ctrl.state.isAgent && agentApiVersion > 1) {

View File

@ -1,5 +1,6 @@
import _ from 'lodash-es'; import _ from 'lodash-es';
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry'; import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
import { isOfflineEndpoint } from '@/portainer/helpers/endpointHelper';
angular.module('portainer.docker').controller('ImagesController', [ angular.module('portainer.docker').controller('ImagesController', [
'$scope', '$scope',
@ -11,9 +12,8 @@ angular.module('portainer.docker').controller('ImagesController', [
'HttpRequestHelper', 'HttpRequestHelper',
'FileSaver', 'FileSaver',
'Blob', 'Blob',
'EndpointProvider',
'endpoint', 'endpoint',
function ($scope, $state, Authentication, ImageService, Notifications, ModalService, HttpRequestHelper, FileSaver, Blob, EndpointProvider, endpoint) { function ($scope, $state, Authentication, ImageService, Notifications, ModalService, HttpRequestHelper, FileSaver, Blob, endpoint) {
$scope.endpoint = endpoint; $scope.endpoint = endpoint;
$scope.isAdmin = Authentication.isAdmin(); $scope.isAdmin = Authentication.isAdmin();
@ -142,7 +142,7 @@ angular.module('portainer.docker').controller('ImagesController', [
ImageService.images(true) ImageService.images(true)
.then(function success(data) { .then(function success(data) {
$scope.images = data; $scope.images = data;
$scope.offlineMode = EndpointProvider.offlineMode(); $scope.offlineMode = isOfflineEndpoint(endpoint);
}) })
.catch(function error(err) { .catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve images'); Notifications.error('Failure', err, 'Unable to retrieve images');

View File

@ -1,5 +1,6 @@
import _ from 'lodash-es'; import _ from 'lodash-es';
import DockerNetworkHelper from 'Docker/helpers/networkHelper'; import DockerNetworkHelper from 'Docker/helpers/networkHelper';
import { isOfflineEndpoint } from '@/portainer/helpers/endpointHelper';
angular.module('portainer.docker').controller('NetworksController', [ angular.module('portainer.docker').controller('NetworksController', [
'$q', '$q',
@ -8,9 +9,9 @@ angular.module('portainer.docker').controller('NetworksController', [
'NetworkService', 'NetworkService',
'Notifications', 'Notifications',
'HttpRequestHelper', 'HttpRequestHelper',
'EndpointProvider', 'endpoint',
'AgentService', 'AgentService',
function ($q, $scope, $state, NetworkService, Notifications, HttpRequestHelper, EndpointProvider, AgentService) { function ($q, $scope, $state, NetworkService, Notifications, HttpRequestHelper, endpoint, AgentService) {
$scope.removeAction = function (selectedItems) { $scope.removeAction = function (selectedItems) {
var actionCount = selectedItems.length; var actionCount = selectedItems.length;
angular.forEach(selectedItems, function (network) { angular.forEach(selectedItems, function (network) {
@ -65,7 +66,7 @@ angular.module('portainer.docker').controller('NetworksController', [
$q.all(req) $q.all(req)
.then((data) => { .then((data) => {
$scope.offlineMode = EndpointProvider.offlineMode(); $scope.offlineMode = isOfflineEndpoint(endpoint);
const networks = _.forEach(data.networks, (item) => (item.Subs = [])); const networks = _.forEach(data.networks, (item) => (item.Subs = []));
if ($scope.applicationState.endpoint.mode.agentProxy && $scope.applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE') { if ($scope.applicationState.endpoint.mode.agentProxy && $scope.applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE') {
$scope.networks = groupSwarmNetworksManagerNodesFirst(data.networks, data.agents); $scope.networks = groupSwarmNetworksManagerNodesFirst(data.networks, data.agents);

View File

@ -7,6 +7,6 @@
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<host-browser ng-if="$ctrl.node"></host-browser> <host-browser ng-if="$ctrl.node" endpoint-id="$ctrl.endpoint.Id"></host-browser>
</div> </div>
</div> </div>

View File

@ -1,4 +1,7 @@
angular.module('portainer.docker').component('nodeBrowserView', { angular.module('portainer.docker').component('nodeBrowserView', {
templateUrl: './node-browser.html', templateUrl: './node-browser.html',
controller: 'NodeBrowserController', controller: 'NodeBrowserController',
bindings: {
endpoint: '<',
},
}); });

View File

@ -22,6 +22,8 @@
show-add-action="true" show-add-action="true"
show-stack-column="true" show-stack-column="true"
refresh-callback="getServices" refresh-callback="getServices"
endpoint-public-url="endpoint.PublicURL"
endpoint-id="endpoint.Id"
></services-datatable> ></services-datatable>
</div> </div>
</div> </div>

View File

@ -8,8 +8,11 @@ angular.module('portainer.docker').controller('ServicesController', [
'TaskHelper', 'TaskHelper',
'NodeService', 'NodeService',
'ContainerService', 'ContainerService',
function ($q, $scope, ServiceService, ServiceHelper, Notifications, TaskService, TaskHelper, NodeService, ContainerService) { 'endpoint',
function ($q, $scope, ServiceService, ServiceHelper, Notifications, TaskService, TaskHelper, NodeService, ContainerService, endpoint) {
$scope.getServices = getServices; $scope.getServices = getServices;
$scope.endpoint = endpoint;
function getServices() { function getServices() {
var agentProxy = $scope.applicationState.endpoint.mode.agentProxy; var agentProxy = $scope.applicationState.endpoint.mode.agentProxy;

View File

@ -1,14 +1,13 @@
angular.module('portainer.docker').controller('BrowseVolumeController', [ angular.module('portainer.docker').controller('BrowseVolumeController', BrowseVolumeController);
'$scope',
'$transition$',
'StateManager',
function ($scope, $transition$, StateManager) {
function initView() {
$scope.volumeId = $transition$.params().id;
$scope.nodeName = $transition$.params().nodeName;
$scope.agentApiVersion = StateManager.getAgentApiVersion();
}
initView(); /* @ngInject */
}, function BrowseVolumeController($scope, $transition$, StateManager, endpoint) {
]); function initView() {
$scope.volumeId = $transition$.params().id;
$scope.nodeName = $transition$.params().nodeName;
$scope.agentApiVersion = StateManager.getAgentApiVersion();
$scope.endpointId = endpoint.Id;
}
initView();
}

View File

@ -7,6 +7,6 @@
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<volume-browser volume-id="volumeId" node-name="nodeName" is-upload-enabled="agentApiVersion > 1"></volume-browser> <volume-browser volume-id="volumeId" node-name="nodeName" is-upload-enabled="agentApiVersion > 1" endpoint-id="endpointId"></volume-browser>
</div> </div>
</div> </div>

View File

@ -1,3 +1,5 @@
import { isOfflineEndpoint } from '@/portainer/helpers/endpointHelper';
angular.module('portainer.docker').controller('VolumesController', [ angular.module('portainer.docker').controller('VolumesController', [
'$q', '$q',
'$scope', '$scope',
@ -7,11 +9,10 @@ angular.module('portainer.docker').controller('VolumesController', [
'VolumeHelper', 'VolumeHelper',
'Notifications', 'Notifications',
'HttpRequestHelper', 'HttpRequestHelper',
'EndpointProvider',
'Authentication', 'Authentication',
'ModalService', 'ModalService',
'endpoint', 'endpoint',
function ($q, $scope, $state, VolumeService, ServiceService, VolumeHelper, Notifications, HttpRequestHelper, EndpointProvider, Authentication, ModalService, endpoint) { function ($q, $scope, $state, VolumeService, ServiceService, VolumeHelper, Notifications, HttpRequestHelper, Authentication, ModalService, endpoint) {
$scope.removeAction = function (selectedItems) { $scope.removeAction = function (selectedItems) {
ModalService.confirmDeletion('Do you want to remove the selected volume(s)?', (confirmed) => { ModalService.confirmDeletion('Do you want to remove the selected volume(s)?', (confirmed) => {
if (confirmed) { if (confirmed) {
@ -52,7 +53,7 @@ angular.module('portainer.docker').controller('VolumesController', [
}) })
.then(function success(data) { .then(function success(data) {
var services = data.services; var services = data.services;
$scope.offlineMode = EndpointProvider.offlineMode(); $scope.offlineMode = isOfflineEndpoint(endpoint);
$scope.volumes = data.attached $scope.volumes = data.attached
.map(function (volume) { .map(function (volume) {
volume.dangling = false; volume.dangling = false;

View File

@ -4,5 +4,6 @@ angular.module('portainer.kubernetes').component('kubernetesApplicationConsoleVi
controllerAs: 'ctrl', controllerAs: 'ctrl',
bindings: { bindings: {
$transition$: '<', $transition$: '<',
endpoint: '<',
}, },
}); });

View File

@ -4,12 +4,11 @@ import { baseHref } from '@/portainer/helpers/pathHelper';
class KubernetesApplicationConsoleController { class KubernetesApplicationConsoleController {
/* @ngInject */ /* @ngInject */
constructor($async, $state, Notifications, KubernetesApplicationService, EndpointProvider, LocalStorage) { constructor($async, $state, Notifications, KubernetesApplicationService, LocalStorage) {
this.$async = $async; this.$async = $async;
this.$state = $state; this.$state = $state;
this.Notifications = Notifications; this.Notifications = Notifications;
this.KubernetesApplicationService = KubernetesApplicationService; this.KubernetesApplicationService = KubernetesApplicationService;
this.EndpointProvider = EndpointProvider;
this.LocalStorage = LocalStorage; this.LocalStorage = LocalStorage;
this.onInit = this.onInit.bind(this); this.onInit = this.onInit.bind(this);
@ -52,7 +51,7 @@ class KubernetesApplicationConsoleController {
connectConsole() { connectConsole() {
const params = { const params = {
token: this.LocalStorage.getJWT(), token: this.LocalStorage.getJWT(),
endpointId: this.EndpointProvider.endpointID(), endpointId: this.endpoint.Id,
namespace: this.application.ResourcePool, namespace: this.application.ResourcePool,
podName: this.podName, podName: this.podName,
containerName: this.containerName, containerName: this.containerName,

View File

@ -4,5 +4,6 @@ angular.module('portainer.kubernetes').component('kubernetesApplicationView', {
controllerAs: 'ctrl', controllerAs: 'ctrl',
bindings: { bindings: {
$transition$: '<', $transition$: '<',
endpoint: '<',
}, },
}); });

View File

@ -112,7 +112,7 @@ class KubernetesApplicationController {
KubernetesStackService, KubernetesStackService,
KubernetesPodService, KubernetesPodService,
KubernetesNodeService, KubernetesNodeService,
EndpointProvider,
StackService StackService
) { ) {
this.$async = $async; this.$async = $async;
@ -131,7 +131,6 @@ class KubernetesApplicationController {
this.KubernetesApplicationDeploymentTypes = KubernetesApplicationDeploymentTypes; this.KubernetesApplicationDeploymentTypes = KubernetesApplicationDeploymentTypes;
this.KubernetesApplicationTypes = KubernetesApplicationTypes; this.KubernetesApplicationTypes = KubernetesApplicationTypes;
this.EndpointProvider = EndpointProvider;
this.KubernetesDeploymentTypes = KubernetesDeploymentTypes; this.KubernetesDeploymentTypes = KubernetesDeploymentTypes;
this.ApplicationDataAccessPolicies = KubernetesApplicationDataAccessPolicies; this.ApplicationDataAccessPolicies = KubernetesApplicationDataAccessPolicies;
@ -365,7 +364,7 @@ class KubernetesApplicationController {
placementWarning: false, placementWarning: false,
expandedNote: false, expandedNote: false,
useIngress: false, useIngress: false,
useServerMetrics: this.EndpointProvider.currentEndpoint().Kubernetes.Configuration.UseServerMetrics, useServerMetrics: this.endpoint.Kubernetes.Configuration.UseServerMetrics,
}; };
this.state.activeTab = this.LocalStorage.getActiveTab('application'); this.state.activeTab = this.LocalStorage.getActiveTab('application');

View File

@ -2,4 +2,7 @@ angular.module('portainer.kubernetes').component('kubernetesDashboardView', {
templateUrl: './dashboard.html', templateUrl: './dashboard.html',
controller: 'KubernetesDashboardController', controller: 'KubernetesDashboardController',
controllerAs: 'ctrl', controllerAs: 'ctrl',
bindings: {
endpoint: '<',
},
}); });

View File

@ -9,7 +9,6 @@ class KubernetesDashboardController {
$async, $async,
Notifications, Notifications,
EndpointService, EndpointService,
EndpointProvider,
KubernetesResourcePoolService, KubernetesResourcePoolService,
KubernetesApplicationService, KubernetesApplicationService,
KubernetesConfigurationService, KubernetesConfigurationService,
@ -20,7 +19,6 @@ class KubernetesDashboardController {
this.$async = $async; this.$async = $async;
this.Notifications = Notifications; this.Notifications = Notifications;
this.EndpointService = EndpointService; this.EndpointService = EndpointService;
this.EndpointProvider = EndpointProvider;
this.KubernetesResourcePoolService = KubernetesResourcePoolService; this.KubernetesResourcePoolService = KubernetesResourcePoolService;
this.KubernetesApplicationService = KubernetesApplicationService; this.KubernetesApplicationService = KubernetesApplicationService;
this.KubernetesConfigurationService = KubernetesConfigurationService; this.KubernetesConfigurationService = KubernetesConfigurationService;
@ -37,16 +35,13 @@ class KubernetesDashboardController {
const isAdmin = this.Authentication.isAdmin(); const isAdmin = this.Authentication.isAdmin();
try { try {
const endpointId = this.EndpointProvider.endpointID(); const [pools, applications, configurations, volumes, tags] = await Promise.all([
const [endpoint, pools, applications, configurations, volumes, tags] = await Promise.all([
this.EndpointService.endpoint(endpointId),
this.KubernetesResourcePoolService.get(), this.KubernetesResourcePoolService.get(),
this.KubernetesApplicationService.get(), this.KubernetesApplicationService.get(),
this.KubernetesConfigurationService.get(), this.KubernetesConfigurationService.get(),
this.KubernetesVolumeService.get(), this.KubernetesVolumeService.get(),
this.TagService.tags(), this.TagService.tags(),
]); ]);
this.endpoint = endpoint;
this.applications = applications; this.applications = applications;
this.volumes = volumes; this.volumes = volumes;

View File

@ -2,4 +2,7 @@ angular.module('portainer.kubernetes').component('kubernetesDeployView', {
templateUrl: './deploy.html', templateUrl: './deploy.html',
controller: 'KubernetesDeployController', controller: 'KubernetesDeployController',
controllerAs: 'ctrl', controllerAs: 'ctrl',
bindings: {
endpoint: '<',
},
}); });

View File

@ -8,26 +8,13 @@ import { KubernetesDeployManifestTypes, KubernetesDeployBuildMethods, Kubernetes
import { buildOption } from '@/portainer/components/box-selector'; import { buildOption } from '@/portainer/components/box-selector';
class KubernetesDeployController { class KubernetesDeployController {
/* @ngInject */ /* @ngInject */
constructor( constructor($async, $state, $window, Authentication, ModalService, Notifications, KubernetesResourcePoolService, StackService, WebhookHelper, CustomTemplateService) {
$async,
$state,
$window,
Authentication,
ModalService,
Notifications,
EndpointProvider,
KubernetesResourcePoolService,
StackService,
WebhookHelper,
CustomTemplateService
) {
this.$async = $async; this.$async = $async;
this.$state = $state; this.$state = $state;
this.$window = $window; this.$window = $window;
this.Authentication = Authentication; this.Authentication = Authentication;
this.ModalService = ModalService; this.ModalService = ModalService;
this.Notifications = Notifications; this.Notifications = Notifications;
this.EndpointProvider = EndpointProvider;
this.KubernetesResourcePoolService = KubernetesResourcePoolService; this.KubernetesResourcePoolService = KubernetesResourcePoolService;
this.StackService = StackService; this.StackService = StackService;
this.WebhookHelper = WebhookHelper; this.WebhookHelper = WebhookHelper;
@ -73,7 +60,6 @@ class KubernetesDeployController {
this.ManifestDeployTypes = KubernetesDeployManifestTypes; this.ManifestDeployTypes = KubernetesDeployManifestTypes;
this.BuildMethods = KubernetesDeployBuildMethods; this.BuildMethods = KubernetesDeployBuildMethods;
this.endpointId = this.EndpointProvider.endpointID();
this.onChangeTemplateId = this.onChangeTemplateId.bind(this); this.onChangeTemplateId = this.onChangeTemplateId.bind(this);
this.deployAsync = this.deployAsync.bind(this); this.deployAsync = this.deployAsync.bind(this);
@ -246,7 +232,7 @@ class KubernetesDeployController {
payload.ManifestURL = this.formValues.ManifestURL; payload.ManifestURL = this.formValues.ManifestURL;
} }
await this.StackService.kubernetesDeploy(this.endpointId, method, payload); await this.StackService.kubernetesDeploy(this.endpoint.Id, method, payload);
this.Notifications.success('Manifest successfully deployed'); this.Notifications.success('Manifest successfully deployed');
this.state.isEditorDirty = false; this.state.isEditorDirty = false;

View File

@ -4,5 +4,6 @@ angular.module('portainer.kubernetes').component('kubernetesResourcePoolAccessVi
controllerAs: 'ctrl', controllerAs: 'ctrl',
bindings: { bindings: {
$transition$: '<', $transition$: '<',
endpoint: '<',
}, },
}); });

View File

@ -6,15 +6,13 @@ import KubernetesConfigMapHelper from 'Kubernetes/helpers/configMapHelper';
class KubernetesResourcePoolAccessController { class KubernetesResourcePoolAccessController {
/* @ngInject */ /* @ngInject */
constructor($async, $state, Notifications, KubernetesResourcePoolService, KubernetesConfigMapService, EndpointProvider, EndpointService, GroupService, AccessService) { constructor($async, $state, Notifications, KubernetesResourcePoolService, KubernetesConfigMapService, GroupService, AccessService) {
this.$async = $async; this.$async = $async;
this.$state = $state; this.$state = $state;
this.Notifications = Notifications; this.Notifications = Notifications;
this.KubernetesResourcePoolService = KubernetesResourcePoolService; this.KubernetesResourcePoolService = KubernetesResourcePoolService;
this.KubernetesConfigMapService = KubernetesConfigMapService; this.KubernetesConfigMapService = KubernetesConfigMapService;
this.EndpointProvider = EndpointProvider;
this.EndpointService = EndpointService;
this.GroupService = GroupService; this.GroupService = GroupService;
this.AccessService = AccessService; this.AccessService = AccessService;
@ -36,6 +34,7 @@ class KubernetesResourcePoolAccessController {
* Init * Init
*/ */
async onInit() { async onInit() {
const endpoint = this.endpoint;
this.state = { this.state = {
actionInProgress: false, actionInProgress: false,
viewReady: false, viewReady: false,
@ -45,12 +44,9 @@ class KubernetesResourcePoolAccessController {
multiselectOutput: [], multiselectOutput: [],
}; };
this.endpointId = this.EndpointProvider.endpointID();
try { try {
const name = this.$transition$.params().id; const name = this.$transition$.params().id;
let [endpoint, pool, configMap] = await Promise.all([ let [pool, configMap] = await Promise.all([
this.EndpointService.endpoint(this.endpointId),
this.KubernetesResourcePoolService.get(name), this.KubernetesResourcePoolService.get(name),
this.KubernetesConfigMapService.getAccess(KubernetesPortainerConfigMapNamespace, KubernetesPortainerConfigMapConfigName), this.KubernetesConfigMapService.getAccess(KubernetesPortainerConfigMapNamespace, KubernetesPortainerConfigMapConfigName),
]); ]);

View File

@ -4,5 +4,6 @@ angular.module('portainer.kubernetes').component('kubernetesVolumesView', {
controllerAs: 'ctrl', controllerAs: 'ctrl',
bindings: { bindings: {
$transition$: '<', $transition$: '<',
endpoint: '<',
}, },
}); });

View File

@ -21,25 +21,13 @@ function computeSize(volumes) {
class KubernetesVolumesController { class KubernetesVolumesController {
/* @ngInject */ /* @ngInject */
constructor( constructor($async, $state, Notifications, Authentication, ModalService, LocalStorage, KubernetesStorageService, KubernetesVolumeService, KubernetesApplicationService) {
$async,
$state,
Notifications,
Authentication,
ModalService,
LocalStorage,
EndpointProvider,
KubernetesStorageService,
KubernetesVolumeService,
KubernetesApplicationService
) {
this.$async = $async; this.$async = $async;
this.$state = $state; this.$state = $state;
this.Notifications = Notifications; this.Notifications = Notifications;
this.Authentication = Authentication; this.Authentication = Authentication;
this.ModalService = ModalService; this.ModalService = ModalService;
this.LocalStorage = LocalStorage; this.LocalStorage = LocalStorage;
this.EndpointProvider = EndpointProvider;
this.KubernetesStorageService = KubernetesStorageService; this.KubernetesStorageService = KubernetesStorageService;
this.KubernetesVolumeService = KubernetesVolumeService; this.KubernetesVolumeService = KubernetesVolumeService;
this.KubernetesApplicationService = KubernetesApplicationService; this.KubernetesApplicationService = KubernetesApplicationService;
@ -87,7 +75,7 @@ class KubernetesVolumesController {
const [volumes, applications, storages] = await Promise.all([ const [volumes, applications, storages] = await Promise.all([
this.KubernetesVolumeService.get(), this.KubernetesVolumeService.get(),
this.KubernetesApplicationService.get(), this.KubernetesApplicationService.get(),
this.KubernetesStorageService.get(this.state.endpointId), this.KubernetesStorageService.get(this.endpoint.Id),
]); ]);
this.volumes = _.map(volumes, (volume) => { this.volumes = _.map(volumes, (volume) => {
@ -107,9 +95,7 @@ class KubernetesVolumesController {
async onInit() { async onInit() {
this.state = { this.state = {
viewReady: false, viewReady: false,
// endpointId: this.$transition$.params().endpointId, // TODO: use this when moving to endpointID in URL
currentName: this.$state.$current.name, currentName: this.$state.$current.name,
endpointId: this.EndpointProvider.endpointID(),
activeTab: this.LocalStorage.getActiveTab('volumes'), activeTab: this.LocalStorage.getActiveTab('volumes'),
isAdmin: this.Authentication.isAdmin(), isAdmin: this.Authentication.isAdmin(),
}; };

View File

@ -35,3 +35,7 @@ export default class EndpointHelper {
} }
} }
} }
export function isOfflineEndpoint(endpoint) {
return endpoint.Status !== 1;
}

View File

@ -1,26 +1,25 @@
angular.module('portainer.app').factory('Stack', [ import angular from 'angular';
'$resource',
'EndpointProvider', angular.module('portainer.app').factory('Stack', StackFactory);
'API_ENDPOINT_STACKS',
function StackFactory($resource, EndpointProvider, API_ENDPOINT_STACKS) { /* @ngInject */
'use strict'; function StackFactory($resource, API_ENDPOINT_STACKS) {
return $resource( return $resource(
API_ENDPOINT_STACKS + '/:id/:action/:subaction', API_ENDPOINT_STACKS + '/:id/:action',
{}, {},
{ {
get: { method: 'GET', params: { id: '@id' } }, get: { method: 'GET', params: { id: '@id' } },
query: { method: 'GET', isArray: true }, query: { method: 'GET', isArray: true },
create: { method: 'POST', ignoreLoadingBar: true }, create: { method: 'POST', ignoreLoadingBar: true },
update: { method: 'PUT', params: { id: '@id' }, ignoreLoadingBar: true }, update: { method: 'PUT', params: { id: '@id' }, ignoreLoadingBar: true },
associate: { method: 'PUT', params: { id: '@id', swarmId: '@swarmId', endpointId: '@endpointId', orphanedRunning: '@orphanedRunning', action: 'associate' } }, associate: { method: 'PUT', params: { id: '@id', swarmId: '@swarmId', endpointId: '@endpointId', orphanedRunning: '@orphanedRunning', action: 'associate' } },
remove: { method: 'DELETE', params: { id: '@id', external: '@external', endpointId: '@endpointId' } }, remove: { method: 'DELETE', params: { id: '@id', external: '@external', endpointId: '@endpointId' } },
getStackFile: { method: 'GET', params: { id: '@id', action: 'file' } }, getStackFile: { method: 'GET', params: { id: '@id', action: 'file' } },
migrate: { method: 'POST', params: { id: '@id', action: 'migrate', endpointId: '@endpointId' }, ignoreLoadingBar: true }, migrate: { method: 'POST', params: { id: '@id', action: 'migrate', endpointId: '@endpointId' }, ignoreLoadingBar: true },
start: { method: 'POST', params: { id: '@id', action: 'start' } }, start: { method: 'POST', params: { id: '@id', action: 'start' } },
stop: { method: 'POST', params: { id: '@id', action: 'stop' } }, stop: { method: 'POST', params: { id: '@id', action: 'stop' } },
updateGit: { method: 'PUT', params: { id: '@id', action: 'git', subaction: 'redeploy' } }, updateGit: { method: 'PUT', params: { id: '@id', action: 'git', subaction: 'redeploy' } },
updateGitStackSettings: { method: 'POST', params: { id: '@id', action: 'git' }, ignoreLoadingBar: true }, updateGitStackSettings: { method: 'POST', params: { id: '@id', action: 'git' }, ignoreLoadingBar: true },
} }
); );
}, }
]);

View File

@ -4,12 +4,13 @@ import { TemplateViewModel } from '../../models/template';
angular.module('portainer.app').factory('TemplateService', TemplateServiceFactory); angular.module('portainer.app').factory('TemplateService', TemplateServiceFactory);
/* @ngInject */ /* @ngInject */
function TemplateServiceFactory($q, Templates, TemplateHelper, EndpointProvider, ImageHelper, ContainerHelper, EndpointService) { function TemplateServiceFactory($q, Templates, TemplateHelper, ImageHelper, ContainerHelper, EndpointService) {
var service = {}; var service = {
templates,
};
service.templates = function () { function templates(endpointId) {
const deferred = $q.defer(); const deferred = $q.defer();
const endpointId = EndpointProvider.currentEndpoint().Id;
$q.all({ $q.all({
templates: Templates.query().$promise, templates: Templates.query().$promise,
@ -36,7 +37,7 @@ function TemplateServiceFactory($q, Templates, TemplateHelper, EndpointProvider,
}); });
return deferred.promise; return deferred.promise;
}; }
service.templateFile = templateFile; service.templateFile = templateFile;
function templateFile(repositoryUrl, composeFilePathInRepository) { function templateFile(repositoryUrl, composeFilePathInRepository) {

View File

@ -1,236 +1,226 @@
import moment from 'moment'; import moment from 'moment';
angular.module('portainer.app').factory('StateManager', [ angular.module('portainer.app').factory('StateManager', StateManagerFactory);
'$q',
'$async',
'SystemService',
'InfoHelper',
'LocalStorage',
'SettingsService',
'StatusService',
'APPLICATION_CACHE_VALIDITY',
'AgentPingService',
'$analytics',
'EndpointProvider',
function StateManagerFactory(
$q,
$async,
SystemService,
InfoHelper,
LocalStorage,
SettingsService,
StatusService,
APPLICATION_CACHE_VALIDITY,
AgentPingService,
$analytics,
EndpointProvider
) {
var manager = {};
var state = { /* @ngInject */
loading: true, function StateManagerFactory(
application: {}, $async,
endpoint: {}, $q,
UI: { SystemService,
dismissedInfoPanels: {}, InfoHelper,
dismissedInfoHash: '', LocalStorage,
}, SettingsService,
extensions: [], StatusService,
}; APPLICATION_CACHE_VALIDITY,
AgentPingService,
$analytics,
EndpointProvider
) {
var manager = {};
manager.setVersionInfo = function (versionInfo) { var state = {
state.application.versionStatus = versionInfo; loading: true,
LocalStorage.storeApplicationState(state.application); application: {},
}; endpoint: {},
UI: {
dismissedInfoPanels: {},
dismissedInfoHash: '',
},
extensions: [],
};
manager.dismissInformationPanel = function (id) { manager.setVersionInfo = function (versionInfo) {
state.UI.dismissedInfoPanels[id] = true; state.application.versionStatus = versionInfo;
LocalStorage.storeUIState(state.UI); LocalStorage.storeApplicationState(state.application);
}; };
manager.dismissImportantInformation = function (hash) { manager.dismissInformationPanel = function (id) {
state.UI.dismissedInfoHash = hash; state.UI.dismissedInfoPanels[id] = true;
LocalStorage.storeUIState(state.UI); LocalStorage.storeUIState(state.UI);
}; };
manager.getState = function () { manager.dismissImportantInformation = function (hash) {
return state; state.UI.dismissedInfoHash = hash;
}; LocalStorage.storeUIState(state.UI);
};
manager.clean = function () { manager.getState = function () {
state.endpoint = {}; return state;
state.application = {}; };
};
manager.cleanEndpoint = function () { manager.clean = function () {
state.endpoint = {}; state.endpoint = {};
EndpointProvider.clean(); state.application = {};
}; };
manager.updateLogo = function (logoURL) { manager.cleanEndpoint = function () {
state.application.logo = logoURL; state.endpoint = {};
LocalStorage.storeApplicationState(state.application); EndpointProvider.clean();
}; };
manager.updateTheme = function (theme) { manager.updateLogo = function (logoURL) {
state.application.theme = theme; state.application.logo = logoURL;
LocalStorage.storeApplicationState(state.application); LocalStorage.storeApplicationState(state.application);
}; };
manager.updateSnapshotInterval = function (interval) { manager.updateTheme = function (theme) {
state.application.snapshotInterval = interval; state.application.theme = theme;
LocalStorage.storeApplicationState(state.application); LocalStorage.storeApplicationState(state.application);
}; };
manager.updateEnableEdgeComputeFeatures = function updateEnableEdgeComputeFeatures(enableEdgeComputeFeatures) { manager.updateSnapshotInterval = function (interval) {
state.application.enableEdgeComputeFeatures = enableEdgeComputeFeatures; state.application.snapshotInterval = interval;
LocalStorage.storeApplicationState(state.application); LocalStorage.storeApplicationState(state.application);
}; };
manager.updateEnableTelemetry = function updateEnableTelemetry(enableTelemetry) { manager.updateEnableEdgeComputeFeatures = function updateEnableEdgeComputeFeatures(enableEdgeComputeFeatures) {
state.application.enableTelemetry = enableTelemetry; state.application.enableEdgeComputeFeatures = enableEdgeComputeFeatures;
$analytics.setOptOut(!enableTelemetry); LocalStorage.storeApplicationState(state.application);
LocalStorage.storeApplicationState(state.application); };
};
function assignStateFromStatusAndSettings(status, settings) { manager.updateEnableTelemetry = function updateEnableTelemetry(enableTelemetry) {
state.application.version = status.Version; state.application.enableTelemetry = enableTelemetry;
state.application.edition = status.Edition; $analytics.setOptOut(!enableTelemetry);
state.application.instanceId = status.InstanceID; LocalStorage.storeApplicationState(state.application);
};
state.application.enableTelemetry = settings.EnableTelemetry; function assignStateFromStatusAndSettings(status, settings) {
state.application.logo = settings.LogoURL; state.application.version = status.Version;
state.application.snapshotInterval = settings.SnapshotInterval; state.application.edition = status.Edition;
state.application.enableEdgeComputeFeatures = settings.EnableEdgeComputeFeatures; state.application.instanceId = status.InstanceID;
state.application.validity = moment().unix();
}
function loadApplicationState() { state.application.enableTelemetry = settings.EnableTelemetry;
var deferred = $q.defer(); state.application.logo = settings.LogoURL;
state.application.snapshotInterval = settings.SnapshotInterval;
state.application.enableEdgeComputeFeatures = settings.EnableEdgeComputeFeatures;
state.application.validity = moment().unix();
}
$q.all({ function loadApplicationState() {
settings: SettingsService.publicSettings(), var deferred = $q.defer();
status: StatusService.status(),
$q.all({
settings: SettingsService.publicSettings(),
status: StatusService.status(),
})
.then(function success(data) {
var status = data.status;
var settings = data.settings;
assignStateFromStatusAndSettings(status, settings);
LocalStorage.storeApplicationState(state.application);
deferred.resolve(state);
}) })
.then(function success(data) { .catch(function error(err) {
var status = data.status; deferred.reject({ msg: 'Unable to retrieve server settings and status', err: err });
var settings = data.settings;
assignStateFromStatusAndSettings(status, settings);
LocalStorage.storeApplicationState(state.application);
deferred.resolve(state);
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to retrieve server settings and status', err: err });
});
return deferred.promise;
}
manager.initialize = initialize;
async function initialize() {
return $async(async () => {
const UIState = LocalStorage.getUIState();
if (UIState) {
state.UI = UIState;
}
const endpointState = LocalStorage.getEndpointState();
if (endpointState) {
state.endpoint = endpointState;
}
const applicationState = LocalStorage.getApplicationState();
if (isAppStateValid(applicationState)) {
state.application = applicationState;
} else {
await loadApplicationState();
}
state.loading = false;
$analytics.setPortainerStatus(state.application.instanceId, state.application.version);
$analytics.setOptOut(!state.application.enableTelemetry);
return state;
}); });
}
function isAppStateValid(appState) { return deferred.promise;
if (!appState || !appState.validity) { }
return false;
}
const now = moment().unix();
const cacheValidity = now - appState.validity;
return cacheValidity < APPLICATION_CACHE_VALIDITY;
}
function assignExtensions(endpointExtensions) { manager.initialize = initialize;
var extensions = []; async function initialize() {
return $async(async () => {
for (var i = 0; i < endpointExtensions.length; i++) { const UIState = LocalStorage.getUIState();
var extension = endpointExtensions[i]; if (UIState) {
if (extension.Type === 1) { state.UI = UIState;
extensions.push('storidge');
}
} }
return extensions; const endpointState = LocalStorage.getEndpointState();
} if (endpointState) {
state.endpoint = endpointState;
manager.updateEndpointState = function (endpoint, extensions) {
var deferred = $q.defer();
if (endpoint.Type === 3) {
state.endpoint.name = endpoint.Name;
state.endpoint.mode = { provider: 'AZURE' };
LocalStorage.storeEndpointState(state.endpoint);
deferred.resolve();
return deferred.promise;
} else if (endpoint.Type === 5 || endpoint.Type === 6 || endpoint.Type === 7) {
state.endpoint.name = endpoint.Name;
state.endpoint.mode = { provider: 'KUBERNETES' };
LocalStorage.storeEndpointState(state.endpoint);
deferred.resolve();
return deferred.promise;
} }
const reload = endpoint.Status === 1 || !endpoint.Snaphosts || !endpoint.Snaphosts.length || !endpoint.Snapshots[0].SnapshotRaw; const applicationState = LocalStorage.getApplicationState();
if (isAppStateValid(applicationState)) {
state.application = applicationState;
} else {
await loadApplicationState();
}
$q.all({ state.loading = false;
version: reload ? SystemService.version() : $q.when(endpoint.Snapshots[0].SnapshotRaw.Version), $analytics.setPortainerStatus(state.application.instanceId, state.application.version);
info: reload ? SystemService.info() : $q.when(endpoint.Snapshots[0].SnapshotRaw.Info), $analytics.setOptOut(!state.application.enableTelemetry);
}) return state;
.then(function success(data) { });
var endpointMode = InfoHelper.determineEndpointMode(data.info, endpoint.Type); }
var endpointAPIVersion = parseFloat(data.version.ApiVersion);
state.endpoint.mode = endpointMode;
state.endpoint.name = endpoint.Name;
state.endpoint.type = endpoint.Type;
state.endpoint.apiVersion = endpointAPIVersion;
state.endpoint.extensions = assignExtensions(extensions);
if (endpointMode.agentProxy && endpoint.Status === 1) { function isAppStateValid(appState) {
return AgentPingService.ping().then(function onPingSuccess(data) { if (!appState || !appState.validity) {
state.endpoint.agentApiVersion = data.version; return false;
}); }
} const now = moment().unix();
}) const cacheValidity = now - appState.validity;
.then(function () { return cacheValidity < APPLICATION_CACHE_VALIDITY;
LocalStorage.storeEndpointState(state.endpoint); }
deferred.resolve();
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to connect to the Docker environment', err: err });
})
.finally(function final() {
state.loading = false;
});
function assignExtensions(endpointExtensions) {
var extensions = [];
for (var i = 0; i < endpointExtensions.length; i++) {
var extension = endpointExtensions[i];
if (extension.Type === 1) {
extensions.push('storidge');
}
}
return extensions;
}
manager.updateEndpointState = function (endpoint, extensions) {
var deferred = $q.defer();
if (endpoint.Type === 3) {
state.endpoint.name = endpoint.Name;
state.endpoint.mode = { provider: 'AZURE' };
LocalStorage.storeEndpointState(state.endpoint);
deferred.resolve();
return deferred.promise; return deferred.promise;
}; } else if (endpoint.Type === 5 || endpoint.Type === 6 || endpoint.Type === 7) {
state.endpoint.name = endpoint.Name;
state.endpoint.mode = { provider: 'KUBERNETES' };
LocalStorage.storeEndpointState(state.endpoint);
deferred.resolve();
return deferred.promise;
}
manager.getAgentApiVersion = function getAgentApiVersion() { const reload = endpoint.Status === 1 || !endpoint.Snaphosts || !endpoint.Snaphosts.length || !endpoint.Snapshots[0].SnapshotRaw;
return state.endpoint.agentApiVersion;
};
return manager; $q.all({
}, version: reload ? SystemService.version() : $q.when(endpoint.Snapshots[0].SnapshotRaw.Version),
]); info: reload ? SystemService.info() : $q.when(endpoint.Snapshots[0].SnapshotRaw.Info),
})
.then(function success(data) {
var endpointMode = InfoHelper.determineEndpointMode(data.info, endpoint.Type);
var endpointAPIVersion = parseFloat(data.version.ApiVersion);
state.endpoint.mode = endpointMode;
state.endpoint.name = endpoint.Name;
state.endpoint.type = endpoint.Type;
state.endpoint.apiVersion = endpointAPIVersion;
state.endpoint.extensions = assignExtensions(extensions);
if (endpointMode.agentProxy && endpoint.Status === 1) {
return AgentPingService.ping().then(function onPingSuccess(data) {
state.endpoint.agentApiVersion = data.version;
});
}
})
.then(function () {
LocalStorage.storeEndpointState(state.endpoint);
deferred.resolve();
})
.catch(function error(err) {
deferred.reject({ msg: 'Unable to connect to the Docker environment', err: err });
})
.finally(function final() {
state.loading = false;
});
return deferred.promise;
};
manager.getAgentApiVersion = function getAgentApiVersion() {
return state.endpoint.agentApiVersion;
};
return manager;
}

View File

@ -11,7 +11,6 @@ class CustomTemplatesViewController {
$state, $state,
Authentication, Authentication,
CustomTemplateService, CustomTemplateService,
EndpointProvider,
FormValidator, FormValidator,
ModalService, ModalService,
NetworkService, NetworkService,
@ -26,7 +25,6 @@ class CustomTemplatesViewController {
this.$state = $state; this.$state = $state;
this.Authentication = Authentication; this.Authentication = Authentication;
this.CustomTemplateService = CustomTemplateService; this.CustomTemplateService = CustomTemplateService;
this.EndpointProvider = EndpointProvider;
this.FormValidator = FormValidator; this.FormValidator = FormValidator;
this.ModalService = ModalService; this.ModalService = ModalService;
this.NetworkService = NetworkService; this.NetworkService = NetworkService;
@ -132,7 +130,7 @@ class CustomTemplatesViewController {
} }
const stackName = this.formValues.name; const stackName = this.formValues.name;
const endpointId = this.EndpointProvider.endpointID(); const endpointId = this.endpoint.Id;
this.state.actionInProgress = true; this.state.actionInProgress = true;

View File

@ -3,4 +3,7 @@ import CustomTemplatesViewController from './customTemplatesViewController.js';
angular.module('portainer.app').component('customTemplatesView', { angular.module('portainer.app').component('customTemplatesView', {
templateUrl: './customTemplatesView.html', templateUrl: './customTemplatesView.html',
controller: CustomTemplatesViewController, controller: CustomTemplatesViewController,
bindings: {
endpoint: '<',
},
}); });

View File

@ -19,7 +19,6 @@ function EndpointController(
EndpointService, EndpointService,
GroupService, GroupService,
TagService, TagService,
EndpointProvider,
Notifications, Notifications,
Authentication, Authentication,
SettingsService, SettingsService,
@ -191,7 +190,6 @@ function EndpointController(
EndpointService.updateEndpoint(endpoint.Id, payload).then( EndpointService.updateEndpoint(endpoint.Id, payload).then(
function success() { function success() {
Notifications.success('Environment updated', $scope.endpoint.Name); Notifications.success('Environment updated', $scope.endpoint.Name);
EndpointProvider.setEndpointPublicURL(endpoint.PublicURL);
$state.go('portainer.endpoints', {}, { reload: true }); $state.go('portainer.endpoints', {}, { reload: true });
}, },
function error(err) { function error(err) {

View File

@ -9,12 +9,11 @@ require('./includes/agent.html');
class InitEndpointController { class InitEndpointController {
/* @ngInject */ /* @ngInject */
constructor($async, $scope, $state, EndpointService, EndpointProvider, StateManager, Notifications) { constructor($async, $scope, $state, EndpointService, StateManager, Notifications) {
this.$async = $async; this.$async = $async;
this.$scope = $scope; this.$scope = $scope;
this.$state = $state; this.$state = $state;
this.EndpointService = EndpointService; this.EndpointService = EndpointService;
this.EndpointProvider = EndpointProvider;
this.StateManager = StateManager; this.StateManager = StateManager;
this.Notifications = Notifications; this.Notifications = Notifications;

View File

@ -3,8 +3,8 @@ import { RegistryCreateFormValues } from 'Portainer/models/registry';
class CreateRegistryController { class CreateRegistryController {
/* @ngInject */ /* @ngInject */
constructor($async, $state, EndpointProvider, Notifications, RegistryService, RegistryGitlabService) { constructor($async, $state, Notifications, RegistryService, RegistryGitlabService) {
Object.assign(this, { $async, $state, EndpointProvider, Notifications, RegistryService, RegistryGitlabService }); Object.assign(this, { $async, $state, Notifications, RegistryService, RegistryGitlabService });
this.RegistryTypes = RegistryTypes; this.RegistryTypes = RegistryTypes;
this.state = { this.state = {
@ -17,6 +17,7 @@ class CreateRegistryController {
selectedItems: [], selectedItems: [],
}, },
originViewReference: 'portainer.registries', originViewReference: 'portainer.registries',
originalEndpointId: null,
}; };
this.createRegistry = this.createRegistry.bind(this); this.createRegistry = this.createRegistry.bind(this);
@ -105,7 +106,7 @@ class CreateRegistryController {
this.state.actionInProgress = true; this.state.actionInProgress = true;
await this.RegistryService.createGitlabRegistries(this.model, this.state.gitlab.selectedItems); await this.RegistryService.createGitlabRegistries(this.model, this.state.gitlab.selectedItems);
this.Notifications.success('Registries successfully created'); this.Notifications.success('Registries successfully created');
this.$state.go(this.state.originViewReference, { endpointId: this.EndpointProvider.endpointID() }); this.$state.go(this.state.originViewReference, { endpointId: this.state.originalEndpointId });
} catch (err) { } catch (err) {
this.Notifications.error('Failure', err, 'Unable to create registries'); this.Notifications.error('Failure', err, 'Unable to create registries');
this.state.actionInProgress = false; this.state.actionInProgress = false;
@ -119,7 +120,7 @@ class CreateRegistryController {
this.state.actionInProgress = true; this.state.actionInProgress = true;
await this.RegistryService.createRegistry(this.model); await this.RegistryService.createRegistry(this.model);
this.Notifications.success('Registry successfully created'); this.Notifications.success('Registry successfully created');
this.$state.go(this.state.originViewReference, { endpointId: this.EndpointProvider.endpointID() }); this.$state.go(this.state.originViewReference, { endpointId: this.state.originalEndpointId });
} catch (err) { } catch (err) {
this.Notifications.error('Failure', err, 'Unable to create registry'); this.Notifications.error('Failure', err, 'Unable to create registry');
this.state.actionInProgress = false; this.state.actionInProgress = false;
@ -130,9 +131,12 @@ class CreateRegistryController {
$onInit() { $onInit() {
this.model = new RegistryCreateFormValues(); this.model = new RegistryCreateFormValues();
const origin = this.$transition$.originalTransition().from(); const from = this.$transition$.from();
if (origin.name && /^[a-z]+\.registries$/.test(origin.name)) { const params = this.$transition$.params('from');
this.state.originViewReference = origin;
if (from.name && /^[a-z]+\.registries$/.test(from.name)) {
this.state.originViewReference = from;
this.state.originalEndpointId = params.endpointId || null;
} }
} }
} }

View File

@ -19,13 +19,13 @@ angular
FormValidator, FormValidator,
ResourceControlService, ResourceControlService,
FormHelper, FormHelper,
EndpointProvider,
StackHelper, StackHelper,
ContainerHelper, ContainerHelper,
CustomTemplateService, CustomTemplateService,
ContainerService, ContainerService,
WebhookHelper, WebhookHelper,
clipboard clipboard,
endpoint
) { ) {
$scope.onChangeTemplateId = onChangeTemplateId; $scope.onChangeTemplateId = onChangeTemplateId;
$scope.buildAnalyticsProperties = buildAnalyticsProperties; $scope.buildAnalyticsProperties = buildAnalyticsProperties;
@ -307,12 +307,7 @@ angular
$scope.state.StackType = 1; $scope.state.StackType = 1;
} }
try { $scope.composeSyntaxMaxVersion = endpoint.ComposeSyntaxMaxVersion;
const endpoint = EndpointProvider.currentEndpoint();
$scope.composeSyntaxMaxVersion = endpoint.ComposeSyntaxMaxVersion;
} catch (err) {
Notifications.error('Failure', err, 'Unable to retrieve the ComposeSyntaxMaxVersion');
}
try { try {
const containers = await ContainerService.containers(true); const containers = await ContainerService.containers(true);

View File

@ -116,7 +116,7 @@
ng-if="regular && endpoints.length > 0" ng-if="regular && endpoints.length > 0"
endpoints="endpoints" endpoints="endpoints"
groups="groups" groups="groups"
current-endpoint-id="currentEndpointId" current-endpoint-id="endpoint.Id"
on-duplicate="duplicateStack(name, endpointId)" on-duplicate="duplicateStack(name, endpointId)"
on-migrate="migrateStack(name, endpointId)" on-migrate="migrateStack(name, endpointId)"
yaml-error="state.yamlError" yaml-error="state.yamlError"
@ -216,6 +216,7 @@
show-host-column="false" show-host-column="false"
show-add-action="false" show-add-action="false"
not-auto-focus="true" not-auto-focus="true"
endpoint-public-url="endpoint.PublicURL"
></containers-datatable> ></containers-datatable>
</div> </div>
</div> </div>
@ -236,6 +237,8 @@
show-add-action="false" show-add-action="false"
show-stack-column="false" show-stack-column="false"
not-auto-focus="true" not-auto-focus="true"
endpoint-public-url="endpoint.PublicURL"
endpoint-id="endpoint.Id"
></services-datatable> ></services-datatable>
</div> </div>
</div> </div>

View File

@ -24,6 +24,7 @@ angular.module('portainer.app').controller('StackController', [
'ResourceControlService', 'ResourceControlService',
'Authentication', 'Authentication',
'ContainerHelper', 'ContainerHelper',
'endpoint',
function ( function (
$async, $async,
$q, $q,
@ -47,8 +48,10 @@ angular.module('portainer.app').controller('StackController', [
StackHelper, StackHelper,
ResourceControlService, ResourceControlService,
Authentication, Authentication,
ContainerHelper ContainerHelper,
endpoint
) { ) {
$scope.endpoint = endpoint;
$scope.state = { $scope.state = {
actionInProgress: false, actionInProgress: false,
migrationInProgress: false, migrationInProgress: false,
@ -79,16 +82,18 @@ angular.module('portainer.app').controller('StackController', [
$scope.formValues.Env = value; $scope.formValues.Env = value;
} }
$scope.duplicateStack = function duplicateStack(name, endpointId) { $scope.duplicateStack = function duplicateStack(name, targetEndpointId) {
var stack = $scope.stack; var stack = $scope.stack;
var env = FormHelper.removeInvalidEnvVars($scope.formValues.Env); var env = FormHelper.removeInvalidEnvVars($scope.formValues.Env);
EndpointProvider.setEndpointID(endpointId); // sets the targetEndpointID as global for interceptors
EndpointProvider.setEndpointID(targetEndpointId);
return StackService.duplicateStack(name, $scope.stackFileContent, env, endpointId, stack.Type).then(onDuplicationSuccess).catch(notifyOnError); return StackService.duplicateStack(name, $scope.stackFileContent, env, targetEndpointId, stack.Type).then(onDuplicationSuccess).catch(notifyOnError);
function onDuplicationSuccess() { function onDuplicationSuccess() {
Notifications.success('Stack successfully duplicated'); Notifications.success('Stack successfully duplicated');
$state.go('docker.stacks', {}, { reload: true }); $state.go('docker.stacks', {}, { reload: true });
// sets back the original endpointID as global for interceptors
EndpointProvider.setEndpointID(stack.EndpointId); EndpointProvider.setEndpointID(stack.EndpointId);
} }
@ -132,11 +137,10 @@ angular.module('portainer.app').controller('StackController', [
}); });
}; };
function migrateStack(name, endpointId) { function migrateStack(name, targetEndpointId) {
var stack = $scope.stack; const stack = $scope.stack;
var targetEndpointId = endpointId;
var migrateRequest = StackService.migrateSwarmStack; let migrateRequest = StackService.migrateSwarmStack;
if (stack.Type === 2) { if (stack.Type === 2) {
migrateRequest = StackService.migrateComposeStack; migrateRequest = StackService.migrateComposeStack;
} }
@ -145,9 +149,8 @@ angular.module('portainer.app').controller('StackController', [
// The EndpointID property is not available for these stacks, we can pass // The EndpointID property is not available for these stacks, we can pass
// the current endpoint identifier as a part of the migrate request. It will be used if // the current endpoint identifier as a part of the migrate request. It will be used if
// the EndpointID property is not defined on the stack. // the EndpointID property is not defined on the stack.
var originalEndpointId = EndpointProvider.endpointID();
if (stack.EndpointId === 0) { if (stack.EndpointId === 0) {
stack.EndpointId = originalEndpointId; stack.EndpointId = endpoint.Id;
} }
$scope.state.migrationInProgress = true; $scope.state.migrationInProgress = true;
@ -213,9 +216,8 @@ angular.module('portainer.app').controller('StackController', [
// The EndpointID property is not available for these stacks, we can pass // The EndpointID property is not available for these stacks, we can pass
// the current endpoint identifier as a part of the update request. It will be used if // the current endpoint identifier as a part of the update request. It will be used if
// the EndpointID property is not defined on the stack. // the EndpointID property is not defined on the stack.
var endpointId = EndpointProvider.endpointID();
if (stack.EndpointId === 0) { if (stack.EndpointId === 0) {
stack.EndpointId = endpointId; stack.EndpointId = endpoint.Id;
} }
$scope.state.actionInProgress = true; $scope.state.actionInProgress = true;
@ -433,8 +435,6 @@ angular.module('portainer.app').controller('StackController', [
var stackName = $transition$.params().name; var stackName = $transition$.params().name;
$scope.stackName = stackName; $scope.stackName = stackName;
$scope.currentEndpointId = EndpointProvider.endpointID();
const regular = $transition$.params().regular == 'true'; const regular = $transition$.params().regular == 'true';
$scope.regular = regular; $scope.regular = regular;
@ -456,12 +456,7 @@ angular.module('portainer.app').controller('StackController', [
loadStack(stackId); loadStack(stackId);
} }
try { $scope.composeSyntaxMaxVersion = endpoint.ComposeSyntaxMaxVersion;
const endpoint = EndpointProvider.currentEndpoint();
$scope.composeSyntaxMaxVersion = endpoint.ComposeSyntaxMaxVersion;
} catch (err) {
Notifications.error('Failure', err, 'Unable to retrieve the ComposeSyntaxMaxVersion');
}
$scope.stackType = $transition$.params().type; $scope.stackType = $transition$.params().type;
} }

View File

@ -1,7 +1,9 @@
import { isOfflineEndpoint } from '@/portainer/helpers/endpointHelper';
angular.module('portainer.app').controller('StacksController', StacksController); angular.module('portainer.app').controller('StacksController', StacksController);
/* @ngInject */ /* @ngInject */
function StacksController($scope, $state, Notifications, StackService, ModalService, EndpointProvider, Authentication, endpoint) { function StacksController($scope, $state, Notifications, StackService, ModalService, Authentication, endpoint) {
$scope.removeAction = function (selectedItems) { $scope.removeAction = function (selectedItems) {
ModalService.confirmDeletion('Do you want to remove the selected stack(s)? Associated services will be removed as well.', function onConfirm(confirmed) { ModalService.confirmDeletion('Do you want to remove the selected stack(s)? Associated services will be removed as well.', function onConfirm(confirmed) {
if (!confirmed) { if (!confirmed) {
@ -12,8 +14,8 @@ function StacksController($scope, $state, Notifications, StackService, ModalServ
}; };
function deleteSelectedStacks(stacks) { function deleteSelectedStacks(stacks) {
var endpointId = EndpointProvider.endpointID(); const endpointId = endpoint.Id;
var actionCount = stacks.length; let actionCount = stacks.length;
angular.forEach(stacks, function (stack) { angular.forEach(stacks, function (stack) {
StackService.remove(stack, stack.External, endpointId) StackService.remove(stack, stack.External, endpointId)
.then(function success() { .then(function success() {
@ -39,15 +41,14 @@ function StacksController($scope, $state, Notifications, StackService, ModalServ
$scope.getStacks = getStacks; $scope.getStacks = getStacks;
function getStacks() { function getStacks() {
var endpointMode = $scope.applicationState.endpoint.mode; const endpointMode = $scope.applicationState.endpoint.mode;
var endpointId = EndpointProvider.endpointID(); const endpointId = endpoint.Id;
const includeOrphanedStacks = Authentication.isAdmin(); const includeOrphanedStacks = Authentication.isAdmin();
StackService.stacks(true, endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER', endpointId, includeOrphanedStacks) StackService.stacks(true, endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER', endpointId, includeOrphanedStacks)
.then(function success(data) { .then(function success(stacks) {
var stacks = data;
$scope.stacks = stacks; $scope.stacks = stacks;
$scope.offlineMode = EndpointProvider.offlineMode(); $scope.offlineMode = isOfflineEndpoint(endpoint);
}) })
.catch(function error(err) { .catch(function error(err) {
$scope.stacks = []; $scope.stacks = [];

View File

@ -276,9 +276,10 @@ angular.module('portainer.app').controller('TemplatesController', [
var endpointMode = $scope.applicationState.endpoint.mode; var endpointMode = $scope.applicationState.endpoint.mode;
var apiVersion = $scope.applicationState.endpoint.apiVersion; var apiVersion = $scope.applicationState.endpoint.apiVersion;
const endpointId = +$state.params.endpointId;
$q.all({ $q.all({
templates: TemplateService.templates(), templates: TemplateService.templates(endpointId),
volumes: VolumeService.getVolumes(), volumes: VolumeService.getVolumes(),
networks: NetworkService.networks( networks: NetworkService.networks(
endpointMode.provider === 'DOCKER_STANDALONE' || endpointMode.provider === 'DOCKER_SWARM_MODE', endpointMode.provider === 'DOCKER_STANDALONE' || endpointMode.provider === 'DOCKER_SWARM_MODE',
@ -296,7 +297,7 @@ angular.module('portainer.app').controller('TemplatesController', [
}) })
.catch(function error(err) { .catch(function error(err) {
$scope.templates = []; $scope.templates = [];
Notifications.error('Failure', err, 'An error occured during apps initialization.'); Notifications.error('Failure', err, 'An error occurred during apps initialization.');
}); });
} }