Skip to content

Commit

Permalink
refactor(sdl): change validation error name
Browse files Browse the repository at this point in the history
  • Loading branch information
ygrishajev committed May 8, 2024
1 parent eb7ee8e commit cdc7380
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 46 deletions.
14 changes: 14 additions & 0 deletions src/error/SdlValidationError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ValidationError } from "./ValidationError";

export class SdlValidationError extends ValidationError {
static assert(condition: unknown, message: string): asserts condition {
if (!condition) {
throw new SdlValidationError(message);
}
}

constructor(message: string) {
super(message);
this.name = "SdlValidationError";
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export class CustomValidationError extends Error {
export class ValidationError extends Error {
static assert(condition: unknown, message: string): asserts condition {
if (!condition) {
throw new CustomValidationError(message);
throw new ValidationError(message);
}
}

constructor(message: string) {
super(message);
this.name = "CustomValidationError";
this.name = "SdlValidationError";
}
}
2 changes: 1 addition & 1 deletion src/error/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./CustomValidationError";
export * from "./SdlValidationError";
12 changes: 6 additions & 6 deletions src/sdl/SDL/SDL.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { faker } from "@faker-js/faker";
import template from "lodash/template";
import omit from "lodash/omit";

import { readYml } from "../../../test/read-yml";
import { SdlValidationError } from "../../error";
import { SDL } from "./SDL";
import { CustomValidationError } from "../../error";
import { faker } from "@faker-js/faker";
import { v2ServiceImageCredentials } from "../types";
import { omit } from "lodash";

const createYML = template(readYml("sdl-hello-world-basic-with-creds"));

Expand Down Expand Up @@ -58,7 +58,7 @@ describe("SDL", () => {

expect(() => {
SDL.fromString(yml, "beta3", "sandbox");
}).toThrowError(new CustomValidationError(`service "web" credentials missing "${field}"`));
}).toThrowError(new SdlValidationError(`service "web" credentials missing "${field}"`));
});

it.each(fields)('should throw an error when credentials "%s" is empty', field => {
Expand All @@ -69,7 +69,7 @@ describe("SDL", () => {

expect(() => {
SDL.fromString(yml, "beta3", "sandbox");
}).toThrowError(new CustomValidationError(`service "web" credentials missing "${field}"`));
}).toThrowError(new SdlValidationError(`service "web" credentials missing "${field}"`));
});

it.each(fields)('should throw an error when credentials "%s" contains spaces only', field => {
Expand All @@ -80,7 +80,7 @@ describe("SDL", () => {

expect(() => {
SDL.fromString(yml, "beta3", "sandbox");
}).toThrowError(new CustomValidationError(`service "web" credentials missing "${field}"`));
}).toThrowError(new SdlValidationError(`service "web" credentials missing "${field}"`));
});
});
});
Expand Down
31 changes: 13 additions & 18 deletions src/sdl/SDL/SDL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { default as stableStringify } from "json-stable-stringify";
import crypto from "node:crypto";
import { MAINNET_ID, USDC_IBC_DENOMS } from "../../config/network";
import { NetworkId } from "../../types/network";
import { CustomValidationError } from "../../error";
import { SdlValidationError } from "../../error";

const Endpoint_SHARED_HTTP = 0;
const Endpoint_RANDOM_PORT = 1;
Expand Down Expand Up @@ -182,7 +182,7 @@ export class SDL {
.map(resource => resource.price.denom);
const invalidDenom = denoms.find(denom => denom !== "uakt" && denom !== usdcDenom);

CustomValidationError.assert(!invalidDenom, `Invalid denom: "${invalidDenom}". Only uakt and ${usdcDenom} are supported.`);
SdlValidationError.assert(!invalidDenom, `Invalid denom: "${invalidDenom}". Only uakt and ${usdcDenom} are supported.`);
}

private validateEndpoints() {
Expand All @@ -192,9 +192,9 @@ export class SDL {

Object.keys(this.data.endpoints).forEach(endpointName => {
const endpoint = this.data.endpoints[endpointName];
CustomValidationError.assert(this.ENDPOINT_NAME_VALIDATION_REGEX.test(endpointName), `Endpoint named "${endpointName}" is not a valid name.`);
CustomValidationError.assert(!!endpoint.kind, `Endpoint named "${endpointName}" has no kind.`);
CustomValidationError.assert(endpoint.kind === this.ENDPOINT_KIND_IP, `Endpoint named "${endpointName}" has an unknown kind "${endpoint.kind}".`);
SdlValidationError.assert(this.ENDPOINT_NAME_VALIDATION_REGEX.test(endpointName), `Endpoint named "${endpointName}" is not a valid name.`);
SdlValidationError.assert(!!endpoint.kind, `Endpoint named "${endpointName}" has no kind.`);
SdlValidationError.assert(endpoint.kind === this.ENDPOINT_KIND_IP, `Endpoint named "${endpointName}" has an unknown kind "${endpoint.kind}".`);
});
}

Expand All @@ -204,29 +204,26 @@ export class SDL {
if (credentials) {
const credentialsKeys: (keyof v2ServiceImageCredentials)[] = ["host", "username", "password"];
credentialsKeys.forEach(key => {
CustomValidationError.assert(credentials[key]?.trim().length, `service "${serviceName}" credentials missing "${key}"`);
SdlValidationError.assert(credentials[key]?.trim().length, `service "${serviceName}" credentials missing "${key}"`);
});
}
}

private validateDeploymentWithRelations(serviceName: string) {
const deployment = this.data.deployment[serviceName];
CustomValidationError.assert(deployment, `Service "${serviceName}" is not defined in the "deployment" section.`);
SdlValidationError.assert(deployment, `Service "${serviceName}" is not defined in the "deployment" section.`);

Object.keys(this.data.deployment[serviceName]).forEach(deploymentName => {
const serviceDeployment = this.data.deployment[serviceName][deploymentName];
const compute = this.data.profiles.compute[serviceDeployment.profile];
const infra = this.data.profiles.placement[deploymentName];

CustomValidationError.assert(infra, `The placement "${deploymentName}" is not defined in the "placement" section.`);
CustomValidationError.assert(
SdlValidationError.assert(infra, `The placement "${deploymentName}" is not defined in the "placement" section.`);
SdlValidationError.assert(
infra.pricing[serviceDeployment.profile],
`The pricing for the "${serviceDeployment.profile}" profile is not defined in the "${deploymentName}" "placement" definition.`
);
CustomValidationError.assert(
compute,
`The compute requirements for the "${serviceDeployment.profile}" profile are not defined in the "compute" section.`
);
SdlValidationError.assert(compute, `The compute requirements for the "${serviceDeployment.profile}" profile are not defined in the "compute" section.`);
});
}

Expand All @@ -236,19 +233,17 @@ export class SDL {

expose.to?.forEach(to => {
if (to.ip?.length > 0) {
CustomValidationError.assert(to.global, `Error on "${serviceName}", if an IP is declared, the directive must be declared as global.`);
SdlValidationError.assert(to.global, `Error on "${serviceName}", if an IP is declared, the directive must be declared as global.`);

if (!this.data.endpoints?.[to.ip]) {
throw new CustomValidationError(
`Unknown endpoint "${to.ip}" in service "${serviceName}". Add to the list of endpoints in the "endpoints" section.`
);
throw new SdlValidationError(`Unknown endpoint "${to.ip}" in service "${serviceName}". Add to the list of endpoints in the "endpoints" section.`);
}

this.endpointsUsed.add(to.ip);

const portKey = `${to.ip}-${expose.as}-${proto}`;
const otherServiceName = this.portsUsed.get(portKey);
CustomValidationError.assert(
SdlValidationError.assert(
!this.portsUsed.has(portKey),
`IP endpoint ${to.ip} port: ${expose.port} protocol: ${proto} specified by service ${serviceName} already in use by ${otherServiceName}`
);
Expand Down
31 changes: 13 additions & 18 deletions src/sdl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { default as stableStringify } from "json-stable-stringify";
import crypto from "node:crypto";
import { MAINNET_ID, USDC_IBC_DENOMS } from "../config/network";
import { NetworkId } from "../types/network";
import { CustomValidationError } from "../error";
import { SdlValidationError } from "../error";

const Endpoint_SHARED_HTTP = 0;
const Endpoint_RANDOM_PORT = 1;
Expand Down Expand Up @@ -182,7 +182,7 @@ export class SDL {
.map(resource => resource.price.denom);
const invalidDenom = denoms.find(denom => denom !== "uakt" && denom !== usdcDenom);

CustomValidationError.assert(!invalidDenom, `Invalid denom: "${invalidDenom}". Only uakt and ${usdcDenom} are supported.`);
SdlValidationError.assert(!invalidDenom, `Invalid denom: "${invalidDenom}". Only uakt and ${usdcDenom} are supported.`);
}

private validateEndpoints() {
Expand All @@ -192,9 +192,9 @@ export class SDL {

Object.keys(this.data.endpoints).forEach(endpointName => {
const endpoint = this.data.endpoints[endpointName];
CustomValidationError.assert(this.ENDPOINT_NAME_VALIDATION_REGEX.test(endpointName), `Endpoint named "${endpointName}" is not a valid name.`);
CustomValidationError.assert(!!endpoint.kind, `Endpoint named "${endpointName}" has no kind.`);
CustomValidationError.assert(endpoint.kind === this.ENDPOINT_KIND_IP, `Endpoint named "${endpointName}" has an unknown kind "${endpoint.kind}".`);
SdlValidationError.assert(this.ENDPOINT_NAME_VALIDATION_REGEX.test(endpointName), `Endpoint named "${endpointName}" is not a valid name.`);
SdlValidationError.assert(!!endpoint.kind, `Endpoint named "${endpointName}" has no kind.`);
SdlValidationError.assert(endpoint.kind === this.ENDPOINT_KIND_IP, `Endpoint named "${endpointName}" has an unknown kind "${endpoint.kind}".`);
});
}

Expand All @@ -204,29 +204,26 @@ export class SDL {
if (credentials) {
const credentialsKeys: (keyof v2ServiceImageCredentials)[] = ["host", "username", "password"];
credentialsKeys.forEach(key => {
CustomValidationError.assert(credentials[key]?.trim().length, `service "${serviceName}" credentials missing "${key}"`);
SdlValidationError.assert(credentials[key]?.trim().length, `service "${serviceName}" credentials missing "${key}"`);
});
}
}

private validateDeploymentWithRelations(serviceName: string) {
const deployment = this.data.deployment[serviceName];
CustomValidationError.assert(deployment, `Service "${serviceName}" is not defined in the "deployment" section.`);
SdlValidationError.assert(deployment, `Service "${serviceName}" is not defined in the "deployment" section.`);

Object.keys(this.data.deployment[serviceName]).forEach(deploymentName => {
const serviceDeployment = this.data.deployment[serviceName][deploymentName];
const compute = this.data.profiles.compute[serviceDeployment.profile];
const infra = this.data.profiles.placement[deploymentName];

CustomValidationError.assert(infra, `The placement "${deploymentName}" is not defined in the "placement" section.`);
CustomValidationError.assert(
SdlValidationError.assert(infra, `The placement "${deploymentName}" is not defined in the "placement" section.`);
SdlValidationError.assert(
infra.pricing[serviceDeployment.profile],
`The pricing for the "${serviceDeployment.profile}" profile is not defined in the "${deploymentName}" "placement" definition.`
);
CustomValidationError.assert(
compute,
`The compute requirements for the "${serviceDeployment.profile}" profile are not defined in the "compute" section.`
);
SdlValidationError.assert(compute, `The compute requirements for the "${serviceDeployment.profile}" profile are not defined in the "compute" section.`);
});
}

Expand All @@ -236,19 +233,17 @@ export class SDL {

expose.to?.forEach(to => {
if (to.ip?.length > 0) {
CustomValidationError.assert(to.global, `Error on "${serviceName}", if an IP is declared, the directive must be declared as global.`);
SdlValidationError.assert(to.global, `Error on "${serviceName}", if an IP is declared, the directive must be declared as global.`);

if (!this.data.endpoints?.[to.ip]) {
throw new CustomValidationError(
`Unknown endpoint "${to.ip}" in service "${serviceName}". Add to the list of endpoints in the "endpoints" section.`
);
throw new SdlValidationError(`Unknown endpoint "${to.ip}" in service "${serviceName}". Add to the list of endpoints in the "endpoints" section.`);
}

this.endpointsUsed.add(to.ip);

const portKey = `${to.ip}-${expose.as}-${proto}`;
const otherServiceName = this.portsUsed.get(portKey);
CustomValidationError.assert(
SdlValidationError.assert(
!this.portsUsed.has(portKey),
`IP endpoint ${to.ip} port: ${expose.port} protocol: ${proto} specified by service ${serviceName} already in use by ${otherServiceName}`
);
Expand Down

0 comments on commit cdc7380

Please sign in to comment.