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

feat(app): limit the docker API version supported by the frontend (#11855)
Some checks are pending
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
ci / build_images (map[arch:arm platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Waiting to run
ci / build_images (map[arch:s390x platform:linux version:]) (push) Waiting to run
ci / build_manifests (push) Blocked by required conditions
/ triage (push) Waiting to run
Lint / Run linters (push) Waiting to run
Test / test-client (push) Waiting to run
Test / test-server (map[arch:amd64 platform:linux]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Waiting to run
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Waiting to run
Test / test-server (map[arch:arm64 platform:linux]) (push) Waiting to run

This commit is contained in:
LP B 2024-06-10 20:54:31 +02:00 committed by GitHub
parent 4ba16f1b04
commit 6a8e6734f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
212 changed files with 4439 additions and 3281 deletions

View file

@ -1,20 +0,0 @@
import { EnvironmentId } from '@/react/portainer/environments/types';
import { buildUrl as buildDockerUrl } from '../../proxy/queries/build-url';
import { NetworkId } from '../types';
export function buildUrl(
environmentId: EnvironmentId,
{ id, action }: { id?: NetworkId; action?: string } = {}
) {
let baseUrl = 'networks';
if (id) {
baseUrl += `/${id}`;
}
if (action) {
baseUrl += `/${action}`;
}
return buildDockerUrl(environmentId, baseUrl);
}

View file

@ -1,6 +1,7 @@
import { EnvironmentId } from '@/react/portainer/environments/types';
import { queryKeys as dockerQueryKeys } from '../../queries/utils';
import { NetworkId } from '../types';
import { NetworksQuery } from './types';
@ -9,4 +10,6 @@ export const queryKeys = {
[...dockerQueryKeys.root(environmentId), 'networks'] as const,
list: (environmentId: EnvironmentId, query: NetworksQuery) =>
[...queryKeys.base(environmentId), 'list', query] as const,
item: (environmentId: EnvironmentId, id: NetworkId) =>
[...queryKeys.base(environmentId), id] as const,
};

View file

@ -10,9 +10,8 @@ import {
} from '@/react-tools/react-query';
import { queryKeys as dockerQueryKeys } from '../../queries/utils';
import { addNodeHeader } from '../../proxy/addNodeHeader';
import { buildUrl } from './buildUrl';
import { withAgentTargetHeader } from '../../proxy/queries/utils';
import { buildDockerProxyUrl } from '../../proxy/queries/buildDockerProxyUrl';
interface ConnectContainerPayload {
Container: string;
@ -40,6 +39,9 @@ interface ConnectContainer {
nodeName?: string;
}
/**
* Raw docker API proxy
*/
export async function connectContainer({
environmentId,
containerId,
@ -56,13 +58,11 @@ export async function connectContainer({
};
}
const headers = addNodeHeader(nodeName);
try {
await axios.post(
buildUrl(environmentId, { id: networkId, action: 'connect' }),
buildDockerProxyUrl(environmentId, 'networks', networkId, 'connect'),
payload,
{ headers }
{ headers: { ...withAgentTargetHeader(nodeName) } }
);
} catch (err) {
throw parseAxiosError(err, 'Unable to connect container');

View file

@ -0,0 +1,91 @@
import { Network } from 'docker-types/generated/1.41';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { EnvironmentId } from '@/react/portainer/environments/types';
import { buildDockerProxyUrl } from '../../proxy/queries/buildDockerProxyUrl';
import {
withAgentManagerOperationHeader,
withAgentTargetHeader,
} from '../../proxy/queries/utils';
type MacvlanConfigOnly = {
ConfigOnly: true;
Internal: false;
Attachable: false;
Options: {
parent: string; // parent network card
};
};
type MacvlanConfigFrom = {
ConfigFrom: {
Network: string;
};
Scope: 'swarm' | 'local';
};
type NetworkConfigBase = {
Name: Required<Network>['Name'];
CheckDuplicate?: boolean;
Driver?: string;
Internal?: boolean;
Attachable?: boolean;
Ingress?: boolean;
IPAM?: Network['IPAM'];
EnableIPv6?: boolean;
Options?: Network['Options'];
Labels?: Network['Labels'];
};
/**
* This type definition of NetworkConfig doesnt enforce the usage of only one type of the union
* and not a mix of fields of the unionised types.
* e.g. the following is valid for TS while it is not for the Docker API
*
* const config: NetworkConfig = {
* Name: 'my-network', // shared
* ConfigOnly: true, // MacvlanConfigOnly
* Scope: 'swarm', // MacvlanConfigFrom
* }
*
*/
type NetworkConfig =
| NetworkConfigBase
| (NetworkConfigBase & MacvlanConfigOnly)
| (NetworkConfigBase & MacvlanConfigFrom);
type CreateOptions = {
nodeName?: string;
agentManagerOperation?: boolean;
};
type CreateNetworkResponse = {
Id: string;
Warning: string;
};
/**
* Raw docker API proxy
*/
export async function createNetwork(
environmentId: EnvironmentId,
networkConfig: NetworkConfig,
{ nodeName, agentManagerOperation }: CreateOptions = {}
) {
try {
const { data } = await axios.post<CreateNetworkResponse>(
buildDockerProxyUrl(environmentId, 'networks', 'create'),
networkConfig,
{
headers: {
...withAgentTargetHeader(nodeName),
...withAgentManagerOperationHeader(agentManagerOperation),
},
}
);
return data;
} catch (err) {
throw parseAxiosError(err, 'Unable to create network');
}
}

View file

@ -0,0 +1,47 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import {
mutationOptions,
withError,
withInvalidate,
} from '@/react-tools/react-query';
import { EnvironmentId } from '@/react/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { buildDockerProxyUrl } from '../../proxy/queries/buildDockerProxyUrl';
import { NetworkId } from '../types';
import { queryKeys } from './queryKeys';
export function useDeleteNetwork(environmentId: EnvironmentId) {
const queryClient = useQueryClient();
return useMutation(
({ networkId }: { networkId: NetworkId }) =>
deleteNetwork(environmentId, networkId),
mutationOptions(
withInvalidate(queryClient, [queryKeys.base(environmentId)]),
withError('Unable to remove network')
)
);
}
/**
* Raw docker API proxy
* @param environmentId
* @param networkId
* @returns
*/
export async function deleteNetwork(
environmentId: EnvironmentId,
networkId: NetworkId
) {
try {
await axios.delete(
buildDockerProxyUrl(environmentId, 'networks', networkId)
);
return networkId;
} catch (err) {
throw parseAxiosError(err, 'Unable to remove network');
}
}

View file

@ -0,0 +1,60 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { EnvironmentId } from '@/react/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import {
mutationOptions,
withError,
withInvalidate,
} from '@/react-tools/react-query';
import { buildDockerProxyUrl } from '../../proxy/queries/buildDockerProxyUrl';
import { ContainerId } from '../../containers/types';
import { NetworkId } from '../types';
import { queryKeys } from './queryKeys';
export function useDisconnectContainer({
environmentId,
networkId,
}: {
environmentId: EnvironmentId;
networkId: NetworkId;
}) {
const client = useQueryClient();
return useMutation(
({ containerId }: { containerId: ContainerId }) =>
disconnectContainer(environmentId, networkId, containerId),
mutationOptions(
withInvalidate(client, [queryKeys.item(environmentId, networkId)]),
withError('Unable to disconnect container from network')
)
);
}
/**
* Raw docker API proxy
* @param environmentId
* @param networkId
* @param containerId
* @returns
*/
export async function disconnectContainer(
environmentId: EnvironmentId,
networkId: NetworkId,
containerId: ContainerId
) {
try {
await axios.post(
buildDockerProxyUrl(environmentId, 'networks', networkId, 'disconnect'),
{
Container: containerId,
Force: false,
}
);
return { networkId, environmentId };
} catch (err) {
throw parseAxiosError(err, 'Unable to disconnect container from network');
}
}

View file

@ -0,0 +1,52 @@
import { useQuery } from '@tanstack/react-query';
import { withGlobalError } from '@/react-tools/react-query';
import { EnvironmentId } from '@/react/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { DockerNetwork, NetworkId } from '../types';
import { buildDockerProxyUrl } from '../../proxy/queries/buildDockerProxyUrl';
import { withAgentTargetHeader } from '../../proxy/queries/utils';
import { queryKeys } from './queryKeys';
export function useNetwork(
environmentId: EnvironmentId,
networkId: NetworkId,
{ nodeName }: { nodeName?: string } = {}
) {
return useQuery(
[...queryKeys.item(environmentId, networkId), { nodeName }],
() => getNetwork(environmentId, networkId, { nodeName }),
{
...withGlobalError('Unable to get network'),
}
);
}
/**
* Raw docker API proxy
* @param environmentId
* @param networkId
* @param param2
* @returns
*/
export async function getNetwork(
environmentId: EnvironmentId,
networkId: NetworkId,
{ nodeName }: { nodeName?: string } = {}
) {
try {
const { data: network } = await axios.get<DockerNetwork>(
buildDockerProxyUrl(environmentId, 'networks', networkId),
{
headers: {
...withAgentTargetHeader(nodeName),
},
}
);
return network;
} catch (e) {
throw parseAxiosError(e as Error, 'Unable to retrieve network details');
}
}

View file

@ -3,8 +3,9 @@ import { useQuery } from '@tanstack/react-query';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { EnvironmentId } from '@/react/portainer/environments/types';
import { buildUrl } from '../../proxy/queries/build-url';
import { DockerNetwork } from '../types';
import { withFiltersQueryParam } from '../../proxy/queries/utils';
import { buildDockerProxyUrl } from '../../proxy/queries/buildDockerProxyUrl';
import { queryKeys } from './queryKeys';
import { NetworksQuery } from './types';
@ -29,17 +30,18 @@ export function useNetworks<T = Array<DockerNetwork>>(
);
}
/**
* Raw docker API proxy
*/
export async function getNetworks(
environmentId: EnvironmentId,
{ local, swarm, swarmAttachable, filters }: NetworksQuery
) {
try {
const { data } = await axios.get<Array<DockerNetwork>>(
buildUrl(environmentId, 'networks'),
filters && {
params: {
filters,
},
buildDockerProxyUrl(environmentId, 'networks'),
{
params: { ...withFiltersQueryParam(filters) },
}
);