@nosana/node 1.0.1 → 1.0.2-rc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/NodeManager/node/Node.js +1 -1
- package/dist/NodeManager/node/api/routes/post/node-validation.js +10 -6
- package/dist/NodeManager/node/job/jobHandler.js +9 -0
- package/dist/NodeManager/provider/Provider.d.ts +2 -1
- package/dist/NodeManager/provider/Provider.js +4 -0
- package/dist/NodeManager/provider/containerOrchestration/docker/createDockerRunOptions.d.ts +1 -1
- package/dist/NodeManager/provider/containerOrchestration/docker/createDockerRunOptions.js +2 -1
- package/dist/NodeManager/provider/containerOrchestration/docker/index.d.ts +4 -2
- package/dist/NodeManager/provider/containerOrchestration/docker/index.js +16 -9
- package/dist/NodeManager/provider/containerOrchestration/interface.d.ts +3 -1
- package/dist/NodeManager/provider/containerOrchestration/podman/index.d.ts +2 -2
- package/dist/NodeManager/provider/containerOrchestration/podman/index.js +2 -5
- package/dist/NodeManager/provider/containerOrchestration/selectContainerOrchestration.d.ts +1 -1
- package/dist/NodeManager/provider/containerOrchestration/selectContainerOrchestration.js +6 -3
- package/dist/cli/commands/prune/action.js +1 -1
- package/dist/cli/commands/run/action.js +1 -1
- package/dist/cli/commands/sharedOptions/--tee-runtime.d.ts +2 -0
- package/dist/cli/commands/sharedOptions/--tee-runtime.js +5 -0
- package/dist/cli/commands/sharedOptions/index.d.ts +1 -0
- package/dist/cli/commands/sharedOptions/index.js +1 -0
- package/dist/cli/commands/start/__tests__/command.spec.js +3 -2
- package/dist/cli/commands/start/command.js +2 -1
- package/npm-shrinkwrap.json +6 -6
- package/package.json +2 -2
|
@@ -29,7 +29,7 @@ export class BasicNode {
|
|
|
29
29
|
this.sdk = getSDK();
|
|
30
30
|
const db = new DB(options.config).db;
|
|
31
31
|
this.repository = new NodeRepository(db);
|
|
32
|
-
this.containerOrchestration = selectContainerOrchestrationProvider(options.provider, options.podman, options.gpu);
|
|
32
|
+
this.containerOrchestration = selectContainerOrchestrationProvider(options.provider, options.podman, options.gpu, options.trustedExecutionRuntime);
|
|
33
33
|
this.resourceManager = new ResourceManager(this.containerOrchestration, this.repository);
|
|
34
34
|
this.provider = new Provider(this.containerOrchestration, this.repository, this.resourceManager);
|
|
35
35
|
this.apiHandler = new ApiHandler(this.sdk, this.repository, this.provider, options.port);
|
|
@@ -135,8 +135,8 @@ export async function postNodeValidation(req, res) {
|
|
|
135
135
|
return false;
|
|
136
136
|
const a = Number(match[1]), b = Number(match[2]);
|
|
137
137
|
return a < b;
|
|
138
|
-
})() || typeof elem === "string" && /^%%(ops|global).[^%]+%%$/.test(elem)) || "object" === typeof elem && null !== elem && _iu0(elem, true && _exceptionable)))) || "object" === typeof input.expose && null !== input.expose && _io14(input.expose, true && _exceptionable)))) && (undefined === input["private"] || "boolean" === typeof input["private"]) && (undefined === input.gpu || "boolean" === typeof input.gpu) && (undefined === input.work_dir || "string" === typeof input.work_dir) && (undefined === input.output || "string" === typeof input.output) && (null !== input.entrypoint && (undefined === input.entrypoint || "string" === typeof input.entrypoint || Array.isArray(input.entrypoint) && input.entrypoint.every((elem, _index6) => "string" === typeof elem))) && (undefined === input.env || "object" === typeof input.env && null !== input.env && false === Array.isArray(input.env) && _io19(input.env, true && _exceptionable)) && (null !== input.restart_policy && (undefined === input.restart_policy || "no" === input.restart_policy || "always" === input.restart_policy || "unless-stopped" === input.restart_policy || "on-failure" === input.restart_policy || "object" === typeof input.restart_policy && null !== input.restart_policy && _io20(input.restart_policy, true && _exceptionable))) && (undefined === input.required_vram || "number" === typeof input.required_vram) && (undefined === input.resources || Array.isArray(input.resources) && input.resources.every((elem, _index7) => null !== elem && undefined !== elem && ("__remove-if-empty__" === elem || "object" === typeof elem && null !== elem && _iu2(elem, true && _exceptionable)))) && (undefined === input.authentication || "object" === typeof input.authentication && null !== input.authentication && false === Array.isArray(input.authentication) && _io28(input.authentication, true && _exceptionable)) && (1 === Object.keys(input).length || Object.keys(input).every(key => {
|
|
139
|
-
if (["image", "aliases", "cmd", "volumes", "expose", "private", "gpu", "work_dir", "output", "entrypoint", "env", "restart_policy", "required_vram", "resources", "authentication"].some(prop => key === prop))
|
|
138
|
+
})() || typeof elem === "string" && /^%%(ops|global).[^%]+%%$/.test(elem)) || "object" === typeof elem && null !== elem && _iu0(elem, true && _exceptionable)))) || "object" === typeof input.expose && null !== input.expose && _io14(input.expose, true && _exceptionable)))) && (undefined === input["private"] || "boolean" === typeof input["private"]) && (undefined === input.gpu || "boolean" === typeof input.gpu) && (undefined === input.work_dir || "string" === typeof input.work_dir) && (undefined === input.output || "string" === typeof input.output) && (null !== input.entrypoint && (undefined === input.entrypoint || "string" === typeof input.entrypoint || Array.isArray(input.entrypoint) && input.entrypoint.every((elem, _index6) => "string" === typeof elem))) && (undefined === input.env || "object" === typeof input.env && null !== input.env && false === Array.isArray(input.env) && _io19(input.env, true && _exceptionable)) && (null !== input.restart_policy && (undefined === input.restart_policy || "no" === input.restart_policy || "always" === input.restart_policy || "unless-stopped" === input.restart_policy || "on-failure" === input.restart_policy || "object" === typeof input.restart_policy && null !== input.restart_policy && _io20(input.restart_policy, true && _exceptionable))) && (undefined === input.required_vram || "number" === typeof input.required_vram) && (undefined === input.resources || Array.isArray(input.resources) && input.resources.every((elem, _index7) => null !== elem && undefined !== elem && ("__remove-if-empty__" === elem || "object" === typeof elem && null !== elem && _iu2(elem, true && _exceptionable)))) && (undefined === input.authentication || "object" === typeof input.authentication && null !== input.authentication && false === Array.isArray(input.authentication) && _io28(input.authentication, true && _exceptionable)) && (undefined === input.trusted_execution_env || "SEV-SNP" === input.trusted_execution_env) && (1 === Object.keys(input).length || Object.keys(input).every(key => {
|
|
139
|
+
if (["image", "aliases", "cmd", "volumes", "expose", "private", "gpu", "work_dir", "output", "entrypoint", "env", "restart_policy", "required_vram", "resources", "authentication", "trusted_execution_env"].some(prop => key === prop))
|
|
140
140
|
return true;
|
|
141
141
|
const value = input[key];
|
|
142
142
|
if (undefined === value)
|
|
@@ -659,11 +659,11 @@ export async function postNodeValidation(req, res) {
|
|
|
659
659
|
value: input.id
|
|
660
660
|
}), ("object" === typeof input.args && null !== input.args || _report(_exceptionable, {
|
|
661
661
|
path: _path + ".args",
|
|
662
|
-
expected: "(__type.
|
|
662
|
+
expected: "((__type.o8 & TagBase<__type>) | __type.o20)",
|
|
663
663
|
value: input.args
|
|
664
664
|
})) && _vu3(input.args, _path + ".args", true && _exceptionable) || _report(_exceptionable, {
|
|
665
665
|
path: _path + ".args",
|
|
666
|
-
expected: "(__type.
|
|
666
|
+
expected: "((__type.o8 & TagBase<__type>) | __type.o20)",
|
|
667
667
|
value: input.args
|
|
668
668
|
}), undefined === input.results || ("object" === typeof input.results && null !== input.results && false === Array.isArray(input.results) || _report(_exceptionable, {
|
|
669
669
|
path: _path + ".results",
|
|
@@ -930,8 +930,12 @@ export async function postNodeValidation(req, res) {
|
|
|
930
930
|
path: _path + ".authentication",
|
|
931
931
|
expected: "(__type.o18 | undefined)",
|
|
932
932
|
value: input.authentication
|
|
933
|
+
}), undefined === input.trusted_execution_env || "SEV-SNP" === input.trusted_execution_env || _report(_exceptionable, {
|
|
934
|
+
path: _path + ".trusted_execution_env",
|
|
935
|
+
expected: "(\"SEV-SNP\" | undefined)",
|
|
936
|
+
value: input.trusted_execution_env
|
|
933
937
|
}), 1 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).map(key => {
|
|
934
|
-
if (["image", "aliases", "cmd", "volumes", "expose", "private", "gpu", "work_dir", "output", "entrypoint", "env", "restart_policy", "required_vram", "resources", "authentication"].some(prop => key === prop))
|
|
938
|
+
if (["image", "aliases", "cmd", "volumes", "expose", "private", "gpu", "work_dir", "output", "entrypoint", "env", "restart_policy", "required_vram", "resources", "authentication", "trusted_execution_env"].some(prop => key === prop))
|
|
935
939
|
return true;
|
|
936
940
|
const value = input[key];
|
|
937
941
|
if (undefined === value)
|
|
@@ -1706,7 +1710,7 @@ export async function postNodeValidation(req, res) {
|
|
|
1706
1710
|
else
|
|
1707
1711
|
return _report(_exceptionable, {
|
|
1708
1712
|
path: _path,
|
|
1709
|
-
expected: "(__type.o8 | __type.
|
|
1713
|
+
expected: "(__type.o8 | __type.o20)",
|
|
1710
1714
|
value: input
|
|
1711
1715
|
});
|
|
1712
1716
|
})(); const _vu4 = (input, _path, _exceptionable = true) => (() => {
|
|
@@ -83,6 +83,15 @@ export class JobHandler {
|
|
|
83
83
|
});
|
|
84
84
|
return false;
|
|
85
85
|
}
|
|
86
|
+
if (jobDefinition.ops.some(op => op.type === "container/run" && op.args.trusted_execution_env)) {
|
|
87
|
+
if (!await this.provider.hasTrustedExecutionEnvCapability("SEV-SNP")) {
|
|
88
|
+
this.repository.updateflowStateError(this.jobId(), {
|
|
89
|
+
status: 'validation-error',
|
|
90
|
+
error: 'Node does not support Trusted Execution Environments',
|
|
91
|
+
});
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
86
95
|
return true;
|
|
87
96
|
}
|
|
88
97
|
listenForAccountChanges() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { Flow, Operation, OperationArgsMap, OperationType } from '@nosana/sdk';
|
|
2
|
+
import { Flow, Operation, OperationArgsMap, OperationType, TrustedExecutionEnv } from '@nosana/sdk';
|
|
3
3
|
import EventEmitter from 'events';
|
|
4
4
|
import { NodeRepository } from '../repository/NodeRepository.js';
|
|
5
5
|
import { ResourceManager } from '../node/resource/resourceManager.js';
|
|
@@ -11,6 +11,7 @@ export declare class Provider {
|
|
|
11
11
|
private readonly frpcImage;
|
|
12
12
|
private proxyStartupAbortController;
|
|
13
13
|
constructor(containerOrchestration: ContainerOrchestrationInterface, repository: NodeRepository, resourceManager: ResourceManager);
|
|
14
|
+
hasTrustedExecutionEnvCapability(required_environment: TrustedExecutionEnv): Promise<boolean>;
|
|
14
15
|
stopReverseProxyApi(address: string): Promise<boolean>;
|
|
15
16
|
setUpReverseProxyApi(address: string, port: string): Promise<boolean>;
|
|
16
17
|
taskManagerContainerRunOperation(flow: Flow, op: Operation<'container/run'>, controller: AbortController, emitter: EventEmitter): Promise<void>;
|
|
@@ -16,6 +16,9 @@ export class Provider {
|
|
|
16
16
|
this.proxyStartupAbortController = undefined;
|
|
17
17
|
applyLoggingProxyToClass(this);
|
|
18
18
|
}
|
|
19
|
+
async hasTrustedExecutionEnvCapability(required_environment) {
|
|
20
|
+
return this.containerOrchestration.teeRuntime === required_environment;
|
|
21
|
+
}
|
|
19
22
|
async stopReverseProxyApi(address) {
|
|
20
23
|
const frpc_name = `frpc-api-${address}`;
|
|
21
24
|
const networkName = `api-${address}`;
|
|
@@ -221,6 +224,7 @@ export class Provider {
|
|
|
221
224
|
volumes,
|
|
222
225
|
aliases,
|
|
223
226
|
restart_policy: op.args.restart_policy,
|
|
227
|
+
runtime: op.args.trusted_execution_env
|
|
224
228
|
});
|
|
225
229
|
emitter.emit('updateOpState', { providerId: container.id });
|
|
226
230
|
stateManager = new ContainerStateManager(container, controller, emitter, op.args.restart_policy);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ContainerCreateOptions } from "dockerode";
|
|
2
2
|
import { RunContainerArgs } from "../interface";
|
|
3
|
-
export declare function createDockerRunOptions(image: string, { name, cmd, gpu, volumes, env, work_dir, entrypoint, aliases, restart_policy, }: RunContainerArgs, gpuOption: string): ContainerCreateOptions;
|
|
3
|
+
export declare function createDockerRunOptions(image: string, { name, cmd, gpu, volumes, env, work_dir, entrypoint, aliases, restart_policy, runtime }: RunContainerArgs, gpuOption: string): ContainerCreateOptions;
|
|
@@ -10,7 +10,7 @@ function parseRestartPolicy(restart_policy) {
|
|
|
10
10
|
}
|
|
11
11
|
return undefined;
|
|
12
12
|
}
|
|
13
|
-
export function createDockerRunOptions(image, { name, cmd, gpu, volumes, env, work_dir, entrypoint, aliases, restart_policy, }, gpuOption) {
|
|
13
|
+
export function createDockerRunOptions(image, { name, cmd, gpu, volumes, env, work_dir, entrypoint, aliases, restart_policy, runtime }, gpuOption) {
|
|
14
14
|
const devices = [];
|
|
15
15
|
if (gpu) {
|
|
16
16
|
devices.push({
|
|
@@ -56,6 +56,7 @@ export function createDockerRunOptions(image, { name, cmd, gpu, volumes, env, wo
|
|
|
56
56
|
NetworkMode: 'bridge',
|
|
57
57
|
DeviceRequests: devices,
|
|
58
58
|
RestartPolicy: parseRestartPolicy(restart_policy),
|
|
59
|
+
...(runtime ? { Runtime: runtime } : {}),
|
|
59
60
|
},
|
|
60
61
|
};
|
|
61
62
|
}
|
|
@@ -10,8 +10,10 @@ export declare class DockerContainerOrchestration implements ContainerOrchestrat
|
|
|
10
10
|
protocol: 'https' | 'http' | 'ssh' | 'socket';
|
|
11
11
|
name: string;
|
|
12
12
|
gpu: string;
|
|
13
|
+
teeRuntime?: string;
|
|
13
14
|
listeners: Map<string, (() => Promise<void>)[]>;
|
|
14
|
-
constructor(server: string, gpu: string);
|
|
15
|
+
constructor(server: string, gpu: string, teeRuntime?: string);
|
|
16
|
+
checkCustomRuntimeAvailability(runtime: string): Promise<boolean>;
|
|
15
17
|
getContainerByName(name: string): Promise<Container | undefined>;
|
|
16
18
|
getContainersByName(names: string[]): Promise<Container[]>;
|
|
17
19
|
getConnection(): DockerExtended;
|
|
@@ -34,7 +36,7 @@ export declare class DockerContainerOrchestration implements ContainerOrchestrat
|
|
|
34
36
|
getProtocol(): string;
|
|
35
37
|
setupContainerAbortListener(containerId: string, controller: AbortController): void;
|
|
36
38
|
runContainer(args: ContainerCreateOptions, controller?: AbortController): Promise<Container>;
|
|
37
|
-
runFlowContainer(image: string, args: RunContainerArgs
|
|
39
|
+
runFlowContainer(image: string, args: RunContainerArgs): Promise<Container>;
|
|
38
40
|
stopContainer(id: string, controller?: AbortController): Promise<void>;
|
|
39
41
|
stopAndDeleteContainer(id: string, controller?: AbortController): Promise<ContainerInspectInfo | undefined>;
|
|
40
42
|
isContainerExited(id: string): Promise<boolean>;
|
|
@@ -4,11 +4,12 @@ import { createSeverObject } from './utils/createServerObject.js';
|
|
|
4
4
|
import { checkDeprecationDeadline } from './utils/deadline.js';
|
|
5
5
|
import { createDockerRunOptions } from './createDockerRunOptions.js';
|
|
6
6
|
export class DockerContainerOrchestration {
|
|
7
|
-
constructor(server, gpu) {
|
|
7
|
+
constructor(server, gpu, teeRuntime) {
|
|
8
8
|
this.name = 'docker';
|
|
9
9
|
this.gpu = 'all';
|
|
10
10
|
this.listeners = new Map();
|
|
11
11
|
this.gpu = gpu;
|
|
12
|
+
this.teeRuntime = teeRuntime;
|
|
12
13
|
if (server.startsWith('http') || server.startsWith('ssh')) {
|
|
13
14
|
const { host, port, protocol } = createSeverObject(server);
|
|
14
15
|
this.host = host;
|
|
@@ -31,6 +32,19 @@ export class DockerContainerOrchestration {
|
|
|
31
32
|
this.docker = new DockerExtended({ socketPath: this.host });
|
|
32
33
|
}
|
|
33
34
|
}
|
|
35
|
+
async checkCustomRuntimeAvailability(runtime) {
|
|
36
|
+
// TODO: implement a better check for custom runtimes by creating and starting a basic container with the runtime
|
|
37
|
+
try {
|
|
38
|
+
const info = await this.docker.info();
|
|
39
|
+
if (info.Runtimes && info.Runtimes[runtime]) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
34
48
|
async getContainerByName(name) {
|
|
35
49
|
const containers = await this.docker
|
|
36
50
|
.listContainers({ all: true })
|
|
@@ -219,19 +233,12 @@ export class DockerContainerOrchestration {
|
|
|
219
233
|
throw error;
|
|
220
234
|
}
|
|
221
235
|
}
|
|
222
|
-
async runFlowContainer(image, args
|
|
236
|
+
async runFlowContainer(image, args) {
|
|
223
237
|
try {
|
|
224
|
-
if (controller?.signal.aborted) {
|
|
225
|
-
throw controller.signal.reason;
|
|
226
|
-
}
|
|
227
238
|
const container = await this.docker.createContainer({
|
|
228
239
|
...createDockerRunOptions(image, args, this.gpu),
|
|
229
|
-
abortSignal: controller?.signal,
|
|
230
240
|
});
|
|
231
241
|
await container.start();
|
|
232
|
-
if (controller) {
|
|
233
|
-
this.setupContainerAbortListener(container.id, controller);
|
|
234
|
-
}
|
|
235
242
|
return container;
|
|
236
243
|
}
|
|
237
244
|
catch (error) {
|
|
@@ -21,8 +21,10 @@ export type RunContainerArgs = {
|
|
|
21
21
|
entrypoint?: string | string[];
|
|
22
22
|
restart_policy?: RestartPolicy;
|
|
23
23
|
aliases?: string[] | undefined;
|
|
24
|
+
runtime?: string;
|
|
24
25
|
};
|
|
25
26
|
export interface ContainerOrchestrationInterface {
|
|
27
|
+
teeRuntime?: string;
|
|
26
28
|
getConnection(): any;
|
|
27
29
|
pullImage(image: string, auth?: DockerAuth, controller?: AbortController): Promise<void>;
|
|
28
30
|
hasImage(image: string): Promise<boolean>;
|
|
@@ -42,7 +44,7 @@ export interface ContainerOrchestrationInterface {
|
|
|
42
44
|
getContainersByName(names: string[]): Promise<Container[]>;
|
|
43
45
|
getContainer(id: string): Promise<Container>;
|
|
44
46
|
runContainer(args: ContainerCreateOptions, controller?: AbortController): Promise<Container>;
|
|
45
|
-
runFlowContainer(image: string, args: RunContainerArgs
|
|
47
|
+
runFlowContainer(image: string, args: RunContainerArgs): Promise<Container>;
|
|
46
48
|
stopContainer(id: string, controller?: AbortController): Promise<void>;
|
|
47
49
|
stopAndDeleteContainer(id: string, controller?: AbortController): Promise<ContainerInspectInfo | undefined>;
|
|
48
50
|
isContainerExited(id: string): Promise<boolean>;
|
|
@@ -5,8 +5,8 @@ import { RequestInit, Response } from 'undici';
|
|
|
5
5
|
export declare class PodmanContainerOrchestration extends DockerContainerOrchestration {
|
|
6
6
|
private api;
|
|
7
7
|
name: string;
|
|
8
|
-
constructor(server: string, gpu: string);
|
|
8
|
+
constructor(server: string, gpu: string, _teeRuntime?: string);
|
|
9
9
|
libPodAPICall(path: string, options: RequestInit): Promise<Response>;
|
|
10
10
|
createNetwork(_name: string, controller?: AbortController): Promise<void>;
|
|
11
|
-
runFlowContainer(image: string, args: RunContainerArgs
|
|
11
|
+
runFlowContainer(image: string, args: RunContainerArgs): Promise<Container>;
|
|
12
12
|
}
|
|
@@ -2,7 +2,7 @@ import { DockerContainerOrchestration } from '../docker/index.js';
|
|
|
2
2
|
import { createPodmanRunOptions } from './utils/createPodmanRunOptions.js';
|
|
3
3
|
import { fetch, Agent } from 'undici';
|
|
4
4
|
export class PodmanContainerOrchestration extends DockerContainerOrchestration {
|
|
5
|
-
constructor(server, gpu) {
|
|
5
|
+
constructor(server, gpu, _teeRuntime) {
|
|
6
6
|
super(server, gpu);
|
|
7
7
|
this.name = 'podman';
|
|
8
8
|
if (this.protocol === 'socket') {
|
|
@@ -42,7 +42,7 @@ export class PodmanContainerOrchestration extends DockerContainerOrchestration {
|
|
|
42
42
|
throw error;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
async runFlowContainer(image, args
|
|
45
|
+
async runFlowContainer(image, args) {
|
|
46
46
|
try {
|
|
47
47
|
let error;
|
|
48
48
|
// Incase of error, retry 3 times
|
|
@@ -63,9 +63,6 @@ export class PodmanContainerOrchestration extends DockerContainerOrchestration {
|
|
|
63
63
|
});
|
|
64
64
|
if (start.status === 204) {
|
|
65
65
|
const container = this.docker.getContainer(createResult.Id);
|
|
66
|
-
if (controller) {
|
|
67
|
-
this.setupContainerAbortListener(container.id, controller);
|
|
68
|
-
}
|
|
69
66
|
return container;
|
|
70
67
|
}
|
|
71
68
|
else {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ContainerOrchestrationInterface } from './interface.js';
|
|
2
|
-
export declare function selectContainerOrchestrationProvider(provider: string, url: string, gpu: string): ContainerOrchestrationInterface;
|
|
2
|
+
export declare function selectContainerOrchestrationProvider(provider: string, url: string, gpu: string, teeRuntime: string | undefined): ContainerOrchestrationInterface;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { DockerContainerOrchestration } from './docker/index.js';
|
|
2
2
|
import { PodmanContainerOrchestration } from './podman/index.js';
|
|
3
|
-
export function selectContainerOrchestrationProvider(provider, url, gpu) {
|
|
3
|
+
export function selectContainerOrchestrationProvider(provider, url, gpu, teeRuntime) {
|
|
4
|
+
if (provider !== 'docker' && teeRuntime) {
|
|
5
|
+
throw new Error('Custom runtimes are only supported with the Docker provider.');
|
|
6
|
+
}
|
|
4
7
|
switch (provider) {
|
|
5
8
|
case 'podman':
|
|
6
|
-
return new PodmanContainerOrchestration(url, gpu);
|
|
9
|
+
return new PodmanContainerOrchestration(url, gpu, undefined);
|
|
7
10
|
case 'docker':
|
|
8
11
|
default:
|
|
9
|
-
return new DockerContainerOrchestration(url, gpu);
|
|
12
|
+
return new DockerContainerOrchestration(url, gpu, teeRuntime);
|
|
10
13
|
}
|
|
11
14
|
}
|
|
@@ -8,7 +8,7 @@ export async function pruneResources(options) {
|
|
|
8
8
|
try {
|
|
9
9
|
const db = new DB(options.config).db;
|
|
10
10
|
const repository = new NodeRepository(db);
|
|
11
|
-
const containerOrchestration = selectContainerOrchestrationProvider(options.provider, options.podman, options.gpu);
|
|
11
|
+
const containerOrchestration = selectContainerOrchestrationProvider(options.provider, options.podman, options.gpu, undefined);
|
|
12
12
|
const resourceManager = new ResourceManager(containerOrchestration, repository);
|
|
13
13
|
await resourceManager.prune();
|
|
14
14
|
console.log('Finished pruning system');
|
|
@@ -29,7 +29,7 @@ export async function runJob(jobDefinitionFile, options) {
|
|
|
29
29
|
log();
|
|
30
30
|
const db = new DB(options.config).db;
|
|
31
31
|
const repository = createLoggingProxy(new NodeRepository(db));
|
|
32
|
-
const containerOrchestration = selectContainerOrchestrationProvider(options.provider, options.podman, options.gpu);
|
|
32
|
+
const containerOrchestration = selectContainerOrchestrationProvider(options.provider, options.podman, options.gpu, options.trustedExecutionRuntime);
|
|
33
33
|
const resourceManager = new ResourceManager(containerOrchestration, repository);
|
|
34
34
|
const provider = new Provider(containerOrchestration, repository, resourceManager);
|
|
35
35
|
const logger = new ConsoleLogger(false);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { TrustedExecutionEnv } from '@nosana/sdk';
|
|
2
|
+
import { Option } from 'commander';
|
|
3
|
+
export const teeRuntimeOption = new Option('--trusted-execution-runtime <runtime>', 'specify the container runtime to use for TEE containers')
|
|
4
|
+
.choices(Object.values(TrustedExecutionEnv))
|
|
5
|
+
.default(undefined);
|
|
@@ -18,8 +18,8 @@ describe('startNodeCommand', () => {
|
|
|
18
18
|
startNodeCommand.parse(parseArgs);
|
|
19
19
|
expect(startNodeCommand.args[0]).toBe('market address');
|
|
20
20
|
});
|
|
21
|
-
it('should have
|
|
22
|
-
expect(startNodeCommand.options.length).toBe(
|
|
21
|
+
it('should have 9 options', () => {
|
|
22
|
+
expect(startNodeCommand.options.length).toBe(9);
|
|
23
23
|
});
|
|
24
24
|
it.each([
|
|
25
25
|
['--network', '-n', 'mainnet'],
|
|
@@ -29,6 +29,7 @@ describe('startNodeCommand', () => {
|
|
|
29
29
|
['--port', '-p', 5001],
|
|
30
30
|
['--podman', '--docker', '~/.nosana/podman/podman.sock'],
|
|
31
31
|
['--gpu', undefined, 'all'],
|
|
32
|
+
['--trusted-execution-runtime', undefined, undefined],
|
|
32
33
|
])('should have %s option', (long, short, defaultValue) => {
|
|
33
34
|
const option = startNodeCommand.options.find((i) => i.long === long);
|
|
34
35
|
expect(option?.long).toBe(long);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command, Option } from 'commander';
|
|
2
2
|
import { startNode } from './action.js';
|
|
3
|
-
import { networkOption, portOption, rpcOption, walletOption, verboseOption, gpuOption } from '../sharedOptions/index.js';
|
|
3
|
+
import { networkOption, portOption, rpcOption, walletOption, verboseOption, gpuOption, teeRuntimeOption, } from '../sharedOptions/index.js';
|
|
4
4
|
export * from './action.js';
|
|
5
5
|
export const startNodeCommand = new Command('start')
|
|
6
6
|
.description('Start Nosana Node')
|
|
@@ -10,6 +10,7 @@ export const startNodeCommand = new Command('start')
|
|
|
10
10
|
.addOption(walletOption)
|
|
11
11
|
.addOption(new Option('--docker, --podman <URI>', 'Podman/Docker connection URI').default('~/.nosana/podman/podman.sock'))
|
|
12
12
|
.addOption(new Option('-c, --config <path>', 'Config path (to store the flows database and other config)').default('~/.nosana/'))
|
|
13
|
+
.addOption(teeRuntimeOption)
|
|
13
14
|
.addOption(gpuOption)
|
|
14
15
|
.addOption(portOption)
|
|
15
16
|
.addOption(verboseOption)
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nosana/node",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2-rc",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@nosana/node",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.2-rc",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@coral-xyz/anchor": "^0.28.1-beta.1",
|
|
13
13
|
"@inquirer/prompts": "^4.3.0",
|
|
14
|
-
"@nosana/sdk": "^0.4.
|
|
14
|
+
"@nosana/sdk": "^0.4.81",
|
|
15
15
|
"@solana/web3.js": "^1.78.0",
|
|
16
16
|
"bn.js": "^5.2.1",
|
|
17
17
|
"chalk": "^5.3.0",
|
|
@@ -1580,9 +1580,9 @@
|
|
|
1580
1580
|
}
|
|
1581
1581
|
},
|
|
1582
1582
|
"node_modules/@nosana/sdk": {
|
|
1583
|
-
"version": "0.4.
|
|
1584
|
-
"resolved": "https://registry.npmjs.org/@nosana/sdk/-/sdk-0.4.
|
|
1585
|
-
"integrity": "sha512-
|
|
1583
|
+
"version": "0.4.81",
|
|
1584
|
+
"resolved": "https://registry.npmjs.org/@nosana/sdk/-/sdk-0.4.81.tgz",
|
|
1585
|
+
"integrity": "sha512-xviLJyO/MPYKnMHDDMum/t2yXrsVzS8lC325Ru/HfRc4GXz7IkD7/UoahmD8YNGGDZV570zdmasTnaT9N9BkIQ==",
|
|
1586
1586
|
"license": "ISC",
|
|
1587
1587
|
"dependencies": {
|
|
1588
1588
|
"@coral-xyz/anchor": "^0.28.1-beta.1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nosana/node",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2-rc",
|
|
4
4
|
"description": "",
|
|
5
5
|
"bin": {
|
|
6
6
|
"nosana-node": "./dist/src/index.js"
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@coral-xyz/anchor": "^0.28.1-beta.1",
|
|
69
69
|
"@inquirer/prompts": "^4.3.0",
|
|
70
|
-
"@nosana/sdk": "^0.4.
|
|
70
|
+
"@nosana/sdk": "^0.4.81",
|
|
71
71
|
"@solana/web3.js": "^1.78.0",
|
|
72
72
|
"bn.js": "^5.2.1",
|
|
73
73
|
"chalk": "^5.3.0",
|