mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-31 04:38:11 +00:00
fix(networking): ignore verified Mesh attachments in drift (#1729)
This commit is contained in:
@@ -18,6 +18,7 @@ import { declaredFromEffectiveModel } from '../helpers/effectiveToDeclaredCompos
|
||||
import type { DeclaredCompose, DeclaredService, DeclaredPort } from '../helpers/composeDependencyParse';
|
||||
import type { EffectiveModel, EffService } from '../services/preflight/effectiveModel';
|
||||
import { fromDeclaredCompose, fromEffectiveModel } from '../services/network/normalize';
|
||||
import { DatabaseService } from '../services/DatabaseService';
|
||||
|
||||
// ── builders ────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -580,6 +581,32 @@ describe('assembleStackDrift - network drift', () => {
|
||||
expect(report.findings.filter(f => f.kind.startsWith('network-'))).toEqual([]);
|
||||
expect(report.status).toBe('in-sync');
|
||||
});
|
||||
|
||||
it('reports in-sync when a verified Mesh attachment is the only runtime difference', () => {
|
||||
const report = assembleStackDrift({
|
||||
stack: 'app',
|
||||
declared: declared([service({ name: 'web' })]),
|
||||
containers: [container({ id: 'c1', service: 'web', networks: [{ name: 'sencho_mesh', id: 'm', ip: '' }] })],
|
||||
networks: [depNet('sencho_mesh', { composeProject: null, stack: null })],
|
||||
managedNetworkAttachment: (_runtimeContainer, networkName) => networkName === 'sencho_mesh',
|
||||
});
|
||||
|
||||
expect(report.status).toBe('in-sync');
|
||||
expect(report.findings.filter(f => f.kind === 'network-undeclared')).toEqual([]);
|
||||
});
|
||||
|
||||
it('keeps an unverified manual Mesh attachment drifted', () => {
|
||||
const report = assembleStackDrift({
|
||||
stack: 'app',
|
||||
declared: declared([service({ name: 'web' })]),
|
||||
containers: [container({ id: 'c1', service: 'web', networks: [{ name: 'sencho_mesh', id: 'm', ip: '' }] })],
|
||||
networks: [depNet('sencho_mesh', { composeProject: null, stack: null })],
|
||||
managedNetworkAttachment: () => false,
|
||||
});
|
||||
|
||||
expect(report.status).toBe('drifted');
|
||||
expect(report.findings.filter(f => f.kind === 'network-undeclared')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
// ── declaredFromEffectiveModel ─────────────────────────────────────────────
|
||||
@@ -815,4 +842,46 @@ describe('buildStackDriftReport - boundaries', () => {
|
||||
expect(findingKinds(report)).toContain('network-undeclared');
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('keeps the report available and Mesh drift actionable when opt-in authority fails', async () => {
|
||||
const snapshot: DependencySnapshot = {
|
||||
containers: [container({ id: 'c1', service: 'web', stack: 'app', image: 'nginx:1.25', networks: [{ name: 'sencho_mesh', id: 'm', ip: '' }] })],
|
||||
networks: [depNet('sencho_mesh', { composeProject: null, stack: null })],
|
||||
volumes: [],
|
||||
};
|
||||
stubDockerRender({ name: 'app', services: { web: { image: 'nginx:1.25' } } });
|
||||
stubFsAndSnapshot(snapshot);
|
||||
vi.spyOn(DatabaseService, 'getInstance').mockImplementation(() => {
|
||||
throw new Error('database unavailable');
|
||||
});
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
|
||||
const report = await buildStackDriftReport(0, 'app');
|
||||
|
||||
expect(report.status).toBe('drifted');
|
||||
expect(report.findings).toContainEqual(expect.objectContaining({
|
||||
kind: 'network-undeclared',
|
||||
actual: 'sencho_mesh',
|
||||
}));
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('reports in-sync through the public builder when DB authority opts the stack into Mesh', async () => {
|
||||
const snapshot: DependencySnapshot = {
|
||||
containers: [container({ id: 'c1', service: 'web', stack: 'app', image: 'nginx:1.25', networks: [{ name: 'sencho_mesh', id: 'm', ip: '' }] })],
|
||||
networks: [depNet('sencho_mesh', { composeProject: null, stack: null })],
|
||||
volumes: [],
|
||||
};
|
||||
stubDockerRender({ name: 'app', services: { web: { image: 'nginx:1.25' } } });
|
||||
stubFsAndSnapshot(snapshot);
|
||||
vi.spyOn(DatabaseService, 'getInstance').mockReturnValue({
|
||||
isMeshStackEnabled: vi.fn().mockReturnValue(true),
|
||||
} as unknown as DatabaseService);
|
||||
|
||||
const report = await buildStackDriftReport(0, 'app');
|
||||
|
||||
expect(report.status).toBe('in-sync');
|
||||
expect(report.findings.filter(f => f.kind === 'network-undeclared')).toEqual([]);
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user