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

fix(agent-updates): fix remote agent updates cannot be scheduled properly for large edge groups [BE-11691] (#528)

This commit is contained in:
Viktor Pettersson 2025-03-20 10:05:15 +01:00 committed by GitHub
parent 5d1b42b314
commit a61c1004d3
8 changed files with 46 additions and 74 deletions

View file

@ -7,6 +7,7 @@ import {
EnvironmentStatus,
EnvironmentGroupId,
PlatformType,
EdgeGroupId,
} from '@/react/portainer/environments/types';
import { type TagId } from '@/portainer/tags/types';
import { UserId } from '@/portainer/users/types';
@ -47,6 +48,7 @@ export interface BaseEnvironmentsQueryParams {
updateInformation?: boolean;
edgeCheckInPassedSeconds?: number;
platformTypes?: PlatformType[];
edgeGroupIds?: EdgeGroupId[];
}
export type EnvironmentsQueryParams = BaseEnvironmentsQueryParams &

View file

@ -3,6 +3,8 @@ import { DockerSnapshot } from '@/react/docker/snapshots/types';
export type EnvironmentGroupId = number;
export type EdgeGroupId = number;
type RoleId = number;
interface AccessPolicy {
RoleId: RoleId;

View file

@ -9,7 +9,6 @@ import { TextTip } from '@@/Tip/TextTip';
import { usePreviousVersions } from '../queries/usePreviousVersions';
import { FormValues } from './types';
import { useEdgeGroupsEnvironmentIds } from './useEdgeGroupsEnvironmentIds';
export function RollbackOptions() {
const { isLoading, count, version, versionError } = useSelectVersionOnMount();
@ -50,24 +49,19 @@ function useSelectVersionOnMount() {
errors: { version: versionError },
} = useFormikContext<FormValues>();
const environmentIdsQuery = useEdgeGroupsEnvironmentIds(groupIds);
const previousVersionsQuery = usePreviousVersions<string[]>({
enabled: !!environmentIdsQuery.data,
});
const previousVersionsQuery = usePreviousVersions(groupIds ?? []);
const previousVersions = useMemo(
() =>
previousVersionsQuery.data
? _.uniq(
_.compact(
environmentIdsQuery.data?.map(
(envId) => previousVersionsQuery.data[envId]
)
)
)
? _.uniq(Object.values(previousVersionsQuery.data))
: [],
[environmentIdsQuery.data, previousVersionsQuery.data]
[previousVersionsQuery.data]
);
const previousVersionCount = useMemo(
() => Object.keys(previousVersions).length,
[previousVersions]
);
useEffect(() => {
@ -91,7 +85,7 @@ function useSelectVersionOnMount() {
isLoading: previousVersionsQuery.isLoading,
versionError,
version,
count: environmentIdsQuery.data?.length,
count: previousVersionCount,
};
}

View file

@ -7,7 +7,6 @@ import { NavContainer } from '@@/NavTabs/NavContainer';
import { ScheduleType } from '../types';
import { useEdgeGroupsEnvironmentIds } from './useEdgeGroupsEnvironmentIds';
import { useEnvironments } from './useEnvironments';
import { defaultValue } from './ScheduledTimeField';
import { FormValues } from './types';
@ -17,10 +16,7 @@ import { RollbackScheduleDetailsFieldset } from './RollbackScheduleDetailsFields
export function ScheduleTypeSelector() {
const { values, setFieldValue } = useFormikContext<FormValues>();
const environmentIdsQuery = useEdgeGroupsEnvironmentIds(values.groupIds);
const edgeGroupsEnvironmentIds = environmentIdsQuery.data || [];
const environments = useEnvironments(edgeGroupsEnvironmentIds);
const environments = useEnvironments(values.groupIds);
// old version is version that doesn't support scheduling of updates
const hasNoTimeZone = environments.some((env) => !env.LocalTimeZone);

View file

@ -1,34 +0,0 @@
import _ from 'lodash';
import { useMemo } from 'react';
import { useEdgeGroups } from '@/react/edge/edge-groups/queries/useEdgeGroups';
import { EdgeGroup } from '@/react/edge/edge-groups/types';
export function useEdgeGroupsEnvironmentIds(
edgeGroupsIds: Array<EdgeGroup['Id']>
) {
const groupsQuery = useEdgeGroups({
select: (groups) =>
Object.fromEntries(groups.map((g) => [g.Id, g.Endpoints])),
});
const envIds = useMemo(
() =>
_.uniq(
_.compact(
edgeGroupsIds.flatMap((id) =>
groupsQuery.data ? groupsQuery.data[id] : []
)
)
),
[edgeGroupsIds, groupsQuery.data]
);
return useMemo(
() => ({
data: groupsQuery.data ? envIds : null,
isLoading: groupsQuery.isLoading,
}),
[envIds, groupsQuery.data, groupsQuery.isLoading]
);
}

View file

@ -1,11 +1,11 @@
import { useEnvironmentList } from '@/react/portainer/environments/queries/useEnvironmentList';
import { EdgeTypes, EnvironmentId } from '@/react/portainer/environments/types';
import { EdgeGroupId, EdgeTypes } from '@/react/portainer/environments/types';
export function useEnvironments(environmentsIds: Array<EnvironmentId>) {
export function useEnvironments(edgeGroupIds: Array<EdgeGroupId>) {
const environmentsQuery = useEnvironmentList(
{ endpointIds: environmentsIds, types: EdgeTypes, pageLimit: 0 },
{ edgeGroupIds, types: EdgeTypes, pageLimit: 0 },
{
enabled: environmentsIds.length > 0,
enabled: edgeGroupIds.length > 0,
}
);

View file

@ -1,4 +1,7 @@
import { EnvironmentId } from '@/react/portainer/environments/types';
import {
EdgeGroupId,
EnvironmentId,
} from '@/react/portainer/environments/types';
import { EdgeUpdateSchedule } from '../types';
@ -11,5 +14,6 @@ export const queryKeys = {
[...queryKeys.base(), 'active', { environmentIds }] as const,
supportedAgentVersions: () =>
[...queryKeys.base(), 'agent_versions'] as const,
previousVersions: () => [...queryKeys.base(), 'previous_versions'] as const,
previousVersions: (edgeGroupIds?: EdgeGroupId[]) =>
[...queryKeys.base(), 'previous_versions', { edgeGroupIds }] as const,
};

View file

@ -1,7 +1,10 @@
import { useQuery } from '@tanstack/react-query';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { EnvironmentId } from '@/react/portainer/environments/types';
import {
EdgeGroupId,
EnvironmentId,
} from '@/react/portainer/environments/types';
import { queryKeys } from './query-keys';
import { buildUrl } from './urls';
@ -12,22 +15,27 @@ interface Options<T> {
enabled?: boolean;
}
export function usePreviousVersions<T = Record<EnvironmentId, string>>({
export function usePreviousVersions<T = Record<EdgeGroupId, string>>(
edgeGroupIds: EdgeGroupId[],
{ select, enabled }: Options<T> = {}
) {
return useQuery(
queryKeys.previousVersions(edgeGroupIds),
() => getPreviousVersions(edgeGroupIds),
{
select,
onSuccess,
enabled,
}: Options<T> = {}) {
return useQuery(queryKeys.previousVersions(), getPreviousVersions, {
select,
onSuccess,
enabled,
});
enabled: enabled && edgeGroupIds.length > 0,
}
);
}
async function getPreviousVersions() {
async function getPreviousVersions(edgeGroupIds: EdgeGroupId[]) {
try {
const { data } = await axios.get<Record<EnvironmentId, string>>(
buildUrl(undefined, 'previous_versions')
const { data } = await axios.get<Record<EdgeGroupId, string>>(
buildUrl(undefined, 'previous_versions'),
{
params: { edgeGroupIds },
}
);
return data;
} catch (err) {