fix: container update logic

This commit is contained in:
Pujit Mehrotra
2025-11-06 11:31:04 -05:00
parent 6c048bf550
commit 92852466e8
3 changed files with 65 additions and 25 deletions

View File

@@ -41,7 +41,22 @@ export class DockerManifestService {
cacheData ??= await this.dockerPhpService.readCachedUpdateStatus();
const containerData = cacheData[taggedRef];
if (!containerData) return null;
return containerData.status?.toLowerCase() === 'true';
const normalize = (digest?: string | null) => {
const value = digest?.trim().toLowerCase();
return value && value !== 'undef' ? value : null;
};
const localDigest = normalize(containerData.local);
const remoteDigest = normalize(containerData.remote);
if (localDigest && remoteDigest) {
return localDigest !== remoteDigest;
}
const status = containerData.status?.toLowerCase();
if (status === 'true') return true;
if (status === 'false') return false;
return null;
}
/**

View File

@@ -8,6 +8,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
// Import the mocked pubsub parts
import { pubsub, PUBSUB_CHANNEL } from '@app/core/pubsub.js';
import { DockerConfigService } from '@app/unraid-api/graph/resolvers/docker/docker-config.service.js';
import { DockerManifestService } from '@app/unraid-api/graph/resolvers/docker/docker-manifest.service.js';
import { DockerTemplateScannerService } from '@app/unraid-api/graph/resolvers/docker/docker-template-scanner.service.js';
import { ContainerState, DockerContainer } from '@app/unraid-api/graph/resolvers/docker/docker.model.js';
import { DockerService } from '@app/unraid-api/graph/resolvers/docker/docker.service.js';
@@ -27,30 +28,40 @@ interface DockerError extends NodeJS.ErrnoException {
address: string;
}
const mockContainer = {
start: vi.fn(),
stop: vi.fn(),
};
const { mockDockerInstance, mockListContainers, mockGetContainer, mockListNetworks, mockContainer } =
vi.hoisted(() => {
const mockContainer = {
start: vi.fn(),
stop: vi.fn(),
};
// Create properly typed mock functions
const mockListContainers = vi.fn();
const mockGetContainer = vi.fn().mockReturnValue(mockContainer);
const mockListNetworks = vi.fn();
const mockListContainers = vi.fn();
const mockGetContainer = vi.fn().mockReturnValue(mockContainer);
const mockListNetworks = vi.fn();
const mockDockerInstance = {
getContainer: mockGetContainer,
listContainers: mockListContainers,
listNetworks: mockListNetworks,
modem: {
Promise: Promise,
protocol: 'http',
socketPath: '/var/run/docker.sock',
headers: {},
sshOptions: {
agentForward: undefined,
},
},
} as unknown as Docker;
const mockDockerInstance = {
getContainer: mockGetContainer,
listContainers: mockListContainers,
listNetworks: mockListNetworks,
modem: {
Promise: Promise,
protocol: 'http',
socketPath: '/var/run/docker.sock',
headers: {},
sshOptions: {
agentForward: undefined,
},
},
} as unknown as Docker;
return {
mockDockerInstance,
mockListContainers,
mockGetContainer,
mockListNetworks,
mockContainer,
};
});
vi.mock('dockerode', () => {
return {
@@ -113,6 +124,10 @@ const mockDockerTemplateScannerService = {
syncMissingContainers: vi.fn().mockResolvedValue(false),
};
const mockDockerManifestService = {
refreshDigests: vi.fn().mockResolvedValue(true),
};
// Mock NotificationsService
const mockNotificationsService = {
notifyIfUnique: vi.fn().mockResolvedValue(null),
@@ -141,6 +156,8 @@ describe('DockerService', () => {
});
mockDockerTemplateScannerService.bootstrapScan.mockResolvedValue(undefined);
mockDockerTemplateScannerService.syncMissingContainers.mockResolvedValue(false);
mockDockerManifestService.refreshDigests.mockReset();
mockDockerManifestService.refreshDigests.mockResolvedValue(true);
const module: TestingModule = await Test.createTestingModule({
providers: [
@@ -157,6 +174,10 @@ describe('DockerService', () => {
provide: DockerTemplateScannerService,
useValue: mockDockerTemplateScannerService,
},
{
provide: DockerManifestService,
useValue: mockDockerManifestService,
},
{
provide: NotificationsService,
useValue: mockNotificationsService,

View File

@@ -12,6 +12,7 @@ import { catchHandlers } from '@app/core/utils/misc/catch-handlers.js';
import { sleep } from '@app/core/utils/misc/sleep.js';
import { getters } from '@app/store/index.js';
import { DockerConfigService } from '@app/unraid-api/graph/resolvers/docker/docker-config.service.js';
import { DockerManifestService } from '@app/unraid-api/graph/resolvers/docker/docker-manifest.service.js';
import {
ContainerPortType,
ContainerState,
@@ -50,7 +51,8 @@ export class DockerService {
constructor(
@Inject(CACHE_MANAGER) private cacheManager: Cache,
private readonly dockerConfigService: DockerConfigService,
private readonly notificationsService: NotificationsService
private readonly notificationsService: NotificationsService,
private readonly dockerManifestService: DockerManifestService
) {
this.client = this.getDockerClient();
}
@@ -458,7 +460,9 @@ export class DockerService {
this.logger.debug(`Invalidated container caches after updating ${id}`);
const updatedContainers = await this.getContainers({ skipCache: true });
const updatedContainer = updatedContainers.find((c) => c.id === id);
const updatedContainer = updatedContainers.find(
(c) => c.names?.some((name) => name.replace(/^\//, '') === containerName) || c.id === id
);
if (!updatedContainer) {
throw new Error(`Container ${id} not found after update`);
}