From 735f58058ded9a95b6b59ea384b91144e1645a67 Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Mon, 17 Nov 2025 14:59:12 -0500 Subject: [PATCH] feat: port conflicts --- api/generated-schema.graphql | 24 +++ .../graph/resolvers/docker/docker.model.ts | 48 ++++++ .../graph/resolvers/docker/docker.resolver.ts | 12 ++ .../resolvers/docker/docker.service.spec.ts | 79 +++++++++ .../graph/resolvers/docker/docker.service.ts | 143 +++++++++++++++ .../Docker/DockerContainerManagement.vue | 163 +++++++++++++++++- .../Docker/docker-containers.query.ts | 19 ++ web/src/composables/gql/gql.ts | 12 +- web/src/composables/gql/graphql.ts | 37 +++- 9 files changed, 528 insertions(+), 9 deletions(-) diff --git a/api/generated-schema.graphql b/api/generated-schema.graphql index 94a7d70d6..1b57db574 100644 --- a/api/generated-schema.graphql +++ b/api/generated-schema.graphql @@ -1106,6 +1106,29 @@ enum ContainerPortType { UDP } +type DockerPortConflictContainer { + id: PrefixedID! + name: String! +} + +type DockerContainerPortConflict { + privatePort: Port! + type: ContainerPortType! + containers: [DockerPortConflictContainer!]! +} + +type DockerLanPortConflict { + lanIpPort: String! + publicPort: Port + type: ContainerPortType! + containers: [DockerPortConflictContainer!]! +} + +type DockerPortConflicts { + containerPorts: [DockerContainerPortConflict!]! + lanPorts: [DockerLanPortConflict!]! +} + type ContainerHostConfig { networkMode: String! } @@ -1176,6 +1199,7 @@ type Docker implements Node { id: PrefixedID! containers(skipCache: Boolean! = false): [DockerContainer!]! networks(skipCache: Boolean! = false): [DockerNetwork!]! + portConflicts(skipCache: Boolean! = false): DockerPortConflicts! organizer(skipCache: Boolean! = false): ResolvedOrganizerV1! containerUpdateStatuses: [ExplicitStatusItem!]! } diff --git a/api/src/unraid-api/graph/resolvers/docker/docker.model.ts b/api/src/unraid-api/graph/resolvers/docker/docker.model.ts index a41c10f16..102f08637 100644 --- a/api/src/unraid-api/graph/resolvers/docker/docker.model.ts +++ b/api/src/unraid-api/graph/resolvers/docker/docker.model.ts @@ -31,6 +31,51 @@ export class ContainerPort { type!: ContainerPortType; } +@ObjectType() +export class DockerPortConflictContainer { + @Field(() => PrefixedID) + id!: string; + + @Field(() => String) + name!: string; +} + +@ObjectType() +export class DockerContainerPortConflict { + @Field(() => GraphQLPort) + privatePort!: number; + + @Field(() => ContainerPortType) + type!: ContainerPortType; + + @Field(() => [DockerPortConflictContainer]) + containers!: DockerPortConflictContainer[]; +} + +@ObjectType() +export class DockerLanPortConflict { + @Field(() => String) + lanIpPort!: string; + + @Field(() => GraphQLPort, { nullable: true }) + publicPort?: number; + + @Field(() => ContainerPortType) + type!: ContainerPortType; + + @Field(() => [DockerPortConflictContainer]) + containers!: DockerPortConflictContainer[]; +} + +@ObjectType() +export class DockerPortConflicts { + @Field(() => [DockerContainerPortConflict]) + containerPorts!: DockerContainerPortConflict[]; + + @Field(() => [DockerLanPortConflict]) + lanPorts!: DockerLanPortConflict[]; +} + export enum ContainerState { RUNNING = 'RUNNING', PAUSED = 'PAUSED', @@ -203,6 +248,9 @@ export class Docker extends Node { @Field(() => [DockerNetwork]) networks!: DockerNetwork[]; + + @Field(() => DockerPortConflicts) + portConflicts!: DockerPortConflicts; } @ObjectType() diff --git a/api/src/unraid-api/graph/resolvers/docker/docker.resolver.ts b/api/src/unraid-api/graph/resolvers/docker/docker.resolver.ts index d6e28fc52..3d764e239 100644 --- a/api/src/unraid-api/graph/resolvers/docker/docker.resolver.ts +++ b/api/src/unraid-api/graph/resolvers/docker/docker.resolver.ts @@ -16,6 +16,7 @@ import { DockerContainer, DockerContainerOverviewForm, DockerNetwork, + DockerPortConflicts, } from '@app/unraid-api/graph/resolvers/docker/docker.model.js'; import { DockerService } from '@app/unraid-api/graph/resolvers/docker/docker.service.js'; import { DockerOrganizerService } from '@app/unraid-api/graph/resolvers/docker/organizer/docker-organizer.service.js'; @@ -91,6 +92,17 @@ export class DockerResolver { return this.dockerService.getNetworks({ skipCache }); } + @UsePermissions({ + action: AuthAction.READ_ANY, + resource: Resource.DOCKER, + }) + @ResolveField(() => DockerPortConflicts) + public async portConflicts( + @Args('skipCache', { defaultValue: false, type: () => Boolean }) skipCache: boolean + ) { + return this.dockerService.getPortConflicts({ skipCache }); + } + @UsePermissions({ action: AuthAction.READ_ANY, resource: Resource.DOCKER, diff --git a/api/src/unraid-api/graph/resolvers/docker/docker.service.spec.ts b/api/src/unraid-api/graph/resolvers/docker/docker.service.spec.ts index d001f6be9..e19480d87 100644 --- a/api/src/unraid-api/graph/resolvers/docker/docker.service.spec.ts +++ b/api/src/unraid-api/graph/resolvers/docker/docker.service.spec.ts @@ -764,4 +764,83 @@ describe('DockerService', () => { expect(mockCacheManager.get).toHaveBeenCalledWith(DockerService.CONTAINER_CACHE_KEY); }); }); + + describe('getPortConflicts', () => { + it('returns empty lists when there are no conflicts', async () => { + const containers = [ + { + id: 'abc', + names: ['/abc'], + ports: [ + { privatePort: 8080, publicPort: 18080, type: ContainerPortType.TCP }, + { privatePort: 443, publicPort: 10443, type: ContainerPortType.TCP }, + ], + }, + { + id: 'def', + names: ['/def'], + ports: [{ privatePort: 3000, publicPort: 13000, type: ContainerPortType.TCP }], + }, + ] as unknown as DockerContainer[]; + + mockCacheManager.get.mockResolvedValueOnce(containers); + + const result = await service.getPortConflicts(); + expect(result.containerPorts).toEqual([]); + expect(result.lanPorts).toEqual([]); + }); + + it('detects container and LAN port conflicts separately', async () => { + mockEmhttpGetter.mockReturnValue({ + networks: [{ ipaddr: ['192.168.1.25'] }], + var: {}, + }); + const containers = [ + { + id: 'one', + names: ['/one'], + ports: [{ privatePort: 8080, publicPort: 18080, type: ContainerPortType.TCP }], + }, + { + id: 'two', + names: ['/two'], + ports: [ + { privatePort: 8080, publicPort: 28080, type: ContainerPortType.TCP }, + { privatePort: 1234, publicPort: 18080, type: ContainerPortType.TCP }, + ], + }, + { + id: 'three', + names: ['/three'], + ports: [{ privatePort: 9999, publicPort: 19999, type: ContainerPortType.UDP }], + }, + ] as unknown as DockerContainer[]; + + mockCacheManager.get.mockResolvedValueOnce(containers); + + const result = await service.getPortConflicts(); + + expect(result.containerPorts).toEqual([ + { + privatePort: 8080, + type: ContainerPortType.TCP, + containers: [ + { id: 'one', name: 'one' }, + { id: 'two', name: 'two' }, + ], + }, + ]); + expect(result.lanPorts).toEqual([ + { + lanIpPort: '192.168.1.25:18080', + publicPort: 18080, + type: ContainerPortType.TCP, + containers: [ + { id: 'one', name: 'one' }, + { id: 'two', name: 'two' }, + ], + }, + ]); + }); + }); }); diff --git a/api/src/unraid-api/graph/resolvers/docker/docker.service.ts b/api/src/unraid-api/graph/resolvers/docker/docker.service.ts index 0a8004c76..dbb2e886d 100644 --- a/api/src/unraid-api/graph/resolvers/docker/docker.service.ts +++ b/api/src/unraid-api/graph/resolvers/docker/docker.service.ts @@ -18,7 +18,11 @@ import { ContainerPortType, ContainerState, DockerContainer, + DockerContainerPortConflict, + DockerLanPortConflict, DockerNetwork, + DockerPortConflictContainer, + DockerPortConflicts, } from '@app/unraid-api/graph/resolvers/docker/docker.model.js'; import { NotificationImportance } from '@app/unraid-api/graph/resolvers/notifications/notifications.model.js'; import { NotificationsService } from '@app/unraid-api/graph/resolvers/notifications/notifications.service.js'; @@ -160,6 +164,133 @@ export class DockerService { return uniquePorts; } + private buildPortConflictContainerRef(container: DockerContainer): DockerPortConflictContainer { + const primaryName = this.getContainerPrimaryName(container); + const fallback = container.names?.[0] ?? container.id; + const normalized = typeof fallback === 'string' ? fallback.replace(/^\//, '') : container.id; + return { + id: container.id, + name: primaryName || normalized, + }; + } + + private buildContainerPortConflicts(containers: DockerContainer[]): DockerContainerPortConflict[] { + const groups = new Map< + string, + { + privatePort: number; + type: ContainerPortType; + containers: DockerContainer[]; + seen: Set; + } + >(); + + for (const container of containers) { + if (!Array.isArray(container.ports)) { + continue; + } + for (const port of container.ports) { + if (!port || typeof port.privatePort !== 'number') { + continue; + } + const type = port.type ?? ContainerPortType.TCP; + const key = `${port.privatePort}/${type}`; + let group = groups.get(key); + if (!group) { + group = { + privatePort: port.privatePort, + type, + containers: [], + seen: new Set(), + }; + groups.set(key, group); + } + if (group.seen.has(container.id)) { + continue; + } + group.seen.add(container.id); + group.containers.push(container); + } + } + + return Array.from(groups.values()) + .filter((group) => group.containers.length > 1) + .map((group) => ({ + privatePort: group.privatePort, + type: group.type, + containers: group.containers.map((container) => + this.buildPortConflictContainerRef(container) + ), + })) + .sort((a, b) => { + if (a.privatePort !== b.privatePort) { + return a.privatePort - b.privatePort; + } + return a.type.localeCompare(b.type); + }); + } + + private buildLanPortConflicts(containers: DockerContainer[]): DockerLanPortConflict[] { + const lanIp = getLanIp(); + const groups = new Map< + string, + { + lanIpPort: string; + publicPort: number; + type: ContainerPortType; + containers: DockerContainer[]; + seen: Set; + } + >(); + + for (const container of containers) { + if (!Array.isArray(container.ports)) { + continue; + } + for (const port of container.ports) { + if (!port || typeof port.publicPort !== 'number') { + continue; + } + const type = port.type ?? ContainerPortType.TCP; + const lanIpPort = lanIp ? `${lanIp}:${port.publicPort}` : `${port.publicPort}`; + const key = `${lanIpPort}/${type}`; + let group = groups.get(key); + if (!group) { + group = { + lanIpPort, + publicPort: port.publicPort, + type, + containers: [], + seen: new Set(), + }; + groups.set(key, group); + } + if (group.seen.has(container.id)) { + continue; + } + group.seen.add(container.id); + group.containers.push(container); + } + } + + return Array.from(groups.values()) + .filter((group) => group.containers.length > 1) + .map((group) => ({ + lanIpPort: group.lanIpPort, + publicPort: group.publicPort, + type: group.type, + containers: group.containers.map((container) => + this.buildPortConflictContainerRef(container) + ), + })) + .sort((a, b) => { + if ((a.publicPort ?? 0) !== (b.publicPort ?? 0)) { + return (a.publicPort ?? 0) - (b.publicPort ?? 0); + } + return a.type.localeCompare(b.type); + }); + } + public getDockerClient() { return new Docker({ socketPath: '/var/run/docker.sock', @@ -301,6 +432,18 @@ export class DockerService { return containersWithTemplatePaths; } + public async getPortConflicts({ + skipCache = false, + }: { + skipCache?: boolean; + } = {}): Promise { + const containers = await this.getContainers({ skipCache }); + return { + containerPorts: this.buildContainerPortConflicts(containers), + lanPorts: this.buildLanPortConflicts(containers), + }; + } + public async getContainerLogSizes(containerNames: string[]): Promise> { const logSizes = new Map(); if (!Array.isArray(containerNames) || containerNames.length === 0) { diff --git a/web/src/components/Docker/DockerContainerManagement.vue b/web/src/components/Docker/DockerContainerManagement.vue index 8cb9e510b..8e1269cb2 100644 --- a/web/src/components/Docker/DockerContainerManagement.vue +++ b/web/src/components/Docker/DockerContainerManagement.vue @@ -21,6 +21,29 @@ interface Props { disabled?: boolean; } +type PortConflictContainer = { + id: string; + name: string; +}; + +type LanPortConflict = { + lanIpPort: string; + publicPort?: number | null; + type: string; + containers: PortConflictContainer[]; +}; + +type ContainerPortConflict = { + privatePort: number; + type: string; + containers: PortConflictContainer[]; +}; + +type DockerPortConflictsResult = { + lanPorts: LanPortConflict[]; + containerPorts: ContainerPortConflict[]; +}; + const props = withDefaults(defineProps(), { disabled: false, }); @@ -171,20 +194,78 @@ const { result, loading, refetch } = useQuery<{ }>; }; containers: DockerContainer[]; + portConflicts: DockerPortConflictsResult; }; }>(GET_DOCKER_CONTAINERS, { fetchPolicy: 'cache-and-network', variables: { skipCache: true }, }); -const flatEntries = computed(() => result.value?.docker?.organizer?.views?.[0]?.flatEntries || []); +const flatEntries = computed( + () => result.value?.docker?.organizer?.views?.[0]?.flatEntries || [] +); const rootFolderId = computed(() => result.value?.docker?.organizer?.views?.[0]?.rootId || 'root'); const viewPrefs = computed(() => result.value?.docker?.organizer?.views?.[0]?.prefs || null); const containers = computed(() => result.value?.docker?.containers || []); +const portConflicts = computed(() => { + const dockerData = result.value?.docker; + return dockerData?.portConflicts ?? null; +}); + +const lanPortConflicts = computed(() => portConflicts.value?.lanPorts ?? []); +const containerPortConflicts = computed( + () => portConflicts.value?.containerPorts ?? [] +); + +const totalPortConflictCount = computed( + () => lanPortConflicts.value.length + containerPortConflicts.value.length +); +const hasPortConflicts = computed(() => totalPortConflictCount.value > 0); + const { navigateToEditPage } = useDockerEditNavigation(); +function getOrganizerEntryIdByContainerId(containerId: string): string | null { + const entry = flatEntries.value.find( + (candidate) => + candidate.type === 'container' && + (candidate.meta as DockerContainer | undefined)?.id === containerId + ); + return entry?.id ?? null; +} + +function focusContainerFromConflict(containerId: string) { + const entryId = getOrganizerEntryIdByContainerId(containerId); + if (!entryId) return; + setActiveContainer(entryId); +} + +function handleConflictContainerAction(conflictContainer: PortConflictContainer) { + const targetContainer = containers.value.find((container) => container.id === conflictContainer.id); + if (targetContainer && navigateToEditPage(targetContainer, conflictContainer.name)) { + return; + } + focusContainerFromConflict(conflictContainer.id); +} + +function formatLanConflictLabel(conflict: LanPortConflict): string { + if (!conflict) return ''; + const lanValue = conflict.lanIpPort?.trim?.().length + ? conflict.lanIpPort + : conflict.publicPort?.toString() || 'LAN port'; + const protocol = conflict.type || 'TCP'; + return `${lanValue} (${protocol})`; +} + +function formatContainerConflictLabel(conflict: ContainerPortConflict): string { + if (!conflict) return ''; + const containerValue = + typeof conflict.privatePort === 'number' ? conflict.privatePort : 'Container port'; + const protocol = conflict.type || 'TCP'; + return `${containerValue}/${protocol}`; +} + watch(activeId, (id) => { if (id && viewMode.value === 'autostart') { viewMode.value = 'overview'; @@ -335,6 +416,86 @@ const isDetailsDisabled = computed(() => props.disabled || isSwitching.value); +
+
+
+
; organizer: ResolvedOrganizerV1; + portConflicts: DockerPortConflicts; }; @@ -701,6 +702,11 @@ export type DockerOrganizerArgs = { skipCache?: Scalars['Boolean']['input']; }; + +export type DockerPortConflictsArgs = { + skipCache?: Scalars['Boolean']['input']; +}; + export type DockerAutostartEntryInput = { /** Whether the container should auto-start */ autoStart: Scalars['Boolean']['input']; @@ -751,6 +757,21 @@ export type DockerContainerOverviewForm = { uiSchema: Scalars['JSON']['output']; }; +export type DockerContainerPortConflict = { + __typename?: 'DockerContainerPortConflict'; + containers: Array; + privatePort: Scalars['Port']['output']; + type: ContainerPortType; +}; + +export type DockerLanPortConflict = { + __typename?: 'DockerLanPortConflict'; + containers: Array; + lanIpPort: Scalars['String']['output']; + publicPort?: Maybe; + type: ContainerPortType; +}; + export type DockerMutations = { __typename?: 'DockerMutations'; /** Pause (Suspend) a container */ @@ -824,6 +845,18 @@ export type DockerNetwork = Node & { scope: Scalars['String']['output']; }; +export type DockerPortConflictContainer = { + __typename?: 'DockerPortConflictContainer'; + id: Scalars['PrefixedID']['output']; + name: Scalars['String']['output']; +}; + +export type DockerPortConflicts = { + __typename?: 'DockerPortConflicts'; + containerPorts: Array; + lanPorts: Array; +}; + export type DockerTemplateSyncResult = { __typename?: 'DockerTemplateSyncResult'; errors: Array; @@ -2795,7 +2828,7 @@ export type GetDockerContainersQueryVariables = Exact<{ }>; -export type GetDockerContainersQuery = { __typename?: 'Query', docker: { __typename?: 'Docker', id: string, containers: Array<{ __typename?: 'DockerContainer', id: string, names: Array, state: ContainerState, status: string, image: string, created: number, lanIpPorts?: Array | null, autoStart: boolean, autoStartOrder?: number | null, autoStartWait?: number | null, networkSettings?: any | null, mounts?: Array | null, ports: Array<{ __typename?: 'ContainerPort', privatePort?: number | null, publicPort?: number | null, type: ContainerPortType }>, hostConfig?: { __typename?: 'ContainerHostConfig', networkMode: string } | null }>, organizer: { __typename?: 'ResolvedOrganizerV1', version: number, views: Array<{ __typename?: 'ResolvedOrganizerView', id: string, name: string, rootId: string, prefs?: any | null, flatEntries: Array<{ __typename?: 'FlatOrganizerEntry', id: string, type: string, name: string, parentId?: string | null, depth: number, position: number, path: Array, hasChildren: boolean, childrenIds: Array, icon?: string | null, meta?: { __typename?: 'DockerContainer', id: string, names: Array, state: ContainerState, status: string, image: string, lanIpPorts?: Array | null, autoStart: boolean, networkSettings?: any | null, mounts?: Array | null, created: number, isUpdateAvailable?: boolean | null, isRebuildReady?: boolean | null, templatePath?: string | null, ports: Array<{ __typename?: 'ContainerPort', privatePort?: number | null, publicPort?: number | null, type: ContainerPortType }>, hostConfig?: { __typename?: 'ContainerHostConfig', networkMode: string } | null } | null }> }> } } }; +export type GetDockerContainersQuery = { __typename?: 'Query', docker: { __typename?: 'Docker', id: string, portConflicts: { __typename?: 'DockerPortConflicts', containerPorts: Array<{ __typename?: 'DockerContainerPortConflict', privatePort: number, type: ContainerPortType, containers: Array<{ __typename?: 'DockerPortConflictContainer', id: string, name: string }> }>, lanPorts: Array<{ __typename?: 'DockerLanPortConflict', lanIpPort: string, publicPort?: number | null, type: ContainerPortType, containers: Array<{ __typename?: 'DockerPortConflictContainer', id: string, name: string }> }> }, containers: Array<{ __typename?: 'DockerContainer', id: string, names: Array, state: ContainerState, status: string, image: string, created: number, lanIpPorts?: Array | null, autoStart: boolean, autoStartOrder?: number | null, autoStartWait?: number | null, networkSettings?: any | null, mounts?: Array | null, ports: Array<{ __typename?: 'ContainerPort', privatePort?: number | null, publicPort?: number | null, type: ContainerPortType }>, hostConfig?: { __typename?: 'ContainerHostConfig', networkMode: string } | null }>, organizer: { __typename?: 'ResolvedOrganizerV1', version: number, views: Array<{ __typename?: 'ResolvedOrganizerView', id: string, name: string, rootId: string, prefs?: any | null, flatEntries: Array<{ __typename?: 'FlatOrganizerEntry', id: string, type: string, name: string, parentId?: string | null, depth: number, position: number, path: Array, hasChildren: boolean, childrenIds: Array, icon?: string | null, meta?: { __typename?: 'DockerContainer', id: string, names: Array, state: ContainerState, status: string, image: string, lanIpPorts?: Array | null, autoStart: boolean, networkSettings?: any | null, mounts?: Array | null, created: number, isUpdateAvailable?: boolean | null, isRebuildReady?: boolean | null, templatePath?: string | null, ports: Array<{ __typename?: 'ContainerPort', privatePort?: number | null, publicPort?: number | null, type: ContainerPortType }>, hostConfig?: { __typename?: 'ContainerHostConfig', networkMode: string } | null } | null }> }> } } }; export type CreateDockerFolderWithItemsMutationVariables = Exact<{ name: Scalars['String']['input']; @@ -3152,7 +3185,7 @@ export const UnifiedDocument = {"kind":"Document","definitions":[{"kind":"Operat export const UpdateConnectSettingsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateConnectSettings"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"JSON"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateSettings"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"restartRequired"}},{"kind":"Field","name":{"kind":"Name","value":"values"}}]}}]}}]} as unknown as DocumentNode; export const GetDockerActiveContainerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetDockerActiveContainer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"PrefixedID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"docker"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"containers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"names"}},{"kind":"Field","name":{"kind":"Name","value":"image"}},{"kind":"Field","name":{"kind":"Name","value":"created"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"autoStart"}},{"kind":"Field","name":{"kind":"Name","value":"ports"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"privatePort"}},{"kind":"Field","name":{"kind":"Name","value":"publicPort"}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"hostConfig"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"networkMode"}}]}},{"kind":"Field","name":{"kind":"Name","value":"networkSettings"}},{"kind":"Field","name":{"kind":"Name","value":"labels"}}]}}]}}]}}]} as unknown as DocumentNode; export const GetDockerContainerSizesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetDockerContainerSizes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"docker"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"containers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"skipCache"},"value":{"kind":"BooleanValue","value":true}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"names"}},{"kind":"Field","name":{"kind":"Name","value":"sizeRootFs"}},{"kind":"Field","name":{"kind":"Name","value":"sizeRw"}},{"kind":"Field","name":{"kind":"Name","value":"sizeLog"}}]}}]}}]}}]} as unknown as DocumentNode; -export const GetDockerContainersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetDockerContainers"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"skipCache"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}},"defaultValue":{"kind":"BooleanValue","value":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"docker"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"containers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"skipCache"},"value":{"kind":"Variable","name":{"kind":"Name","value":"skipCache"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"names"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"image"}},{"kind":"Field","name":{"kind":"Name","value":"created"}},{"kind":"Field","name":{"kind":"Name","value":"lanIpPorts"}},{"kind":"Field","name":{"kind":"Name","value":"autoStart"}},{"kind":"Field","name":{"kind":"Name","value":"autoStartOrder"}},{"kind":"Field","name":{"kind":"Name","value":"autoStartWait"}},{"kind":"Field","name":{"kind":"Name","value":"ports"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"privatePort"}},{"kind":"Field","name":{"kind":"Name","value":"publicPort"}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"hostConfig"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"networkMode"}}]}},{"kind":"Field","name":{"kind":"Name","value":"networkSettings"}},{"kind":"Field","name":{"kind":"Name","value":"mounts"}}]}},{"kind":"Field","name":{"kind":"Name","value":"organizer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"skipCache"},"value":{"kind":"Variable","name":{"kind":"Name","value":"skipCache"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"views"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"rootId"}},{"kind":"Field","name":{"kind":"Name","value":"prefs"}},{"kind":"Field","name":{"kind":"Name","value":"flatEntries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"parentId"}},{"kind":"Field","name":{"kind":"Name","value":"depth"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"hasChildren"}},{"kind":"Field","name":{"kind":"Name","value":"childrenIds"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"meta"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"names"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"image"}},{"kind":"Field","name":{"kind":"Name","value":"lanIpPorts"}},{"kind":"Field","name":{"kind":"Name","value":"ports"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"privatePort"}},{"kind":"Field","name":{"kind":"Name","value":"publicPort"}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"autoStart"}},{"kind":"Field","name":{"kind":"Name","value":"hostConfig"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"networkMode"}}]}},{"kind":"Field","name":{"kind":"Name","value":"networkSettings"}},{"kind":"Field","name":{"kind":"Name","value":"mounts"}},{"kind":"Field","name":{"kind":"Name","value":"created"}},{"kind":"Field","name":{"kind":"Name","value":"isUpdateAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"isRebuildReady"}},{"kind":"Field","name":{"kind":"Name","value":"templatePath"}}]}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const GetDockerContainersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetDockerContainers"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"skipCache"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}},"defaultValue":{"kind":"BooleanValue","value":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"docker"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"portConflicts"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"skipCache"},"value":{"kind":"Variable","name":{"kind":"Name","value":"skipCache"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"containerPorts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"privatePort"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"containers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"lanPorts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"lanIpPort"}},{"kind":"Field","name":{"kind":"Name","value":"publicPort"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"containers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"containers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"skipCache"},"value":{"kind":"Variable","name":{"kind":"Name","value":"skipCache"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"names"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"image"}},{"kind":"Field","name":{"kind":"Name","value":"created"}},{"kind":"Field","name":{"kind":"Name","value":"lanIpPorts"}},{"kind":"Field","name":{"kind":"Name","value":"autoStart"}},{"kind":"Field","name":{"kind":"Name","value":"autoStartOrder"}},{"kind":"Field","name":{"kind":"Name","value":"autoStartWait"}},{"kind":"Field","name":{"kind":"Name","value":"ports"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"privatePort"}},{"kind":"Field","name":{"kind":"Name","value":"publicPort"}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"hostConfig"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"networkMode"}}]}},{"kind":"Field","name":{"kind":"Name","value":"networkSettings"}},{"kind":"Field","name":{"kind":"Name","value":"mounts"}}]}},{"kind":"Field","name":{"kind":"Name","value":"organizer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"skipCache"},"value":{"kind":"Variable","name":{"kind":"Name","value":"skipCache"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"views"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"rootId"}},{"kind":"Field","name":{"kind":"Name","value":"prefs"}},{"kind":"Field","name":{"kind":"Name","value":"flatEntries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"parentId"}},{"kind":"Field","name":{"kind":"Name","value":"depth"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"hasChildren"}},{"kind":"Field","name":{"kind":"Name","value":"childrenIds"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"meta"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"names"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"image"}},{"kind":"Field","name":{"kind":"Name","value":"lanIpPorts"}},{"kind":"Field","name":{"kind":"Name","value":"ports"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"privatePort"}},{"kind":"Field","name":{"kind":"Name","value":"publicPort"}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"autoStart"}},{"kind":"Field","name":{"kind":"Name","value":"hostConfig"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"networkMode"}}]}},{"kind":"Field","name":{"kind":"Name","value":"networkSettings"}},{"kind":"Field","name":{"kind":"Name","value":"mounts"}},{"kind":"Field","name":{"kind":"Name","value":"created"}},{"kind":"Field","name":{"kind":"Name","value":"isUpdateAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"isRebuildReady"}},{"kind":"Field","name":{"kind":"Name","value":"templatePath"}}]}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateDockerFolderWithItemsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateDockerFolderWithItems"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"parentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"sourceEntryIds"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"position"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createDockerFolderWithItems"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}},{"kind":"Argument","name":{"kind":"Name","value":"parentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"parentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"sourceEntryIds"},"value":{"kind":"Variable","name":{"kind":"Name","value":"sourceEntryIds"}}},{"kind":"Argument","name":{"kind":"Name","value":"position"},"value":{"kind":"Variable","name":{"kind":"Name","value":"position"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"views"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"rootId"}},{"kind":"Field","name":{"kind":"Name","value":"flatEntries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"parentId"}},{"kind":"Field","name":{"kind":"Name","value":"depth"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"hasChildren"}},{"kind":"Field","name":{"kind":"Name","value":"childrenIds"}},{"kind":"Field","name":{"kind":"Name","value":"meta"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"names"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"image"}},{"kind":"Field","name":{"kind":"Name","value":"ports"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"privatePort"}},{"kind":"Field","name":{"kind":"Name","value":"publicPort"}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"autoStart"}},{"kind":"Field","name":{"kind":"Name","value":"hostConfig"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"networkMode"}}]}},{"kind":"Field","name":{"kind":"Name","value":"created"}},{"kind":"Field","name":{"kind":"Name","value":"isUpdateAvailable"}},{"kind":"Field","name":{"kind":"Name","value":"isRebuildReady"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateDockerFolderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateDockerFolder"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"parentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"childrenIds"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createDockerFolder"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}},{"kind":"Argument","name":{"kind":"Name","value":"parentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"parentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"childrenIds"},"value":{"kind":"Variable","name":{"kind":"Name","value":"childrenIds"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"views"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"rootId"}},{"kind":"Field","name":{"kind":"Name","value":"flatEntries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"parentId"}},{"kind":"Field","name":{"kind":"Name","value":"depth"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"hasChildren"}},{"kind":"Field","name":{"kind":"Name","value":"childrenIds"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const DeleteDockerEntriesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteDockerEntries"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"entryIds"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteDockerEntries"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"entryIds"},"value":{"kind":"Variable","name":{"kind":"Name","value":"entryIds"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"views"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"rootId"}},{"kind":"Field","name":{"kind":"Name","value":"flatEntries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"parentId"}},{"kind":"Field","name":{"kind":"Name","value":"depth"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"hasChildren"}},{"kind":"Field","name":{"kind":"Name","value":"childrenIds"}}]}}]}}]}}]}}]} as unknown as DocumentNode;