diff --git a/packages/dockerCompose/src/userSettings.ts b/packages/dockerCompose/src/userSettings.ts index 39d8fb567..759274267 100644 --- a/packages/dockerCompose/src/userSettings.ts +++ b/packages/dockerCompose/src/userSettings.ts @@ -1,5 +1,14 @@ import path from "path"; -import { mapValues, pick, omitBy, isObject, merge } from "lodash-es"; +import { + mapValues, + pick, + omitBy, + isObject, + merge, + mergeWith, + isArray, + union, +} from "lodash-es"; import { parsePortMappings, stringifyPortMappings, @@ -181,8 +190,18 @@ export function applyUserSettings( }) ); - // use lodash to merge networks and userSetNetworks with merge - const nextNetworks = merge(networks, userSetNetworks); + // docker aliases must be uinique + // TODO: use docker compose merge to automatically merge these dappnode docker compose properties + // see https://github.com/dappnode/DNP_DAPPMANAGER/issues/1983 + const nextNetworks = mergeWith( + networks, + userSetNetworks, + (value1, value2) => { + return mergeWith(value1, value2, (subvalue1, subvalue2) => { + return union(subvalue1, subvalue2); + }); + } + ); // ##### Kept for legacy compatibility const nextServiceVolumes = stringifyVolumeMappings( diff --git a/packages/stakers/src/consensus.ts b/packages/stakers/src/consensus.ts index 286788620..4ddf933dc 100644 --- a/packages/stakers/src/consensus.ts +++ b/packages/stakers/src/consensus.ts @@ -101,10 +101,14 @@ export class Consensus extends StakerComponent { this.DbHandlers[network].set(undefined); return; } - await this.persistSelectedIfInstalled( - currentConsensusDnpName, - this.getUserSettings(currentConsensusDnpName, isInstalled, network) - ); + await this.persistSelectedIfInstalled({ + dnpName: currentConsensusDnpName, + userSettings: this.getUserSettings( + currentConsensusDnpName, + isInstalled, + network + ), + }); await this.DbHandlers[network].set(currentConsensusDnpName); } } @@ -173,19 +177,19 @@ export class Consensus extends StakerComponent { }, } : {}, - networks: - beaconServiceName === validatorServiceName - ? { - rootNetworks: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - external: true, - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - external: true, - }, - }, - serviceNetworks: { - ["beacon-validator"]: { + networks: { + rootNetworks: { + [params.DOCKER_STAKER_NETWORKS[network]]: { + external: true, + }, + [params.DOCKER_PRIVATE_NETWORK_NAME]: { + external: true, + }, + }, + serviceNetworks: + beaconServiceName === validatorServiceName + ? { + "beacon-validator": { [params.DOCKER_STAKER_NETWORKS[network]]: { aliases: [ `beacon-chain.${network}.staker.dappnode`, @@ -199,19 +203,9 @@ export class Consensus extends StakerComponent { ], }, }, - }, - } - : { - rootNetworks: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - external: true, - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - external: true, - }, - }, - serviceNetworks: { - ["beacon-chain"]: { + } + : { + "beacon-chain": { [params.DOCKER_STAKER_NETWORKS[network]]: { aliases: [`beacon-chain.${network}.staker.dappnode`], }, @@ -219,7 +213,7 @@ export class Consensus extends StakerComponent { aliases: [`beacon-chain.${network}.dncore.dappnode`], }, }, - ["validator"]: { + validator: { [params.DOCKER_STAKER_NETWORKS[network]]: { aliases: [`validator.${network}.staker.dappnode`], }, @@ -228,7 +222,7 @@ export class Consensus extends StakerComponent { }, }, }, - }, + }, }; } diff --git a/packages/stakers/src/execution.ts b/packages/stakers/src/execution.ts index 3f606b771..e9f9ab45a 100644 --- a/packages/stakers/src/execution.ts +++ b/packages/stakers/src/execution.ts @@ -88,10 +88,10 @@ export class Execution extends StakerComponent { this.DbHandlers[network].set(undefined); return; } - await this.persistSelectedIfInstalled( - currentExecutionDnpName, - this.getUserSettings(network, currentExecutionDnpName) - ); + await this.persistSelectedIfInstalled({ + dnpName: currentExecutionDnpName, + userSettings: this.getUserSettings(network, currentExecutionDnpName), + }); await this.DbHandlers[network].set(currentExecutionDnpName); } } diff --git a/packages/stakers/src/mevBoost.ts b/packages/stakers/src/mevBoost.ts index e7396029e..27a6660ce 100644 --- a/packages/stakers/src/mevBoost.ts +++ b/packages/stakers/src/mevBoost.ts @@ -91,10 +91,10 @@ export class MevBoost extends StakerComponent { this.DbHandlers[network].set(false); return; } - await this.persistSelectedIfInstalled( - currentMevBoostDnpName, - this.getUserSettings([], false, network) - ); + await this.persistSelectedIfInstalled({ + dnpName: currentMevBoostDnpName, + userSettings: this.getUserSettings([], false, network), + }); this.DbHandlers[network].set(true); } } diff --git a/packages/stakers/src/signer.ts b/packages/stakers/src/signer.ts index c61718665..445ff4b6e 100644 --- a/packages/stakers/src/signer.ts +++ b/packages/stakers/src/signer.ts @@ -62,10 +62,10 @@ export class Signer extends StakerComponent { }) )?.containers.some((container) => container.running) ) - await this.persistSelectedIfInstalled( - Signer.CompatibleSigners[network].dnpName, - this.getUserSettings(network) - ); + await this.persistSelectedIfInstalled({ + dnpName: Signer.CompatibleSigners[network].dnpName, + userSettings: this.getUserSettings(network), + }); } async setNewSigner(network: Network, newWeb3signerDnpName: string | null) { diff --git a/packages/stakers/src/stakerComponent.ts b/packages/stakers/src/stakerComponent.ts index 335ab1a50..73bc0b66c 100644 --- a/packages/stakers/src/stakerComponent.ts +++ b/packages/stakers/src/stakerComponent.ts @@ -74,12 +74,15 @@ export class StakerComponent { ); } - protected async persistSelectedIfInstalled( - dnpName: string, - userSettings: UserSettings - ): Promise { + protected async persistSelectedIfInstalled({ + dnpName, + userSettings, + }: { + dnpName: string; + userSettings: UserSettings; + }): Promise { logs.info(`Persisting ${dnpName}`); - await this.setStakerPkgConfig(dnpName, userSettings); + await this.setStakerPkgConfig({ dnpName, isInstalled: true, userSettings }); } protected async setNew({ @@ -122,7 +125,13 @@ export class StakerComponent { if (!newStakerDnpName) return; // set staker config - await this.setStakerPkgConfig(newStakerDnpName, userSettings); + await this.setStakerPkgConfig({ + dnpName: newStakerDnpName, + isInstalled: Boolean( + await listPackageNoThrow({ dnpName: newStakerDnpName }) + ), + userSettings, + }); } /** @@ -132,12 +141,17 @@ export class StakerComponent { * - adds the staker network to the docker-compose file * - starts the staker pkg */ - private async setStakerPkgConfig( - dnpName: string, - userSettings: UserSettings - ): Promise { + private async setStakerPkgConfig({ + dnpName, + isInstalled, + userSettings, + }: { + dnpName: string; + isInstalled: boolean; + userSettings: UserSettings; + }): Promise { // ensure pkg installed - if (!(await listPackageNoThrow({ dnpName }))) + if (!isInstalled) await packageInstall(this.dappnodeInstaller, { name: dnpName, userSettings: userSettings ? { [dnpName]: userSettings } : {},