feat: port conflicts

This commit is contained in:
Pujit Mehrotra
2025-11-17 14:59:12 -05:00
parent a5cd839993
commit 735f58058d
9 changed files with 528 additions and 9 deletions

View File

@@ -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!]!
}

View File

@@ -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()

View File

@@ -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,

View File

@@ -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' },
],
},
]);
});
});
});

View File

@@ -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<string>;
}
>();
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<string>(),
};
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<string>;
}
>();
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<string>(),
};
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<DockerPortConflicts> {
const containers = await this.getContainers({ skipCache });
return {
containerPorts: this.buildContainerPortConflicts(containers),
lanPorts: this.buildLanPortConflicts(containers),
};
}
public async getContainerLogSizes(containerNames: string[]): Promise<Map<string, number>> {
const logSizes = new Map<string, number>();
if (!Array.isArray(containerNames) || containerNames.length === 0) {

View File

@@ -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<Props>(), {
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<FlatOrganizerEntry[]>(
() => 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<DockerContainer[]>(() => result.value?.docker?.containers || []);
const portConflicts = computed<DockerPortConflictsResult | null>(() => {
const dockerData = result.value?.docker;
return dockerData?.portConflicts ?? null;
});
const lanPortConflicts = computed<LanPortConflict[]>(() => portConflicts.value?.lanPorts ?? []);
const containerPortConflicts = computed<ContainerPortConflict[]>(
() => 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);
</UButton>
</div>
</div>
<div
v-if="hasPortConflicts"
class="mb-4 rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900 dark:border-amber-400/50 dark:bg-amber-400/10 dark:text-amber-100"
>
<div class="flex items-start gap-3">
<UIcon
name="i-lucide-triangle-alert"
class="mt-1 h-5 w-5 flex-shrink-0 text-amber-500 dark:text-amber-300"
aria-hidden="true"
/>
<div class="w-full space-y-3">
<div>
<p class="text-sm font-semibold">
Port conflicts detected ({{ totalPortConflictCount }})
</p>
<p class="text-xs text-amber-900/80 dark:text-amber-100/80">
Multiple containers are sharing the same LAN or container ports. Click a container
below to open its editor or highlight it in the table.
</p>
</div>
<div class="space-y-4">
<div v-if="lanPortConflicts.length" class="space-y-2">
<p
class="text-xs font-semibold tracking-wide text-amber-900/70 uppercase dark:text-amber-100/70"
>
LAN ports
</p>
<div
v-for="conflict in lanPortConflicts"
:key="`lan-${conflict.lanIpPort}-${conflict.type}`"
class="rounded-md border border-amber-200/70 bg-white/80 p-3 dark:border-amber-300/30 dark:bg-transparent"
>
<div class="text-sm font-medium">{{ formatLanConflictLabel(conflict) }}</div>
<div class="mt-2 flex flex-wrap gap-2">
<button
v-for="container in conflict.containers"
:key="container.id"
type="button"
class="inline-flex items-center gap-1 rounded-full border border-amber-300 bg-amber-100 px-2 py-1 text-xs font-medium text-amber-900 transition hover:bg-amber-200 focus-visible:ring-2 focus-visible:ring-amber-400 focus-visible:outline-none dark:border-amber-200/40 dark:bg-transparent dark:text-amber-100"
:title="`Edit ${container.name || 'container'}`"
@click="handleConflictContainerAction(container)"
>
<span>{{ container.name || 'Container' }}</span>
<UIcon name="i-lucide-pencil" class="h-3.5 w-3.5" aria-hidden="true" />
</button>
</div>
</div>
</div>
<div v-if="containerPortConflicts.length" class="space-y-2">
<p
class="text-xs font-semibold tracking-wide text-amber-900/70 uppercase dark:text-amber-100/70"
>
Container ports
</p>
<div
v-for="conflict in containerPortConflicts"
:key="`container-${conflict.privatePort}-${conflict.type}`"
class="rounded-md border border-amber-200/70 bg-white/80 p-3 dark:border-amber-300/30 dark:bg-transparent"
>
<div class="text-sm font-medium">{{ formatContainerConflictLabel(conflict) }}</div>
<div class="mt-2 flex flex-wrap gap-2">
<button
v-for="container in conflict.containers"
:key="container.id"
type="button"
class="inline-flex items-center gap-1 rounded-full border border-amber-300 bg-amber-100 px-2 py-1 text-xs font-medium text-amber-900 transition hover:bg-amber-200 focus-visible:ring-2 focus-visible:ring-amber-400 focus-visible:outline-none dark:border-amber-200/40 dark:bg-transparent dark:text-amber-100"
:title="`Edit ${container.name || 'container'}`"
@click="handleConflictContainerAction(container)"
>
<span>{{ container.name || 'Container' }}</span>
<UIcon name="i-lucide-pencil" class="h-3.5 w-3.5" aria-hidden="true" />
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<DockerContainersTable
:containers="containers"
:flat-entries="flatEntries"

View File

@@ -4,6 +4,25 @@ export const GET_DOCKER_CONTAINERS = gql`
query GetDockerContainers($skipCache: Boolean = false) {
docker {
id
portConflicts(skipCache: $skipCache) {
containerPorts {
privatePort
type
containers {
id
name
}
}
lanPorts {
lanIpPort
publicPort
type
containers {
id
name
}
}
}
containers(skipCache: $skipCache) {
id
names

View File

@@ -30,7 +30,7 @@ type Documents = {
"\n mutation UpdateConnectSettings($input: JSON!) {\n updateSettings(input: $input) {\n restartRequired\n values\n }\n }\n": typeof types.UpdateConnectSettingsDocument,
"\n query GetDockerActiveContainer($id: PrefixedID!) {\n docker {\n id\n containers {\n id\n names\n image\n created\n state\n status\n autoStart\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n labels\n }\n }\n }\n": typeof types.GetDockerActiveContainerDocument,
"\n query GetDockerContainerSizes {\n docker {\n id\n containers(skipCache: true) {\n id\n names\n sizeRootFs\n sizeRw\n sizeLog\n }\n }\n }\n": typeof types.GetDockerContainerSizesDocument,
"\n query GetDockerContainers($skipCache: Boolean = false) {\n docker {\n id\n containers(skipCache: $skipCache) {\n id\n names\n state\n status\n image\n created\n lanIpPorts\n autoStart\n autoStartOrder\n autoStartWait\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n }\n organizer(skipCache: $skipCache) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n icon\n meta {\n id\n names\n state\n status\n image\n lanIpPorts\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n created\n isUpdateAvailable\n isRebuildReady\n templatePath\n }\n }\n }\n }\n }\n }\n": typeof types.GetDockerContainersDocument,
"\n query GetDockerContainers($skipCache: Boolean = false) {\n docker {\n id\n portConflicts(skipCache: $skipCache) {\n containerPorts {\n privatePort\n type\n containers {\n id\n name\n }\n }\n lanPorts {\n lanIpPort\n publicPort\n type\n containers {\n id\n name\n }\n }\n }\n containers(skipCache: $skipCache) {\n id\n names\n state\n status\n image\n created\n lanIpPorts\n autoStart\n autoStartOrder\n autoStartWait\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n }\n organizer(skipCache: $skipCache) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n icon\n meta {\n id\n names\n state\n status\n image\n lanIpPorts\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n created\n isUpdateAvailable\n isRebuildReady\n templatePath\n }\n }\n }\n }\n }\n }\n": typeof types.GetDockerContainersDocument,
"\n mutation CreateDockerFolderWithItems(\n $name: String!\n $parentId: String\n $sourceEntryIds: [String!]\n $position: Float\n ) {\n createDockerFolderWithItems(\n name: $name\n parentId: $parentId\n sourceEntryIds: $sourceEntryIds\n position: $position\n ) {\n version\n views {\n id\n name\n rootId\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n meta {\n id\n names\n state\n status\n image\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n created\n isUpdateAvailable\n isRebuildReady\n }\n }\n }\n }\n }\n": typeof types.CreateDockerFolderWithItemsDocument,
"\n mutation CreateDockerFolder($name: String!, $parentId: String, $childrenIds: [String!]) {\n createDockerFolder(name: $name, parentId: $parentId, childrenIds: $childrenIds) {\n version\n views {\n id\n name\n rootId\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n }\n }\n }\n }\n": typeof types.CreateDockerFolderDocument,
"\n mutation DeleteDockerEntries($entryIds: [String!]!) {\n deleteDockerEntries(entryIds: $entryIds) {\n version\n views {\n id\n name\n rootId\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n }\n }\n }\n }\n": typeof types.DeleteDockerEntriesDocument,
@@ -44,7 +44,7 @@ type Documents = {
"\n mutation StartDockerContainer($id: PrefixedID!) {\n docker {\n start(id: $id) {\n id\n names\n state\n }\n }\n }\n": typeof types.StartDockerContainerDocument,
"\n mutation StopDockerContainer($id: PrefixedID!) {\n docker {\n stop(id: $id) {\n id\n names\n state\n }\n }\n }\n": typeof types.StopDockerContainerDocument,
"\n mutation UnpauseDockerContainer($id: PrefixedID!) {\n docker {\n unpause(id: $id) {\n id\n names\n state\n }\n }\n }\n": typeof types.UnpauseDockerContainerDocument,
"\n mutation UpdateDockerAutostartConfiguration(\n $entries: [DockerAutostartEntryInput!]!\n $persistUserPreferences: Boolean\n ) {\n docker {\n updateAutostartConfiguration(\n entries: $entries\n persistUserPreferences: $persistUserPreferences\n )\n }\n }\n": typeof types.UpdateDockerAutostartConfigurationDocument,
"\n mutation UpdateDockerAutostartConfiguration(\n $entries: [DockerAutostartEntryInput!]!\n $persistUserPreferences: Boolean\n ) {\n docker {\n updateAutostartConfiguration(entries: $entries, persistUserPreferences: $persistUserPreferences)\n }\n }\n": typeof types.UpdateDockerAutostartConfigurationDocument,
"\n mutation UpdateDockerContainer($id: PrefixedID!) {\n docker {\n updateContainer(id: $id) {\n id\n names\n state\n isUpdateAvailable\n isRebuildReady\n }\n }\n }\n": typeof types.UpdateDockerContainerDocument,
"\n mutation UpdateDockerContainers($ids: [PrefixedID!]!) {\n docker {\n updateContainers(ids: $ids) {\n id\n names\n state\n isUpdateAvailable\n isRebuildReady\n }\n }\n }\n": typeof types.UpdateDockerContainersDocument,
"\n mutation UpdateDockerViewPreferences($viewId: String, $prefs: JSON!) {\n updateDockerViewPreferences(viewId: $viewId, prefs: $prefs) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n meta {\n id\n names\n state\n status\n image\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n created\n isUpdateAvailable\n isRebuildReady\n }\n }\n }\n }\n }\n": typeof types.UpdateDockerViewPreferencesDocument,
@@ -98,7 +98,7 @@ const documents: Documents = {
"\n mutation UpdateConnectSettings($input: JSON!) {\n updateSettings(input: $input) {\n restartRequired\n values\n }\n }\n": types.UpdateConnectSettingsDocument,
"\n query GetDockerActiveContainer($id: PrefixedID!) {\n docker {\n id\n containers {\n id\n names\n image\n created\n state\n status\n autoStart\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n labels\n }\n }\n }\n": types.GetDockerActiveContainerDocument,
"\n query GetDockerContainerSizes {\n docker {\n id\n containers(skipCache: true) {\n id\n names\n sizeRootFs\n sizeRw\n sizeLog\n }\n }\n }\n": types.GetDockerContainerSizesDocument,
"\n query GetDockerContainers($skipCache: Boolean = false) {\n docker {\n id\n containers(skipCache: $skipCache) {\n id\n names\n state\n status\n image\n created\n lanIpPorts\n autoStart\n autoStartOrder\n autoStartWait\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n }\n organizer(skipCache: $skipCache) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n icon\n meta {\n id\n names\n state\n status\n image\n lanIpPorts\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n created\n isUpdateAvailable\n isRebuildReady\n templatePath\n }\n }\n }\n }\n }\n }\n": types.GetDockerContainersDocument,
"\n query GetDockerContainers($skipCache: Boolean = false) {\n docker {\n id\n portConflicts(skipCache: $skipCache) {\n containerPorts {\n privatePort\n type\n containers {\n id\n name\n }\n }\n lanPorts {\n lanIpPort\n publicPort\n type\n containers {\n id\n name\n }\n }\n }\n containers(skipCache: $skipCache) {\n id\n names\n state\n status\n image\n created\n lanIpPorts\n autoStart\n autoStartOrder\n autoStartWait\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n }\n organizer(skipCache: $skipCache) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n icon\n meta {\n id\n names\n state\n status\n image\n lanIpPorts\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n created\n isUpdateAvailable\n isRebuildReady\n templatePath\n }\n }\n }\n }\n }\n }\n": types.GetDockerContainersDocument,
"\n mutation CreateDockerFolderWithItems(\n $name: String!\n $parentId: String\n $sourceEntryIds: [String!]\n $position: Float\n ) {\n createDockerFolderWithItems(\n name: $name\n parentId: $parentId\n sourceEntryIds: $sourceEntryIds\n position: $position\n ) {\n version\n views {\n id\n name\n rootId\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n meta {\n id\n names\n state\n status\n image\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n created\n isUpdateAvailable\n isRebuildReady\n }\n }\n }\n }\n }\n": types.CreateDockerFolderWithItemsDocument,
"\n mutation CreateDockerFolder($name: String!, $parentId: String, $childrenIds: [String!]) {\n createDockerFolder(name: $name, parentId: $parentId, childrenIds: $childrenIds) {\n version\n views {\n id\n name\n rootId\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n }\n }\n }\n }\n": types.CreateDockerFolderDocument,
"\n mutation DeleteDockerEntries($entryIds: [String!]!) {\n deleteDockerEntries(entryIds: $entryIds) {\n version\n views {\n id\n name\n rootId\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n }\n }\n }\n }\n": types.DeleteDockerEntriesDocument,
@@ -112,7 +112,7 @@ const documents: Documents = {
"\n mutation StartDockerContainer($id: PrefixedID!) {\n docker {\n start(id: $id) {\n id\n names\n state\n }\n }\n }\n": types.StartDockerContainerDocument,
"\n mutation StopDockerContainer($id: PrefixedID!) {\n docker {\n stop(id: $id) {\n id\n names\n state\n }\n }\n }\n": types.StopDockerContainerDocument,
"\n mutation UnpauseDockerContainer($id: PrefixedID!) {\n docker {\n unpause(id: $id) {\n id\n names\n state\n }\n }\n }\n": types.UnpauseDockerContainerDocument,
"\n mutation UpdateDockerAutostartConfiguration(\n $entries: [DockerAutostartEntryInput!]!\n $persistUserPreferences: Boolean\n ) {\n docker {\n updateAutostartConfiguration(\n entries: $entries\n persistUserPreferences: $persistUserPreferences\n )\n }\n }\n": types.UpdateDockerAutostartConfigurationDocument,
"\n mutation UpdateDockerAutostartConfiguration(\n $entries: [DockerAutostartEntryInput!]!\n $persistUserPreferences: Boolean\n ) {\n docker {\n updateAutostartConfiguration(entries: $entries, persistUserPreferences: $persistUserPreferences)\n }\n }\n": types.UpdateDockerAutostartConfigurationDocument,
"\n mutation UpdateDockerContainer($id: PrefixedID!) {\n docker {\n updateContainer(id: $id) {\n id\n names\n state\n isUpdateAvailable\n isRebuildReady\n }\n }\n }\n": types.UpdateDockerContainerDocument,
"\n mutation UpdateDockerContainers($ids: [PrefixedID!]!) {\n docker {\n updateContainers(ids: $ids) {\n id\n names\n state\n isUpdateAvailable\n isRebuildReady\n }\n }\n }\n": types.UpdateDockerContainersDocument,
"\n mutation UpdateDockerViewPreferences($viewId: String, $prefs: JSON!) {\n updateDockerViewPreferences(viewId: $viewId, prefs: $prefs) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n meta {\n id\n names\n state\n status\n image\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n created\n isUpdateAvailable\n isRebuildReady\n }\n }\n }\n }\n }\n": types.UpdateDockerViewPreferencesDocument,
@@ -231,7 +231,7 @@ export function graphql(source: "\n query GetDockerContainerSizes {\n docker
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n query GetDockerContainers($skipCache: Boolean = false) {\n docker {\n id\n containers(skipCache: $skipCache) {\n id\n names\n state\n status\n image\n created\n lanIpPorts\n autoStart\n autoStartOrder\n autoStartWait\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n }\n organizer(skipCache: $skipCache) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n icon\n meta {\n id\n names\n state\n status\n image\n lanIpPorts\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n created\n isUpdateAvailable\n isRebuildReady\n templatePath\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query GetDockerContainers($skipCache: Boolean = false) {\n docker {\n id\n containers(skipCache: $skipCache) {\n id\n names\n state\n status\n image\n created\n lanIpPorts\n autoStart\n autoStartOrder\n autoStartWait\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n }\n organizer(skipCache: $skipCache) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n icon\n meta {\n id\n names\n state\n status\n image\n lanIpPorts\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n created\n isUpdateAvailable\n isRebuildReady\n templatePath\n }\n }\n }\n }\n }\n }\n"];
export function graphql(source: "\n query GetDockerContainers($skipCache: Boolean = false) {\n docker {\n id\n portConflicts(skipCache: $skipCache) {\n containerPorts {\n privatePort\n type\n containers {\n id\n name\n }\n }\n lanPorts {\n lanIpPort\n publicPort\n type\n containers {\n id\n name\n }\n }\n }\n containers(skipCache: $skipCache) {\n id\n names\n state\n status\n image\n created\n lanIpPorts\n autoStart\n autoStartOrder\n autoStartWait\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n }\n organizer(skipCache: $skipCache) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n icon\n meta {\n id\n names\n state\n status\n image\n lanIpPorts\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n created\n isUpdateAvailable\n isRebuildReady\n templatePath\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query GetDockerContainers($skipCache: Boolean = false) {\n docker {\n id\n portConflicts(skipCache: $skipCache) {\n containerPorts {\n privatePort\n type\n containers {\n id\n name\n }\n }\n lanPorts {\n lanIpPort\n publicPort\n type\n containers {\n id\n name\n }\n }\n }\n containers(skipCache: $skipCache) {\n id\n names\n state\n status\n image\n created\n lanIpPorts\n autoStart\n autoStartOrder\n autoStartWait\n ports {\n privatePort\n publicPort\n type\n }\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n }\n organizer(skipCache: $skipCache) {\n version\n views {\n id\n name\n rootId\n prefs\n flatEntries {\n id\n type\n name\n parentId\n depth\n position\n path\n hasChildren\n childrenIds\n icon\n meta {\n id\n names\n state\n status\n image\n lanIpPorts\n ports {\n privatePort\n publicPort\n type\n }\n autoStart\n hostConfig {\n networkMode\n }\n networkSettings\n mounts\n created\n isUpdateAvailable\n isRebuildReady\n templatePath\n }\n }\n }\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -287,7 +287,7 @@ export function graphql(source: "\n mutation UnpauseDockerContainer($id: Prefix
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n mutation UpdateDockerAutostartConfiguration(\n $entries: [DockerAutostartEntryInput!]!\n $persistUserPreferences: Boolean\n ) {\n docker {\n updateAutostartConfiguration(\n entries: $entries\n persistUserPreferences: $persistUserPreferences\n )\n }\n }\n"): (typeof documents)["\n mutation UpdateDockerAutostartConfiguration(\n $entries: [DockerAutostartEntryInput!]!\n $persistUserPreferences: Boolean\n ) {\n docker {\n updateAutostartConfiguration(\n entries: $entries\n persistUserPreferences: $persistUserPreferences\n )\n }\n }\n"];
export function graphql(source: "\n mutation UpdateDockerAutostartConfiguration(\n $entries: [DockerAutostartEntryInput!]!\n $persistUserPreferences: Boolean\n ) {\n docker {\n updateAutostartConfiguration(entries: $entries, persistUserPreferences: $persistUserPreferences)\n }\n }\n"): (typeof documents)["\n mutation UpdateDockerAutostartConfiguration(\n $entries: [DockerAutostartEntryInput!]!\n $persistUserPreferences: Boolean\n ) {\n docker {\n updateAutostartConfiguration(entries: $entries, persistUserPreferences: $persistUserPreferences)\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/

File diff suppressed because one or more lines are too long