Skip to content

Commit

Permalink
feat(api): move deployment relations and ip lease validation from clo…
Browse files Browse the repository at this point in the history
  • Loading branch information
ygrishajev committed May 8, 2024
1 parent 6743fbf commit 5486eab
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 5 deletions.
80 changes: 76 additions & 4 deletions src/sdl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ import {
v2ServiceParams,
v3DeploymentGroup,
v3ManifestServiceParams,
v2StorageAttributes
v2StorageAttributes,
v2ServiceImageCredentials
} from "./types";
import { convertCpuResourceString, convertResourceString } from "./sizes";
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/CustomValidationError";
import { CustomValidationError } from "../error";

const Endpoint_SHARED_HTTP = 0;
const Endpoint_RANDOM_PORT = 1;
Expand Down Expand Up @@ -140,6 +141,10 @@ export class SDL {

private readonly ENDPOINT_KIND_IP = "ip";

private readonly endpointsUsed = new Set<string>();

private readonly portsUsed = new Map<string, string>();

constructor(
public readonly data: v2Sdl,
public readonly version: NetworkVersion = "beta2",
Expand All @@ -159,8 +164,15 @@ export class SDL {
SDL.validateStorage(name, resources.storage);
});

this.validateDenom();
this.validateEndpoints();

Object.keys(this.data.services).forEach(serviceName => {
this.validateDeploymentWithRelations(serviceName);
this.validateLeaseIP(serviceName);
this.validateCredentials(serviceName);
});

this.validateDenom();
}

private validateDenom() {
Expand All @@ -186,6 +198,66 @@ export class SDL {
});
}

private validateCredentials(serviceName: string) {
const { credentials } = this.data.services[serviceName];

if (credentials) {
const credentialsKeys: (keyof v2ServiceImageCredentials)[] = ["host", "username", "password"];
credentialsKeys.forEach(key => {
CustomValidationError.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.`);

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(
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.`
);
});
}

private validateLeaseIP(serviceName: string) {
this.data.services[serviceName].expose?.forEach(expose => {
const proto = this.parseServiceProto(expose.proto);

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.`);

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.`
);
}

this.endpointsUsed.add(to.ip);

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

services() {
if (this.data) {
return this.data.services;
Expand Down Expand Up @@ -599,7 +671,7 @@ export class SDL {
count: deployment[placement].count,
expose: this.v3ManifestExpose(service),
params: this.v3ManifestServiceParams(service.params),
credentials: null
credentials: service.credentials || null
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/sdl/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export type v2ServiceParams = {

export type v2ServiceImageCredentials = {
host: string;
email: string;
email?: string;
username: string;
password: string;
};
Expand Down

0 comments on commit 5486eab

Please sign in to comment.