Skip to content

Commit

Permalink
fix: env merge & deploy start validation
Browse files Browse the repository at this point in the history
  • Loading branch information
robot9706 committed Dec 16, 2024
1 parent fc97901 commit 2cca4e0
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 33 deletions.
17 changes: 16 additions & 1 deletion web/crux-ui/src/models/container-merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Marker,
Port,
UniqueKey,
UniqueKeyValue,
UniqueSecretKey,
UniqueSecretKeyValue,
Volume,
Expand Down Expand Up @@ -84,7 +85,7 @@ export const mergeSecrets = (strong: UniqueSecretKeyValue[], weak: UniqueSecretK
export const mergeConfigs = (strong: ContainerConfigData, weak: ContainerConfigData): ContainerConfigData => ({
// common
name: strong.name ?? weak.name,
environment: strong.environment ?? weak.environment,
environment: mergeUniqueKeyValues(strong.environment, weak.environment),
secrets: mergeSecretKeys(strong.secrets, weak.secrets),
user: mergeNumber(strong.user, weak.user),
workingDirectory: strong.workingDirectory ?? weak.workingDirectory,
Expand Down Expand Up @@ -154,6 +155,20 @@ const mergeUniqueKeys = <T extends UniqueKey>(strong: T[], weak: T[]): T[] => {
return [...strong, ...missing]
}

// TODO(@robot9706): Validate
const mergeUniqueKeyValues = <T extends UniqueKeyValue>(strong: T[], weak: T[]): T[] => {
if (!strong) {
return weak ?? null
}

if (!weak) {
return strong
}

const missing = weak.filter(w => !strong.find(it => it.key === w.key))
return [...strong, ...missing]
}

const mergePorts = (strong: Port[], weak: Port[]): Port[] => {
if (!strong) {
return weak ?? null
Expand Down
49 changes: 20 additions & 29 deletions web/crux/src/app/deploy/interceptors/deploy.start.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getConflictsForConcreteConfig } from 'src/domain/container-conflict'
import { mergeConfigsWithConcreteConfig } from 'src/domain/container-merge'
import { checkDeploymentDeployability } from 'src/domain/deployment'
import { parseDyrectorioEnvRules } from 'src/domain/image'
import { missingSecretsOf } from 'src/domain/start-deployment'
import { deploymentConfigOf, instanceConfigOf, missingSecretsOf } from 'src/domain/start-deployment'
import { createStartDeploymentSchema, nullifyUndefinedProperties, yupValidate } from 'src/domain/validation'
import { CruxPreconditionFailedException } from 'src/exception/crux-exception'
import PrismaService from 'src/services/prisma.service'
Expand Down Expand Up @@ -110,25 +110,7 @@ export default class DeployStartValidationInterceptor implements NestInterceptor
})
yupValidate(createStartDeploymentSchema(instanceValidations), target)

const missingSecrets = deployment.instances
.map(it => {
const imageConfig = it.image.config as any as ContainerConfigData
const instanceConfig = it.config as any as ConcreteContainerConfigData
const mergedConfig = mergeConfigsWithConcreteConfig([imageConfig], instanceConfig)

return missingSecretsOf(it.configId, mergedConfig)
})
.filter(it => !!it)

if (missingSecrets.length > 0) {
throw new CruxPreconditionFailedException({
message: 'Required secrets must have values!',
property: 'instanceSecrets',
value: missingSecrets,
})
}

// config bundles
// check config bundle conflicts
if (deployment.configBundles.length > 0) {
const configs = deployment.configBundles.map(it => it.configBundle.config as any as ContainerConfigDataWithId)
const concreteConfig = deployment.config as any as ConcreteContainerConfigData
Expand All @@ -140,16 +122,25 @@ export default class DeployStartValidationInterceptor implements NestInterceptor
value: Object.keys(conflicts).join(', '),
})
}
}

const mergedConfig = mergeConfigsWithConcreteConfig(configs, concreteConfig)
const missingInstanceSecrets = missingSecretsOf(deployment.configId, mergedConfig)
if (missingInstanceSecrets) {
throw new CruxPreconditionFailedException({
message: 'Required secrets must have values!',
property: 'deploymentSecrets',
value: missingInstanceSecrets,
})
}
// validate instance configs
const deploymentConfig = deploymentConfigOf(deployment)

const missingSecrets = deployment.instances
.map(it => {
const instanceConfig = instanceConfigOf(deployment, deploymentConfig, it)

return missingSecretsOf(it.configId, instanceConfig)
})
.filter(it => !!it)

if (missingSecrets.length > 0) {
throw new CruxPreconditionFailedException({
message: 'Required secrets must have values!',
property: 'instanceSecrets',
value: missingSecrets,
})
}

// node
Expand Down
22 changes: 19 additions & 3 deletions web/crux/src/domain/container-merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Marker,
Port,
UniqueKey,
UniqueKeyValue,
UniqueSecretKey,
UniqueSecretKeyValue,
Volume,
Expand Down Expand Up @@ -97,10 +98,11 @@ export const mergeSecrets = (strong: UniqueSecretKeyValue[], weak: UniqueSecretK
weak = weak ?? []
strong = strong ?? []

const overriddenIds: Set<string> = new Set(strong?.map(it => it.id))
// TODO(@robot9706): Validate this
const overriddenKeys: Set<string> = new Set(strong?.map(it => it.key))

const missing: UniqueSecretKeyValue[] = weak
.filter(it => !overriddenIds.has(it.id))
.filter(it => !overriddenKeys.has(it.key))
.map(it => ({
...it,
value: '',
Expand All @@ -114,7 +116,7 @@ export const mergeSecrets = (strong: UniqueSecretKeyValue[], weak: UniqueSecretK
export const mergeConfigs = (strong: ContainerConfigData, weak: ContainerConfigData): ContainerConfigData => ({
// common
name: strong.name ?? weak.name,
environment: strong.environment ?? weak.environment,
environment: mergeUniqueKeyValues(strong.environment, weak.environment),
secrets: mergeSecretKeys(strong.secrets, weak.secrets),
user: mergeNumber(strong.user, weak.user),
workingDirectory: strong.workingDirectory ?? weak.workingDirectory,
Expand Down Expand Up @@ -184,6 +186,20 @@ const mergeUniqueKeys = <T extends UniqueKey>(strong: T[], weak: T[]): T[] => {
return [...strong, ...missing]
}

// TODO(@robot9706): Validate
const mergeUniqueKeyValues = <T extends UniqueKeyValue>(strong: T[], weak: T[]): T[] => {
if (!strong) {
return weak ?? null
}

if (!weak) {
return strong
}

const missing = weak.filter(w => !strong.find(it => it.key === w.key))
return [...strong, ...missing]
}

const mergePorts = (strong: Port[], weak: Port[]): Port[] => {
if (!strong) {
return weak ?? null
Expand Down

0 comments on commit 2cca4e0

Please sign in to comment.