diff --git a/cluster/pulumi/canton-network/src/dso.ts b/cluster/pulumi/canton-network/src/dso.ts index 1fb21cef8e..959ea02bbf 100644 --- a/cluster/pulumi/canton-network/src/dso.ts +++ b/cluster/pulumi/canton-network/src/dso.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import * as pulumi from '@pulumi/pulumi'; import { + activeVersion, Auth0Client, BackupConfig, BackupLocation, @@ -68,6 +69,7 @@ export class Dso extends pulumi.ComponentResource { cometBftGovernanceKey: CnInput | undefined = undefined, extraDependsOn: CnInput[] = [] ) { + const dynamicConfig = configForSv(svConf.nodeName); return installSvNode( { isFirstSv, @@ -95,7 +97,8 @@ export class Dso extends pulumi.ComponentResource { sweep: svConf.sweep, cometBftGovernanceKey, initialRound: initialRound?.toString(), - ...configForSv(svConf.nodeName), + version: dynamicConfig.versionOverride ?? activeVersion, + ...dynamicConfig, }, this.args.decentralizedSynchronizerUpgradeConfig, extraDependsOn diff --git a/cluster/pulumi/canton-network/src/info.ts b/cluster/pulumi/canton-network/src/info.ts index ca9d345bfe..77a90e006f 100644 --- a/cluster/pulumi/canton-network/src/info.ts +++ b/cluster/pulumi/canton-network/src/info.ts @@ -22,7 +22,8 @@ export function installInfo( gateway: string, decentralizedSynchronizerMigrationConfig: DecentralizedSynchronizerMigrationConfig, scanUrl: string, - scanDependency: Resource + scanDependency: Resource, + version: CnChartVersion ): void { function md5(str: string): string { return createHash('md5').update(str).digest('hex'); @@ -86,14 +87,7 @@ export function installInfo( }, }; - installSpliceHelmChart( - xns, - 'info', - 'splice-info', - infoValues, - decentralizedSynchronizerMigrationConfig.active.version, - { - dependsOn: [scanDependency], - } - ); + installSpliceHelmChart(xns, 'info', 'splice-info', infoValues, version, { + dependsOn: [scanDependency], + }); } diff --git a/cluster/pulumi/canton-network/src/sv.ts b/cluster/pulumi/canton-network/src/sv.ts index 4394cd17b6..9102383e73 100644 --- a/cluster/pulumi/canton-network/src/sv.ts +++ b/cluster/pulumi/canton-network/src/sv.ts @@ -4,7 +4,6 @@ import * as postgres from '@lfdecentralizedtrust/splice-pulumi-common/src/postgr import * as k8s from '@pulumi/kubernetes'; import * as pulumi from '@pulumi/pulumi'; import { - activeVersion, ansDomainPrefix, appsAffinityAndTolerations, BackupConfig, @@ -220,7 +219,7 @@ export async function installSvNode( xns, 'postgres', 'postgres', - activeVersion, + config.version, spliceConfig.pulumiProjectConfig.cloudSql, false, { @@ -234,7 +233,7 @@ export async function installSvNode( xns, `cn-apps-pg`, `cn-apps-pg`, - activeVersion, + config.version, spliceConfig.pulumiProjectConfig.cloudSql, true, { @@ -282,7 +281,8 @@ export async function installSvNode( 'cluster-ingress/cn-http-gateway', decentralizedSynchronizerUpgradeConfig, `http://scan-app.${config.nodeName}:5012`, - scan + scan, + config.version ); if (baseConfig.scanBigQuery && appsPostgres instanceof postgres.CloudPostgres) { @@ -327,7 +327,7 @@ export async function installSvNode( }, }, }, - activeVersion, + config.version, { dependsOn: [xns.ns] } ); @@ -397,6 +397,7 @@ async function installValidator( logAsync: svConfig.logging?.appsAsync, additionalJvmOptions: svConfig.validatorApp?.additionalJvmOptions || '', resources: svConfig.validatorApp?.resources, + version: svConfig.version, }); } @@ -510,7 +511,7 @@ function installSvApp( 'sv-app', 'splice-sv-node', svValues, - activeVersion, + config.version, { dependsOn: dependsOn .concat([postgres]) @@ -574,7 +575,7 @@ function installScan( installRateLimits(xns.logicalName, 'scan-app', 5012, svsConfig.scan.externalRateLimits); } - return installSpliceHelmChart(xns, 'scan', 'splice-scan', scanValues, activeVersion, { + return installSpliceHelmChart(xns, 'scan', 'splice-scan', scanValues, config.version, { // TODO(#893) if possible, don't require parallel start of sv app and scan when using CantonBft dependsOn: dependsOn .concat(decentralizedSynchronizerNode.dependencies) diff --git a/cluster/pulumi/common-sv/src/config.ts b/cluster/pulumi/common-sv/src/config.ts index 0583592c66..397f9a7fd6 100644 --- a/cluster/pulumi/common-sv/src/config.ts +++ b/cluster/pulumi/common-sv/src/config.ts @@ -12,6 +12,7 @@ import { SvIdKey, ValidatorTopupConfig, RateLimitSchema, + CnChartVersion, } from '@lfdecentralizedtrust/splice-pulumi-common'; import { SweepConfig } from '@lfdecentralizedtrust/splice-pulumi-common-validator'; import { clusterYamlConfig } from '@lfdecentralizedtrust/splice-pulumi-common/src/config/config'; @@ -78,6 +79,7 @@ export interface SvConfig extends StaticSvConfig, SingleSvConfiguration { cometBftGovernanceKey?: CnInput; initialRound?: string; periodicTopologySnapshotConfig?: BackupConfig; + version: CnChartVersion; } export const GCPBucketSchema = z.object({ diff --git a/cluster/pulumi/common-sv/src/singleSvConfig.ts b/cluster/pulumi/common-sv/src/singleSvConfig.ts index 47790ca53d..e8bbb153d7 100644 --- a/cluster/pulumi/common-sv/src/singleSvConfig.ts +++ b/cluster/pulumi/common-sv/src/singleSvConfig.ts @@ -9,6 +9,7 @@ import { import { ValidatorAppConfigSchema } from '@lfdecentralizedtrust/splice-pulumi-common-validator/src/config'; import { spliceConfig } from '@lfdecentralizedtrust/splice-pulumi-common/src/config/config'; import { clusterYamlConfig } from '@lfdecentralizedtrust/splice-pulumi-common/src/config/config'; +import { CnChartVersionSchema } from '@lfdecentralizedtrust/splice-pulumi-common/src/config/versionSchema'; import { merge } from 'lodash'; import util from 'node:util'; import { z } from 'zod'; @@ -155,6 +156,7 @@ const SingleSvConfigSchema = z }) .optional(), periodicSnapshots: z.object({ topology: GCPBucketSchema.optional() }).optional(), + versionOverride: CnChartVersionSchema.optional(), }) .strict(); const AllSvsConfigurationSchema = z.record(z.string(), SingleSvConfigSchema).and( diff --git a/cluster/pulumi/common-validator/src/validator.ts b/cluster/pulumi/common-validator/src/validator.ts index e10c30f475..165818dc27 100644 --- a/cluster/pulumi/common-validator/src/validator.ts +++ b/cluster/pulumi/common-validator/src/validator.ts @@ -3,11 +3,11 @@ import * as k8s from '@pulumi/kubernetes'; import * as pulumi from '@pulumi/pulumi'; import { - activeVersion, Auth0Client, BackupConfig, BootstrappingDumpConfig, CLUSTER_BASENAME, + CnChartVersion, CnInput, config, daContactPoint, @@ -76,6 +76,7 @@ type BasicValidatorConfig = { logLevel?: LogLevel; logAsync?: boolean; resources?: K8sResourceSchema; + version: CnChartVersion; }; export type ValidatorInstallConfig = BasicValidatorConfig & { @@ -238,7 +239,7 @@ export async function installValidatorApp( resources: baseConfig.svValidator ? config.resources : {}, ...spliceInstanceNames, }, - activeVersion, + config.version, { dependsOn } ); } diff --git a/cluster/pulumi/common/src/config/migrationSchema.ts b/cluster/pulumi/common/src/config/migrationSchema.ts index fe5957b92b..d5e4029d7c 100644 --- a/cluster/pulumi/common/src/config/migrationSchema.ts +++ b/cluster/pulumi/common/src/config/migrationSchema.ts @@ -2,8 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { z } from 'zod'; -import { CnChartVersion } from '../artifacts'; -import { spliceEnvConfig } from './envConfig'; +import { CnChartVersionSchema } from './versionSchema'; export const defaultActiveMigration = { id: 0, @@ -13,18 +12,6 @@ export const defaultActiveMigration = { }, }; -const migrationVersion = z.string().transform((version, ctx) => { - if (version == 'local' && spliceEnvConfig.optionalEnv('SPLICE_OPERATOR_DEPLOYMENT')) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `Using a local version for the operator deployment is not supported.`, - }); - return z.NEVER; - } else { - return CnChartVersion.parse(version); - } -}); - export const GitReferenceSchema = z.object({ repoUrl: z.string(), gitReference: z.string(), @@ -43,7 +30,7 @@ export const MigrationInfoSchema = z .number() .lt(10, 'Migration id must be less than or equal to 10 as we use in the cometbft ports.') .gte(0), - version: migrationVersion, + version: CnChartVersionSchema, releaseReference: GitReferenceSchema.optional(), sequencer: z .object({ @@ -58,7 +45,7 @@ export const SynchronizerMigrationSchema = z legacy: MigrationInfoSchema.optional(), active: MigrationInfoSchema.extend({ migratingFrom: z.number().optional(), - version: migrationVersion, + version: CnChartVersionSchema, }) .strict() .default(defaultActiveMigration), diff --git a/cluster/pulumi/common/src/config/versionSchema.ts b/cluster/pulumi/common/src/config/versionSchema.ts new file mode 100644 index 0000000000..370ecc92aa --- /dev/null +++ b/cluster/pulumi/common/src/config/versionSchema.ts @@ -0,0 +1,18 @@ +// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +import { z } from 'zod'; + +import { CnChartVersion } from '../artifacts'; +import { spliceEnvConfig } from './envConfig'; + +export const CnChartVersionSchema = z.string().transform((version, ctx) => { + if (version == 'local' && spliceEnvConfig.optionalEnv('SPLICE_OPERATOR_DEPLOYMENT')) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Using a local version for the operator deployment is not supported.`, + }); + return z.NEVER; + } else { + return CnChartVersion.parse(version); + } +}); diff --git a/cluster/pulumi/splitwell/src/splitwell.ts b/cluster/pulumi/splitwell/src/splitwell.ts index cda504c3a6..7895921004 100644 --- a/cluster/pulumi/splitwell/src/splitwell.ts +++ b/cluster/pulumi/splitwell/src/splitwell.ts @@ -176,6 +176,7 @@ export async function installSplitwell( nodeIdentifier: 'splitwell', logLevel: splitwellConfig.logging?.level, logAsync: splitwellConfig.logging?.async, + version: activeVersion, }); } diff --git a/cluster/pulumi/sv-canton/src/canton.ts b/cluster/pulumi/sv-canton/src/canton.ts index ad75d148a3..c48ab84b41 100644 --- a/cluster/pulumi/sv-canton/src/canton.ts +++ b/cluster/pulumi/sv-canton/src/canton.ts @@ -75,13 +75,16 @@ export function installCantonComponents( if (!migrationInfo) { throw new Error(`Migration ${migrationId} not found in migration config`); } + const version = isActiveMigration + ? (svConfig.versionOverride ?? migrationInfo.version) + : migrationInfo.version; const participantPg = dbs?.participant || installPostgres( xns, `participant-${migrationId}-pg`, `participant-pg`, - migrationInfo.version, + version, svConfig.participant?.cloudSql || spliceConfig.pulumiProjectConfig.cloudSql, true, { isActive: migrationStillRunning, migrationId, disableProtection } @@ -92,7 +95,7 @@ export function installCantonComponents( xns, `mediator-${migrationId}-pg`, `mediator-pg`, - migrationInfo.version, + version, svConfig.mediator?.cloudSql || spliceConfig.pulumiProjectConfig.cloudSql, true, { @@ -107,7 +110,7 @@ export function installCantonComponents( xns, `sequencer-${migrationId}-pg`, `sequencer-pg`, - migrationInfo.version, + version, svConfig.sequencer?.cloudSql || spliceConfig.pulumiProjectConfig.cloudSql, true, { isActive: migrationStillRunning, migrationId, disableProtection } @@ -119,7 +122,7 @@ export function installCantonComponents( migrationId, auth0Config, participantPg, - migrationInfo.version, + version, ledgerApiUserSecretSource, imagePullServiceAccountName, withAddedDependencies(opts, ledgerApiUserSecret ? [ledgerApiUserSecret] : []) @@ -135,7 +138,7 @@ export function installCantonComponents( mediatorPostgres: mediatorPostgres, setCoreDbNames: svConfig.isCoreSv, }, - migrationInfo.version, + version, imagePullServiceAccountName, opts ) @@ -152,7 +155,7 @@ export function installCantonComponents( isActiveMigration, migrationConfig.isRunningMigration(), svConfig.onboardingName, - migrationInfo.version, + version, imagePullServiceAccountName, disableProtection, opts diff --git a/cluster/pulumi/validator1/src/validator1.ts b/cluster/pulumi/validator1/src/validator1.ts index 6606439167..bbf6ec7742 100644 --- a/cluster/pulumi/validator1/src/validator1.ts +++ b/cluster/pulumi/validator1/src/validator1.ts @@ -128,6 +128,7 @@ export async function installValidator1( participantPruningConfig, deduplicationDuration: validator1Config?.deduplicationDuration, disableAuth: validator1Config?.disableAuth, + version: activeVersion, }); installIngress(xns, installSplitwell, decentralizedSynchronizerMigrationConfig);