mirror of
https://github.com/unraid/api.git
synced 2026-01-11 19:20:09 -06:00
feat: port conflicts
This commit is contained in:
@@ -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!]!
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user