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:
parent
5d1b42b314
commit
a61c1004d3
8 changed files with 46 additions and 74 deletions
|
@ -7,6 +7,7 @@ import {
|
||||||
EnvironmentStatus,
|
EnvironmentStatus,
|
||||||
EnvironmentGroupId,
|
EnvironmentGroupId,
|
||||||
PlatformType,
|
PlatformType,
|
||||||
|
EdgeGroupId,
|
||||||
} from '@/react/portainer/environments/types';
|
} from '@/react/portainer/environments/types';
|
||||||
import { type TagId } from '@/portainer/tags/types';
|
import { type TagId } from '@/portainer/tags/types';
|
||||||
import { UserId } from '@/portainer/users/types';
|
import { UserId } from '@/portainer/users/types';
|
||||||
|
@ -47,6 +48,7 @@ export interface BaseEnvironmentsQueryParams {
|
||||||
updateInformation?: boolean;
|
updateInformation?: boolean;
|
||||||
edgeCheckInPassedSeconds?: number;
|
edgeCheckInPassedSeconds?: number;
|
||||||
platformTypes?: PlatformType[];
|
platformTypes?: PlatformType[];
|
||||||
|
edgeGroupIds?: EdgeGroupId[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EnvironmentsQueryParams = BaseEnvironmentsQueryParams &
|
export type EnvironmentsQueryParams = BaseEnvironmentsQueryParams &
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { DockerSnapshot } from '@/react/docker/snapshots/types';
|
||||||
|
|
||||||
export type EnvironmentGroupId = number;
|
export type EnvironmentGroupId = number;
|
||||||
|
|
||||||
|
export type EdgeGroupId = number;
|
||||||
|
|
||||||
type RoleId = number;
|
type RoleId = number;
|
||||||
interface AccessPolicy {
|
interface AccessPolicy {
|
||||||
RoleId: RoleId;
|
RoleId: RoleId;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { TextTip } from '@@/Tip/TextTip';
|
||||||
import { usePreviousVersions } from '../queries/usePreviousVersions';
|
import { usePreviousVersions } from '../queries/usePreviousVersions';
|
||||||
|
|
||||||
import { FormValues } from './types';
|
import { FormValues } from './types';
|
||||||
import { useEdgeGroupsEnvironmentIds } from './useEdgeGroupsEnvironmentIds';
|
|
||||||
|
|
||||||
export function RollbackOptions() {
|
export function RollbackOptions() {
|
||||||
const { isLoading, count, version, versionError } = useSelectVersionOnMount();
|
const { isLoading, count, version, versionError } = useSelectVersionOnMount();
|
||||||
|
@ -50,24 +49,19 @@ function useSelectVersionOnMount() {
|
||||||
errors: { version: versionError },
|
errors: { version: versionError },
|
||||||
} = useFormikContext<FormValues>();
|
} = useFormikContext<FormValues>();
|
||||||
|
|
||||||
const environmentIdsQuery = useEdgeGroupsEnvironmentIds(groupIds);
|
const previousVersionsQuery = usePreviousVersions(groupIds ?? []);
|
||||||
|
|
||||||
const previousVersionsQuery = usePreviousVersions<string[]>({
|
|
||||||
enabled: !!environmentIdsQuery.data,
|
|
||||||
});
|
|
||||||
|
|
||||||
const previousVersions = useMemo(
|
const previousVersions = useMemo(
|
||||||
() =>
|
() =>
|
||||||
previousVersionsQuery.data
|
previousVersionsQuery.data
|
||||||
? _.uniq(
|
? _.uniq(Object.values(previousVersionsQuery.data))
|
||||||
_.compact(
|
|
||||||
environmentIdsQuery.data?.map(
|
|
||||||
(envId) => previousVersionsQuery.data[envId]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
: [],
|
: [],
|
||||||
[environmentIdsQuery.data, previousVersionsQuery.data]
|
[previousVersionsQuery.data]
|
||||||
|
);
|
||||||
|
|
||||||
|
const previousVersionCount = useMemo(
|
||||||
|
() => Object.keys(previousVersions).length,
|
||||||
|
[previousVersions]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -91,7 +85,7 @@ function useSelectVersionOnMount() {
|
||||||
isLoading: previousVersionsQuery.isLoading,
|
isLoading: previousVersionsQuery.isLoading,
|
||||||
versionError,
|
versionError,
|
||||||
version,
|
version,
|
||||||
count: environmentIdsQuery.data?.length,
|
count: previousVersionCount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { NavContainer } from '@@/NavTabs/NavContainer';
|
||||||
|
|
||||||
import { ScheduleType } from '../types';
|
import { ScheduleType } from '../types';
|
||||||
|
|
||||||
import { useEdgeGroupsEnvironmentIds } from './useEdgeGroupsEnvironmentIds';
|
|
||||||
import { useEnvironments } from './useEnvironments';
|
import { useEnvironments } from './useEnvironments';
|
||||||
import { defaultValue } from './ScheduledTimeField';
|
import { defaultValue } from './ScheduledTimeField';
|
||||||
import { FormValues } from './types';
|
import { FormValues } from './types';
|
||||||
|
@ -17,10 +16,7 @@ import { RollbackScheduleDetailsFieldset } from './RollbackScheduleDetailsFields
|
||||||
export function ScheduleTypeSelector() {
|
export function ScheduleTypeSelector() {
|
||||||
const { values, setFieldValue } = useFormikContext<FormValues>();
|
const { values, setFieldValue } = useFormikContext<FormValues>();
|
||||||
|
|
||||||
const environmentIdsQuery = useEdgeGroupsEnvironmentIds(values.groupIds);
|
const environments = useEnvironments(values.groupIds);
|
||||||
|
|
||||||
const edgeGroupsEnvironmentIds = environmentIdsQuery.data || [];
|
|
||||||
const environments = useEnvironments(edgeGroupsEnvironmentIds);
|
|
||||||
|
|
||||||
// old version is version that doesn't support scheduling of updates
|
// old version is version that doesn't support scheduling of updates
|
||||||
const hasNoTimeZone = environments.some((env) => !env.LocalTimeZone);
|
const hasNoTimeZone = environments.some((env) => !env.LocalTimeZone);
|
||||||
|
|
|
@ -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]
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { useEnvironmentList } from '@/react/portainer/environments/queries/useEnvironmentList';
|
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(
|
const environmentsQuery = useEnvironmentList(
|
||||||
{ endpointIds: environmentsIds, types: EdgeTypes, pageLimit: 0 },
|
{ edgeGroupIds, types: EdgeTypes, pageLimit: 0 },
|
||||||
{
|
{
|
||||||
enabled: environmentsIds.length > 0,
|
enabled: edgeGroupIds.length > 0,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { EnvironmentId } from '@/react/portainer/environments/types';
|
import {
|
||||||
|
EdgeGroupId,
|
||||||
|
EnvironmentId,
|
||||||
|
} from '@/react/portainer/environments/types';
|
||||||
|
|
||||||
import { EdgeUpdateSchedule } from '../types';
|
import { EdgeUpdateSchedule } from '../types';
|
||||||
|
|
||||||
|
@ -11,5 +14,6 @@ export const queryKeys = {
|
||||||
[...queryKeys.base(), 'active', { environmentIds }] as const,
|
[...queryKeys.base(), 'active', { environmentIds }] as const,
|
||||||
supportedAgentVersions: () =>
|
supportedAgentVersions: () =>
|
||||||
[...queryKeys.base(), 'agent_versions'] as const,
|
[...queryKeys.base(), 'agent_versions'] as const,
|
||||||
previousVersions: () => [...queryKeys.base(), 'previous_versions'] as const,
|
previousVersions: (edgeGroupIds?: EdgeGroupId[]) =>
|
||||||
|
[...queryKeys.base(), 'previous_versions', { edgeGroupIds }] as const,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import axios, { parseAxiosError } from '@/portainer/services/axios';
|
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 { queryKeys } from './query-keys';
|
||||||
import { buildUrl } from './urls';
|
import { buildUrl } from './urls';
|
||||||
|
@ -12,22 +15,27 @@ interface Options<T> {
|
||||||
enabled?: boolean;
|
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,
|
select,
|
||||||
onSuccess,
|
enabled: enabled && edgeGroupIds.length > 0,
|
||||||
enabled,
|
}
|
||||||
}: Options<T> = {}) {
|
);
|
||||||
return useQuery(queryKeys.previousVersions(), getPreviousVersions, {
|
|
||||||
select,
|
|
||||||
onSuccess,
|
|
||||||
enabled,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getPreviousVersions() {
|
async function getPreviousVersions(edgeGroupIds: EdgeGroupId[]) {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get<Record<EnvironmentId, string>>(
|
const { data } = await axios.get<Record<EdgeGroupId, string>>(
|
||||||
buildUrl(undefined, 'previous_versions')
|
buildUrl(undefined, 'previous_versions'),
|
||||||
|
{
|
||||||
|
params: { edgeGroupIds },
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue