mirror of
https://github.com/portainer/portainer.git
synced 2025-08-08 15:25:22 +02:00
fix(edge): filtering of edge devices [EE-3210] (#7077)
* fix(edge): filtering of edge devices [EE-3210] fixes [EE-3210] changes: - replaces `edgeDeviceFilter` with two filters: - `edgeDevice` - `edgeDeviceUntrusted` these filters will only apply to the edge endpoints in the query (so it's possible to get both regular endpoints and edge devices). if `edgeDevice` is true, will filter out edge agents which are not an edge device. false, will filter out edge devices `edgeDeviceUntrusted` applies only when `edgeDevice` is true. then false (default) will hide the untrusted edge devices, true will show only untrusted edge devices. fix(edge/job-create): retrieve only trusted endpoints + fix endpoint selector pagination limits onChange fix(endpoint-groups): remove listing of untrusted edge envs (aka in waiting room) refactor(endpoints): move filter to another function feat(endpoints): separate edge filters refactor(environments): change getEnv api refactor(endpoints): use single getEnv feat(groups): show error when failed loading envs style(endpoints): remove unused endpointsByGroup * chore(deps): update go to 1.18 * fix(endpoint): filter out untrusted by default * fix(edge): show correct endpoints * style(endpoints): fix typo * fix(endpoints): fix swagger * fix(admin): use new getEnv function Co-authored-by: LP B <xAt0mZ@users.noreply.github.com>
This commit is contained in:
parent
1a8fe82821
commit
05357ecce5
28 changed files with 868 additions and 601 deletions
|
@ -11,7 +11,7 @@
|
|||
loaded="$ctrl.loaded"
|
||||
page-type="$ctrl.pageType"
|
||||
table-type="available"
|
||||
retrieve-page="$ctrl.getPaginatedEndpoints"
|
||||
retrieve-page="$ctrl.getAvailableEndpoints"
|
||||
dataset="$ctrl.endpoints.available"
|
||||
entry-click="$ctrl.associateEndpoint"
|
||||
pagination-state="$ctrl.state.available"
|
||||
|
@ -34,7 +34,7 @@
|
|||
loaded="$ctrl.loaded"
|
||||
page-type="$ctrl.pageType"
|
||||
table-type="associated"
|
||||
retrieve-page="$ctrl.getPaginatedEndpoints"
|
||||
retrieve-page="$ctrl.getAssociatedEndpoints"
|
||||
dataset="$ctrl.endpoints.associated"
|
||||
entry-click="$ctrl.dissociateEndpoint"
|
||||
pagination-state="$ctrl.state.associated"
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import angular from 'angular';
|
||||
import _ from 'lodash-es';
|
||||
|
||||
import { EdgeTypes } from '@/portainer/environments/types';
|
||||
import { getEnvironments } from '@/portainer/environments/environment.service';
|
||||
|
||||
class AssoicatedEndpointsSelectorController {
|
||||
/* @ngInject */
|
||||
constructor($async, EndpointService) {
|
||||
constructor($async) {
|
||||
this.$async = $async;
|
||||
this.EndpointService = EndpointService;
|
||||
|
||||
this.state = {
|
||||
available: {
|
||||
|
@ -27,12 +29,11 @@ class AssoicatedEndpointsSelectorController {
|
|||
available: null,
|
||||
};
|
||||
|
||||
this.getEndpoints = this.getEndpoints.bind(this);
|
||||
this.getEndpointsAsync = this.getEndpointsAsync.bind(this);
|
||||
this.getAvailableEndpoints = this.getAvailableEndpoints.bind(this);
|
||||
this.getAssociatedEndpoints = this.getAssociatedEndpoints.bind(this);
|
||||
this.getAssociatedEndpointsAsync = this.getAssociatedEndpointsAsync.bind(this);
|
||||
this.associateEndpoint = this.associateEndpoint.bind(this);
|
||||
this.dissociateEndpoint = this.dissociateEndpoint.bind(this);
|
||||
this.loadData = this.loadData.bind(this);
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
|
@ -46,41 +47,41 @@ class AssoicatedEndpointsSelectorController {
|
|||
}
|
||||
|
||||
loadData() {
|
||||
this.getAvailableEndpoints();
|
||||
this.getAssociatedEndpoints();
|
||||
this.getEndpoints();
|
||||
}
|
||||
|
||||
getEndpoints() {
|
||||
return this.$async(this.getEndpointsAsync);
|
||||
}
|
||||
/* #region internal queries to retrieve endpoints per "side" of the selector */
|
||||
getAvailableEndpoints() {
|
||||
return this.$async(async () => {
|
||||
const { start, search, limit } = this.getPaginationData('available');
|
||||
const query = { search, types: EdgeTypes };
|
||||
|
||||
async getEndpointsAsync() {
|
||||
const { start, search, limit } = this.getPaginationData('available');
|
||||
const query = { search, types: [4, 7] };
|
||||
const response = await getEnvironments({ start, limit, query });
|
||||
|
||||
const response = await this.EndpointService.endpoints(start, limit, query);
|
||||
|
||||
const endpoints = _.filter(response.value, (endpoint) => !_.includes(this.endpointIds, endpoint.Id));
|
||||
this.setTableData('available', endpoints, response.totalCount);
|
||||
this.noEndpoints = this.state.available.totalCount === 0;
|
||||
const endpoints = _.filter(response.value, (endpoint) => !_.includes(this.endpointIds, endpoint.Id));
|
||||
this.setTableData('available', endpoints, response.totalCount);
|
||||
this.noEndpoints = this.state.available.totalCount === 0;
|
||||
});
|
||||
}
|
||||
|
||||
getAssociatedEndpoints() {
|
||||
return this.$async(this.getAssociatedEndpointsAsync);
|
||||
}
|
||||
|
||||
async getAssociatedEndpointsAsync() {
|
||||
let response = { value: [], totalCount: 0 };
|
||||
if (this.endpointIds.length > 0) {
|
||||
const { start, search, limit } = this.getPaginationData('associated');
|
||||
const query = { search, types: [4, 7], endpointIds: this.endpointIds };
|
||||
|
||||
response = await this.EndpointService.endpoints(start, limit, query);
|
||||
}
|
||||
|
||||
this.setTableData('associated', response.value, response.totalCount);
|
||||
return this.$async(async () => {
|
||||
let response = { value: [], totalCount: 0 };
|
||||
if (this.endpointIds.length > 0) {
|
||||
// fetch only if already has associated endpoints
|
||||
const { start, search, limit } = this.getPaginationData('associated');
|
||||
const query = { search, types: EdgeTypes, endpointIds: this.endpointIds };
|
||||
|
||||
response = await getEnvironments({ start, limit, query });
|
||||
}
|
||||
|
||||
this.setTableData('associated', response.value, response.totalCount);
|
||||
});
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
/* #region On endpoint click (either available or associated) */
|
||||
associateEndpoint(endpoint) {
|
||||
this.onAssociate(endpoint);
|
||||
}
|
||||
|
@ -88,7 +89,9 @@ class AssoicatedEndpointsSelectorController {
|
|||
dissociateEndpoint(endpoint) {
|
||||
this.onDissociate(endpoint);
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
/* #region Utils funcs */
|
||||
getPaginationData(tableType) {
|
||||
const { pageNumber, limit, search } = this.state[tableType];
|
||||
const start = (pageNumber - 1) * limit + 1;
|
||||
|
@ -100,6 +103,7 @@ class AssoicatedEndpointsSelectorController {
|
|||
this.endpoints[tableType] = endpoints;
|
||||
this.state[tableType].totalCount = parseInt(totalCount, 10);
|
||||
}
|
||||
/* #endregion */
|
||||
}
|
||||
|
||||
angular.module('portainer.app').controller('AssoicatedEndpointsSelectorController', AssoicatedEndpointsSelectorController);
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import _ from 'lodash-es';
|
||||
import angular from 'angular';
|
||||
import { endpointsByGroup } from '@/portainer/environments/environment.service';
|
||||
import { notifyError } from '@/portainer/services/notifications';
|
||||
|
||||
class GroupFormController {
|
||||
/* @ngInject */
|
||||
constructor($q, $scope, EndpointService, GroupService, Notifications, Authentication) {
|
||||
this.$q = $q;
|
||||
constructor($async, $scope, GroupService, Notifications, Authentication) {
|
||||
this.$async = $async;
|
||||
this.$scope = $scope;
|
||||
this.EndpointService = EndpointService;
|
||||
this.GroupService = GroupService;
|
||||
this.Notifications = Notifications;
|
||||
this.Authentication = Authentication;
|
||||
|
@ -75,23 +76,27 @@ class GroupFormController {
|
|||
}
|
||||
|
||||
getPaginatedEndpointsByGroup(pageType, tableType) {
|
||||
if (tableType === 'available') {
|
||||
const context = this.state.available;
|
||||
const start = (context.pageNumber - 1) * context.limit + 1;
|
||||
this.EndpointService.endpointsByGroup(start, context.limit, context.filter, 1).then((data) => {
|
||||
this.availableEndpoints = data.value;
|
||||
this.state.available.totalCount = data.totalCount;
|
||||
});
|
||||
} else if (tableType === 'associated' && pageType === 'edit') {
|
||||
const groupId = this.model.Id ? this.model.Id : 1;
|
||||
const context = this.state.associated;
|
||||
const start = (context.pageNumber - 1) * context.limit + 1;
|
||||
this.EndpointService.endpointsByGroup(start, context.limit, context.filter, groupId).then((data) => {
|
||||
this.associatedEndpoints = data.value;
|
||||
this.state.associated.totalCount = data.totalCount;
|
||||
});
|
||||
}
|
||||
// ignore (associated + create) group as there is no backend pagination for this table
|
||||
this.$async(async () => {
|
||||
try {
|
||||
if (tableType === 'available') {
|
||||
const context = this.state.available;
|
||||
const start = (context.pageNumber - 1) * context.limit + 1;
|
||||
const data = await endpointsByGroup(1, start, context.limit, { search: context.filter });
|
||||
this.availableEndpoints = data.value;
|
||||
this.state.available.totalCount = data.totalCount;
|
||||
} else if (tableType === 'associated' && pageType === 'edit') {
|
||||
const groupId = this.model.Id ? this.model.Id : 1;
|
||||
const context = this.state.associated;
|
||||
const start = (context.pageNumber - 1) * context.limit + 1;
|
||||
const data = await endpointsByGroup(groupId, start, context.limit, { search: context.filter });
|
||||
this.associatedEndpoints = data.value;
|
||||
this.state.associated.totalCount = data.totalCount;
|
||||
}
|
||||
// ignore (associated + create) group as there is no backend pagination for this table
|
||||
} catch (err) {
|
||||
notifyError('Failure', err, 'Failed getting endpoints for group');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,61 +12,50 @@ import type {
|
|||
EnvironmentStatus,
|
||||
} from '../types';
|
||||
|
||||
import { arrayToJson, buildUrl } from './utils';
|
||||
import { buildUrl } from './utils';
|
||||
|
||||
export interface EnvironmentsQueryParams {
|
||||
search?: string;
|
||||
types?: EnvironmentType[];
|
||||
types?: EnvironmentType[] | readonly EnvironmentType[];
|
||||
tagIds?: TagId[];
|
||||
endpointIds?: EnvironmentId[];
|
||||
tagsPartialMatch?: boolean;
|
||||
groupIds?: EnvironmentGroupId[];
|
||||
status?: EnvironmentStatus[];
|
||||
sort?: string;
|
||||
order?: 'asc' | 'desc';
|
||||
edgeDeviceFilter?: 'all' | 'trusted' | 'untrusted' | 'none';
|
||||
edgeDevice?: boolean;
|
||||
edgeDeviceUntrusted?: boolean;
|
||||
provisioned?: boolean;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export async function getEndpoints(
|
||||
start: number,
|
||||
limit: number,
|
||||
export interface GetEnvironmentsOptions {
|
||||
start?: number;
|
||||
limit?: number;
|
||||
sort?: { by?: string; order?: 'asc' | 'desc' };
|
||||
query?: EnvironmentsQueryParams;
|
||||
}
|
||||
|
||||
export async function getEnvironments(
|
||||
{
|
||||
types,
|
||||
tagIds,
|
||||
endpointIds,
|
||||
status,
|
||||
groupIds,
|
||||
...query
|
||||
}: EnvironmentsQueryParams = {}
|
||||
start,
|
||||
limit,
|
||||
sort = { by: '', order: 'asc' },
|
||||
query = {},
|
||||
}: GetEnvironmentsOptions = { query: {} }
|
||||
) {
|
||||
if (tagIds && tagIds.length === 0) {
|
||||
if (query.tagIds && query.tagIds.length === 0) {
|
||||
return { totalCount: 0, value: <Environment[]>[] };
|
||||
}
|
||||
|
||||
const url = buildUrl();
|
||||
|
||||
const params: Record<string, unknown> = { start, limit, ...query };
|
||||
|
||||
if (types) {
|
||||
params.types = arrayToJson(types);
|
||||
}
|
||||
|
||||
if (tagIds) {
|
||||
params.tagIds = arrayToJson(tagIds);
|
||||
}
|
||||
|
||||
if (endpointIds) {
|
||||
params.endpointIds = arrayToJson(endpointIds);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
params.status = arrayToJson(status);
|
||||
}
|
||||
|
||||
if (groupIds) {
|
||||
params.groupIds = arrayToJson(groupIds);
|
||||
}
|
||||
const params: Record<string, unknown> = {
|
||||
start,
|
||||
limit,
|
||||
sort: sort.by,
|
||||
order: sort.order,
|
||||
...query,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await axios.get<Environment[]>(url, { params });
|
||||
|
@ -109,12 +98,16 @@ export async function snapshotEndpoint(id: EnvironmentId) {
|
|||
}
|
||||
|
||||
export async function endpointsByGroup(
|
||||
groupId: EnvironmentGroupId,
|
||||
start: number,
|
||||
limit: number,
|
||||
search: string,
|
||||
groupId: EnvironmentGroupId
|
||||
query: Omit<EnvironmentsQueryParams, 'groupIds'>
|
||||
) {
|
||||
return getEndpoints(start, limit, { search, groupIds: [groupId] });
|
||||
return getEnvironments({
|
||||
start,
|
||||
limit,
|
||||
query: { groupIds: [groupId], ...query },
|
||||
});
|
||||
}
|
||||
|
||||
export async function disassociateEndpoint(id: EnvironmentId) {
|
||||
|
|
|
@ -3,16 +3,21 @@ import { useQuery } from 'react-query';
|
|||
import { withError } from '@/react-tools/react-query';
|
||||
|
||||
import { EnvironmentStatus } from '../types';
|
||||
import { EnvironmentsQueryParams, getEndpoints } from '../environment.service';
|
||||
import {
|
||||
EnvironmentsQueryParams,
|
||||
getEnvironments,
|
||||
} from '../environment.service';
|
||||
|
||||
export const ENVIRONMENTS_POLLING_INTERVAL = 30000; // in ms
|
||||
|
||||
interface Query extends EnvironmentsQueryParams {
|
||||
export interface Query extends EnvironmentsQueryParams {
|
||||
page?: number;
|
||||
pageLimit?: number;
|
||||
sort?: string;
|
||||
order?: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
type GetEndpointsResponse = Awaited<ReturnType<typeof getEndpoints>>;
|
||||
type GetEndpointsResponse = Awaited<ReturnType<typeof getEnvironments>>;
|
||||
|
||||
export function refetchIfAnyOffline(data?: GetEndpointsResponse) {
|
||||
if (!data) {
|
||||
|
@ -31,7 +36,7 @@ export function refetchIfAnyOffline(data?: GetEndpointsResponse) {
|
|||
}
|
||||
|
||||
export function useEnvironmentList(
|
||||
{ page = 1, pageLimit = 100, ...query }: Query = {},
|
||||
{ page = 1, pageLimit = 100, sort, order, ...query }: Query = {},
|
||||
refetchInterval?:
|
||||
| number
|
||||
| false
|
||||
|
@ -45,12 +50,19 @@ export function useEnvironmentList(
|
|||
{
|
||||
page,
|
||||
pageLimit,
|
||||
sort,
|
||||
order,
|
||||
...query,
|
||||
},
|
||||
],
|
||||
async () => {
|
||||
const start = (page - 1) * pageLimit + 1;
|
||||
return getEndpoints(start, pageLimit, query);
|
||||
return getEnvironments({
|
||||
start,
|
||||
limit: pageLimit,
|
||||
sort: { by: sort, order },
|
||||
query,
|
||||
});
|
||||
},
|
||||
{
|
||||
staleTime,
|
||||
|
|
|
@ -20,6 +20,11 @@ export enum EnvironmentType {
|
|||
EdgeAgentOnKubernetes,
|
||||
}
|
||||
|
||||
export const EdgeTypes = [
|
||||
EnvironmentType.EdgeAgentOnDocker,
|
||||
EnvironmentType.EdgeAgentOnKubernetes,
|
||||
] as const;
|
||||
|
||||
export enum EnvironmentStatus {
|
||||
Up = 1,
|
||||
Down,
|
||||
|
|
|
@ -133,7 +133,8 @@ export function EnvironmentList({ onClickItem, onRefresh }: Props) {
|
|||
groupIds: groupFilter,
|
||||
sort: sortByFilter,
|
||||
order: sortByDescending ? 'desc' : 'asc',
|
||||
edgeDeviceFilter: 'none',
|
||||
provisioned: true,
|
||||
edgeDevice: false,
|
||||
tagsPartialMatch: true,
|
||||
},
|
||||
refetchIfAnyOffline
|
||||
|
@ -312,7 +313,7 @@ export function EnvironmentList({ onClickItem, onRefresh }: Props) {
|
|||
groupIds: groupFilter,
|
||||
sort: sortByFilter,
|
||||
order: sortByDescending ? 'desc' : 'asc',
|
||||
edgeDeviceFilter: 'none',
|
||||
edgeDevice: false,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { useState } from 'react';
|
|||
import { Download } from 'react-feather';
|
||||
|
||||
import { Environment } from '@/portainer/environments/types';
|
||||
import { EnvironmentsQueryParams } from '@/portainer/environments/environment.service/index';
|
||||
import { Query } from '@/portainer/environments/queries/useEnvironmentList';
|
||||
import { isKubernetesEnvironment } from '@/portainer/environments/utils';
|
||||
import { trackEvent } from '@/angulartics.matomo/analytics-services';
|
||||
|
||||
|
@ -14,7 +14,7 @@ import '@reach/dialog/styles.css';
|
|||
|
||||
export interface Props {
|
||||
environments: Environment[];
|
||||
envQueryParams: EnvironmentsQueryParams;
|
||||
envQueryParams: Query;
|
||||
}
|
||||
export function KubeconfigButton({ environments, envQueryParams }: Props) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import _ from 'lodash-es';
|
||||
import { isLimitedToBE } from '@/portainer/feature-flags/feature-flags.service';
|
||||
|
||||
import { getEnvironments } from '@/portainer/environments/environment.service';
|
||||
import AccessViewerPolicyModel from '../../models/access';
|
||||
|
||||
export default class AccessViewerController {
|
||||
/* @ngInject */
|
||||
constructor(Notifications, RoleService, UserService, EndpointService, GroupService, TeamService, TeamMembershipService, Authentication) {
|
||||
constructor(Notifications, RoleService, UserService, GroupService, TeamService, TeamMembershipService, Authentication) {
|
||||
this.Notifications = Notifications;
|
||||
this.RoleService = RoleService;
|
||||
this.UserService = UserService;
|
||||
this.EndpointService = EndpointService;
|
||||
this.GroupService = GroupService;
|
||||
this.TeamService = TeamService;
|
||||
this.TeamMembershipService = TeamMembershipService;
|
||||
|
@ -138,7 +138,7 @@ export default class AccessViewerController {
|
|||
|
||||
this.isAdmin = this.Authentication.isAdmin();
|
||||
this.allUsers = await this.UserService.users();
|
||||
this.endpoints = _.keyBy((await this.EndpointService.endpoints()).value, 'Id');
|
||||
this.endpoints = _.keyBy((await getEnvironments()).value, 'Id');
|
||||
const groups = await this.GroupService.groups();
|
||||
this.groupUserAccessPolicies = {};
|
||||
this.groupTeamAccessPolicies = {};
|
||||
|
|
|
@ -16,14 +16,6 @@ angular.module('portainer.app').factory('EndpointService', [
|
|||
return Endpoints.get({ id: endpointID }).$promise;
|
||||
};
|
||||
|
||||
service.endpoints = function (start, limit, { search, types, tagIds, endpointIds, tagsPartialMatch } = {}) {
|
||||
if (tagIds && !tagIds.length) {
|
||||
return Promise.resolve({ value: [], totalCount: 0 });
|
||||
}
|
||||
return Endpoints.query({ start, limit, search, types: JSON.stringify(types), tagIds: JSON.stringify(tagIds), endpointIds: JSON.stringify(endpointIds), tagsPartialMatch })
|
||||
.$promise;
|
||||
};
|
||||
|
||||
service.snapshotEndpoints = function () {
|
||||
return Endpoints.snapshots({}, {}).$promise;
|
||||
};
|
||||
|
@ -32,10 +24,6 @@ angular.module('portainer.app').factory('EndpointService', [
|
|||
return Endpoints.snapshot({ id: endpointID }, {}).$promise;
|
||||
};
|
||||
|
||||
service.endpointsByGroup = function (start, limit, search, groupId) {
|
||||
return Endpoints.query({ start, limit, search, groupId }).$promise;
|
||||
};
|
||||
|
||||
service.updateAccess = function (id, userAccessPolicies, teamAccessPolicies) {
|
||||
return Endpoints.updateAccess({ id: id }, { UserAccessPolicies: userAccessPolicies, TeamAccessPolicies: teamAccessPolicies }).$promise;
|
||||
};
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
import angular from 'angular';
|
||||
import { getEnvironments } from '../environments/environment.service';
|
||||
|
||||
angular.module('portainer.app').factory('NameValidator', NameValidatorFactory);
|
||||
/* @ngInject */
|
||||
function NameValidatorFactory(EndpointService, Notifications) {
|
||||
function NameValidatorFactory(Notifications) {
|
||||
return {
|
||||
validateEnvironmentName,
|
||||
};
|
||||
|
||||
async function validateEnvironmentName(environmentName) {
|
||||
async function validateEnvironmentName(name) {
|
||||
try {
|
||||
const endpoints = await EndpointService.endpoints();
|
||||
const endpointArray = endpoints.value;
|
||||
const nameDuplicated = endpointArray.filter((item) => item.Name === environmentName);
|
||||
return nameDuplicated.length > 0;
|
||||
const endpoints = await getEnvironments({ limit: 1, name });
|
||||
return endpoints.value.length > 0;
|
||||
} catch (err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve environment details');
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import angular from 'angular';
|
||||
import uuidv4 from 'uuid/v4';
|
||||
import { getEnvironments } from '@/portainer/environments/environment.service';
|
||||
|
||||
class AuthenticationController {
|
||||
/* @ngInject */
|
||||
|
@ -12,7 +13,6 @@ class AuthenticationController {
|
|||
$window,
|
||||
Authentication,
|
||||
UserService,
|
||||
EndpointService,
|
||||
StateManager,
|
||||
Notifications,
|
||||
SettingsService,
|
||||
|
@ -28,7 +28,6 @@ class AuthenticationController {
|
|||
this.$window = $window;
|
||||
this.Authentication = Authentication;
|
||||
this.UserService = UserService;
|
||||
this.EndpointService = EndpointService;
|
||||
this.StateManager = StateManager;
|
||||
this.Notifications = Notifications;
|
||||
this.SettingsService = SettingsService;
|
||||
|
@ -119,8 +118,8 @@ class AuthenticationController {
|
|||
|
||||
async checkForEndpointsAsync() {
|
||||
try {
|
||||
const endpoints = await this.EndpointService.endpoints(0, 1);
|
||||
const isAdmin = this.Authentication.isAdmin();
|
||||
const endpoints = await getEnvironments({ limit: 1 });
|
||||
|
||||
if (this.Authentication.getUserDetails().forceChangePassword) {
|
||||
return this.$state.go('portainer.account');
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import angular from 'angular';
|
||||
import EndpointHelper from 'Portainer/helpers/endpointHelper';
|
||||
import EndpointHelper from '@/portainer/helpers/endpointHelper';
|
||||
import { getEnvironments } from '@/portainer/environments/environment.service';
|
||||
|
||||
angular.module('portainer.app').controller('EndpointsController', EndpointsController);
|
||||
|
||||
|
@ -46,10 +47,10 @@ function EndpointsController($q, $scope, $state, $async, EndpointService, GroupS
|
|||
}
|
||||
|
||||
$scope.getPaginatedEndpoints = getPaginatedEndpoints;
|
||||
function getPaginatedEndpoints(lastId, limit, search) {
|
||||
function getPaginatedEndpoints(start, limit, search) {
|
||||
const deferred = $q.defer();
|
||||
$q.all({
|
||||
endpoints: EndpointService.endpoints(lastId, limit, { search }),
|
||||
endpoints: getEnvironments({ start, limit, query: { search } }),
|
||||
groups: GroupService.groups(),
|
||||
})
|
||||
.then(function success(data) {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { getEnvironments } from '@/portainer/environments/environment.service';
|
||||
|
||||
angular.module('portainer.app').controller('InitAdminController', [
|
||||
'$scope',
|
||||
'$state',
|
||||
|
@ -6,10 +8,9 @@ angular.module('portainer.app').controller('InitAdminController', [
|
|||
'StateManager',
|
||||
'SettingsService',
|
||||
'UserService',
|
||||
'EndpointService',
|
||||
'BackupService',
|
||||
'StatusService',
|
||||
function ($scope, $state, Notifications, Authentication, StateManager, SettingsService, UserService, EndpointService, BackupService, StatusService) {
|
||||
function ($scope, $state, Notifications, Authentication, StateManager, SettingsService, UserService, BackupService, StatusService) {
|
||||
$scope.uploadBackup = uploadBackup;
|
||||
|
||||
$scope.logo = StateManager.getState().application.logo;
|
||||
|
@ -50,7 +51,7 @@ angular.module('portainer.app').controller('InitAdminController', [
|
|||
return StateManager.initialize();
|
||||
})
|
||||
.then(function () {
|
||||
return EndpointService.endpoints(0, 100);
|
||||
return getEnvironments({ limit: 100 });
|
||||
})
|
||||
.then(function success(data) {
|
||||
if (data.value.length === 0) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { ResourceControlType } from '@/portainer/access-control/types';
|
||||
import { AccessControlFormData } from 'Portainer/components/accessControlForm/porAccessControlFormModel';
|
||||
import { FeatureId } from 'Portainer/feature-flags/enums';
|
||||
import { getEnvironments } from '@/portainer/environments/environment.service';
|
||||
|
||||
angular.module('portainer.app').controller('StackController', [
|
||||
'$async',
|
||||
|
@ -20,7 +21,6 @@ angular.module('portainer.app').controller('StackController', [
|
|||
'Notifications',
|
||||
'FormHelper',
|
||||
'EndpointProvider',
|
||||
'EndpointService',
|
||||
'GroupService',
|
||||
'ModalService',
|
||||
'StackHelper',
|
||||
|
@ -46,7 +46,6 @@ angular.module('portainer.app').controller('StackController', [
|
|||
Notifications,
|
||||
FormHelper,
|
||||
EndpointProvider,
|
||||
EndpointService,
|
||||
GroupService,
|
||||
ModalService,
|
||||
StackHelper,
|
||||
|
@ -317,60 +316,62 @@ angular.module('portainer.app').controller('StackController', [
|
|||
}
|
||||
|
||||
function loadStack(id) {
|
||||
var agentProxy = $scope.applicationState.endpoint.mode.agentProxy;
|
||||
return $async(() => {
|
||||
var agentProxy = $scope.applicationState.endpoint.mode.agentProxy;
|
||||
|
||||
EndpointService.endpoints()
|
||||
.then(function success(data) {
|
||||
$scope.endpoints = data.value;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve environments');
|
||||
});
|
||||
|
||||
$q.all({
|
||||
stack: StackService.stack(id),
|
||||
groups: GroupService.groups(),
|
||||
containers: ContainerService.containers(true),
|
||||
})
|
||||
.then(function success(data) {
|
||||
var stack = data.stack;
|
||||
$scope.groups = data.groups;
|
||||
$scope.stack = stack;
|
||||
$scope.containerNames = ContainerHelper.getContainerNames(data.containers);
|
||||
|
||||
$scope.formValues.Env = $scope.stack.Env;
|
||||
|
||||
let resourcesPromise = Promise.resolve({});
|
||||
if (!stack.Status || stack.Status === 1) {
|
||||
resourcesPromise = stack.Type === 1 ? retrieveSwarmStackResources(stack.Name, agentProxy) : retrieveComposeStackResources(stack.Name);
|
||||
}
|
||||
|
||||
return $q.all({
|
||||
stackFile: StackService.getStackFile(id),
|
||||
resources: resourcesPromise,
|
||||
getEnvironments()
|
||||
.then(function success(data) {
|
||||
$scope.endpoints = data.value;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve environments');
|
||||
});
|
||||
})
|
||||
.then(function success(data) {
|
||||
const isSwarm = $scope.stack.Type === 1;
|
||||
$scope.stackFileContent = data.stackFile;
|
||||
// workaround for missing status, if stack has resources, set the status to 1 (active), otherwise to 2 (inactive) (https://github.com/portainer/portainer/issues/4422)
|
||||
if (!$scope.stack.Status) {
|
||||
$scope.stack.Status = data.resources && ((isSwarm && data.resources.services.length) || data.resources.containers.length) ? 1 : 2;
|
||||
}
|
||||
|
||||
if ($scope.stack.Status === 1) {
|
||||
if (isSwarm) {
|
||||
assignSwarmStackResources(data.resources, agentProxy);
|
||||
} else {
|
||||
assignComposeStackResources(data.resources);
|
||||
$q.all({
|
||||
stack: StackService.stack(id),
|
||||
groups: GroupService.groups(),
|
||||
containers: ContainerService.containers(true),
|
||||
})
|
||||
.then(function success(data) {
|
||||
var stack = data.stack;
|
||||
$scope.groups = data.groups;
|
||||
$scope.stack = stack;
|
||||
$scope.containerNames = ContainerHelper.getContainerNames(data.containers);
|
||||
|
||||
$scope.formValues.Env = $scope.stack.Env;
|
||||
|
||||
let resourcesPromise = Promise.resolve({});
|
||||
if (!stack.Status || stack.Status === 1) {
|
||||
resourcesPromise = stack.Type === 1 ? retrieveSwarmStackResources(stack.Name, agentProxy) : retrieveComposeStackResources(stack.Name);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.state.yamlError = StackHelper.validateYAML($scope.stackFileContent, $scope.containerNames);
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve stack details');
|
||||
});
|
||||
return $q.all({
|
||||
stackFile: StackService.getStackFile(id),
|
||||
resources: resourcesPromise,
|
||||
});
|
||||
})
|
||||
.then(function success(data) {
|
||||
const isSwarm = $scope.stack.Type === 1;
|
||||
$scope.stackFileContent = data.stackFile;
|
||||
// workaround for missing status, if stack has resources, set the status to 1 (active), otherwise to 2 (inactive) (https://github.com/portainer/portainer/issues/4422)
|
||||
if (!$scope.stack.Status) {
|
||||
$scope.stack.Status = data.resources && ((isSwarm && data.resources.services.length) || data.resources.containers.length) ? 1 : 2;
|
||||
}
|
||||
|
||||
if ($scope.stack.Status === 1) {
|
||||
if (isSwarm) {
|
||||
assignSwarmStackResources(data.resources, agentProxy);
|
||||
} else {
|
||||
assignComposeStackResources(data.resources);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.state.yamlError = StackHelper.validateYAML($scope.stackFileContent, $scope.containerNames);
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve stack details');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function retrieveSwarmStackResources(stackName, agentProxy) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue