diff --git a/src/docker/DockerApi.ts b/src/docker/DockerApi.ts index 54624af..b07f567 100644 --- a/src/docker/DockerApi.ts +++ b/src/docker/DockerApi.ts @@ -65,6 +65,40 @@ export abstract class IDockerUpdateOrders { } export type IDockerUpdateOrder = 'auto' | 'stopFirst' | 'startFirst' +export function getLegacyServiceDnsAlias( + serviceName: string, + namespace: string | undefined, + isLegacyAppName: boolean +) { + if (!namespace || isLegacyAppName) { + return undefined + } + + return `srv-${namespace}--${serviceName}` +} + +export interface IServiceNetworkAttachment { + Target: string + Aliases?: string[] +} + +export function getServiceNetworkAttachments( + networks: string[], + legacyDnsAlias: string | undefined +) { + return networks.map((network) => { + const attachment: IServiceNetworkAttachment = { + Target: network, + } + + if (legacyDnsAlias) { + attachment.Aliases = [legacyDnsAlias] + } + + return attachment + }) +} + export interface CreateContainerParams { containerName?: string imageName: string @@ -1454,11 +1488,25 @@ class DockerApi { } if (networks) { - updatedData.TaskTemplate.Networks = [] - for (let i = 0; i < networks.length; i++) { - updatedData.TaskTemplate.Networks.push({ - Target: networks[i], - }) + if (appObject) { + const legacyDnsAlias = getLegacyServiceDnsAlias( + serviceName, + namespace, + !!appObject.isLegacyAppName + ) + + updatedData.TaskTemplate.Networks = + getServiceNetworkAttachments( + networks, + legacyDnsAlias + ) + } else { + updatedData.TaskTemplate.Networks = [] + for (let i = 0; i < networks.length; i++) { + updatedData.TaskTemplate.Networks.push({ + Target: networks[i], + }) + } } } diff --git a/tests/ServiceNamingMigration.test.ts b/tests/ServiceNamingMigration.test.ts index f4896f2..2efeb07 100644 --- a/tests/ServiceNamingMigration.test.ts +++ b/tests/ServiceNamingMigration.test.ts @@ -3,6 +3,10 @@ import AppsDataStore, { isNameAllowed, } from '../src/datastore/AppsDataStore' import { runDataStoreMigrations } from '../src/datastore/DataStore' +import { + getLegacyServiceDnsAlias, + getServiceNetworkAttachments, +} from '../src/docker/DockerApi' import ServiceManager from '../src/user/ServiceManager' function createConfigStore(initialData: { [key: string]: any }) { @@ -88,6 +92,49 @@ describe('service and volume naming migration', () => { expect(failedVolumes).toEqual(['data']) }) + test('adds the legacy DNS alias to every network for a new app', () => { + const alias = getLegacyServiceDnsAlias( + 'paperless-db', + 'captain', + false + ) + + expect( + getServiceNetworkAttachments( + ['captain-overlay-network', 'private-network'], + alias + ) + ).toEqual([ + { + Target: 'captain-overlay-network', + Aliases: ['srv-captain--paperless-db'], + }, + { + Target: 'private-network', + Aliases: ['srv-captain--paperless-db'], + }, + ]) + }) + + test('does not add a redundant DNS alias to legacy apps', () => { + const alias = getLegacyServiceDnsAlias( + 'srv-captain--paperless-db', + 'captain', + true + ) + + expect( + getServiceNetworkAttachments( + ['captain-overlay-network'], + alias + ) + ).toEqual([ + { + Target: 'captain-overlay-network', + }, + ]) + }) + test('deletes both physical volumes when neither remains in use', async () => { const appsDataStore = new AppsDataStore( createConfigStore({}),