Skip to content

Commit decd7c3

Browse files
committed
Adapters with IRuntimeAdapter interface
1 parent 3753ca1 commit decd7c3

File tree

13 files changed

+153
-89
lines changed

13 files changed

+153
-89
lines changed

Diff for: packages/adapter-docker/src/docker-instance-adapter.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
InstanceConfig,
1212
RunnerContainerConfiguration,
1313
InstanceLimits,
14-
STHConfiguration,
14+
DockerAdapterConfiguration,
1515
} from "@scramjet/types";
1616
import path from "path";
1717
import { DockerodeDockerHelper } from "./dockerode-docker-helper";
@@ -32,6 +32,7 @@ IComponent {
3232
private dockerHelper: IDockerHelper;
3333
private _limits?: InstanceLimits = {};
3434
private resources: DockerAdapterResources = {};
35+
3536
id: string = "";
3637

3738
logger: IObjectLogger;
@@ -41,7 +42,7 @@ IComponent {
4142
get limits() { return this._limits || {} as InstanceLimits; }
4243
private set limits(value: InstanceLimits) { this._limits = value; }
4344

44-
constructor(_sthConfig: STHConfiguration, id: string = "") {
45+
constructor(_config: DockerAdapterConfiguration, id: string = "") {
4546
this.dockerHelper = new DockerodeDockerHelper();
4647

4748
this.logger = new ObjLogger(this, { id });

Diff for: packages/adapter-docker/src/index.ts

+32-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,39 @@
1+
import { DockerAdapterConfiguration, IInstanceAdapter, IRuntimeAdapter, ISequenceAdapter } from "@scramjet/types";
12
import { DockerodeDockerHelper } from "./dockerode-docker-helper";
3+
import { DockerSequenceAdapter } from "./docker-sequence-adapter";
4+
import { DockerInstanceAdapter } from "./docker-instance-adapter";
25

36
/**
47
* Adapter module must provide SequenceAdapter, InstanceAdapter classes, init method and name field.
58
*/
6-
export { DockerSequenceAdapter as SequenceAdapter } from "./docker-sequence-adapter";
7-
export { DockerInstanceAdapter as InstanceAdapter } from "./docker-instance-adapter";
9+
export default class DockerAdapter implements IRuntimeAdapter {
10+
name = "docker";
811

9-
export const init = async (..._args: any[]) => {
10-
return await DockerodeDockerHelper.isDockerConfigured() ? {} : { error: "Docker initialization failed" };
11-
};
12+
#_instanceAdapter: IInstanceAdapter;
13+
#_sequenceAdapter: ISequenceAdapter;
1214

13-
export const name = "docker";
15+
get instanceAdapter() {
16+
return this.#_instanceAdapter;
17+
}
18+
19+
get sequenceAdapter() {
20+
return this.#_sequenceAdapter;
21+
}
22+
23+
config: DockerAdapterConfiguration;
24+
25+
constructor(config: DockerAdapterConfiguration) {
26+
this.config = config;
27+
28+
this.#_instanceAdapter = new DockerInstanceAdapter(this.config);
29+
this.#_sequenceAdapter = new DockerSequenceAdapter(this.config);
30+
}
31+
32+
getSequenceAdapter(): ISequenceAdapter {
33+
return this.#_sequenceAdapter;
34+
}
35+
36+
async init(config: any): Promise<{ error?: string }> {
37+
return await DockerodeDockerHelper.isDockerConfigured() ? {} : { error: "Docker initialization failed" };
38+
}
39+
}

Diff for: packages/adapter-k8s/src/index.ts

+34-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,41 @@
1+
import { IInstanceAdapter, IRuntimeAdapter, ISequenceAdapter, K8SAdapterConfiguration } from "@scramjet/types";
2+
import { KubernetesInstanceAdapter } from "./kubernetes-instance-adapter";
3+
import { KubernetesSequenceAdapter } from "./kubernetes-sequence-adapter";
4+
15
/**
26
* Adapter module must provide SequenceAdapter, InstanceAdapter classes, init method and name field.
37
*/
48
export { KubernetesSequenceAdapter as SequenceAdapter } from "./kubernetes-sequence-adapter";
59
export { KubernetesInstanceAdapter as InstanceAdapter } from "./kubernetes-instance-adapter";
610

7-
export const init = async (..._args: any[]) => {
8-
return Promise.resolve({ });
9-
};
11+
export default class KubernetesAdapter implements IRuntimeAdapter {
12+
name = "kubernetes";
13+
14+
#_instanceAdapter: IInstanceAdapter;
15+
#_sequenceAdapter: ISequenceAdapter;
16+
17+
get instanceAdapter() {
18+
return this.#_instanceAdapter;
19+
}
20+
21+
get sequenceAdapter() {
22+
return this.#_sequenceAdapter;
23+
}
24+
25+
config: K8SAdapterConfiguration;
26+
27+
constructor(config: K8SAdapterConfiguration) {
28+
this.config = config;
29+
30+
this.#_instanceAdapter = new KubernetesInstanceAdapter(this.config);
31+
this.#_sequenceAdapter = new KubernetesSequenceAdapter(this.config);
32+
}
33+
34+
getSequenceAdapter(): ISequenceAdapter {
35+
return this.#_sequenceAdapter;
36+
}
1037

11-
export const name = "kubernetes";
38+
async init(config: any): Promise<{ error?: string }> {
39+
return Promise.resolve({});
40+
}
41+
}

Diff for: packages/adapter-k8s/src/kubernetes-instance-adapter.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import path from "path";
1515
import { ObjLogger } from "@scramjet/obj-logger";
1616
import { createReadStream } from "fs";
1717
import { KubernetesClientAdapter } from "./kubernetes-client-adapter";
18-
import { adapterConfigDecoder } from "./kubernetes-config-decoder";
18+
//import { adapterConfigDecoder } from "./kubernetes-config-decoder";
1919
import { getRunnerEnvEntries } from "@scramjet/adapters-utils";
2020
import { PassThrough } from "stream";
2121
import { RunnerExitCode } from "@scramjet/symbols";
@@ -42,13 +42,13 @@ IComponent {
4242
constructor(config: K8SAdapterConfiguration) {
4343
// @TODO this is a redundant check (it was already checked in sequence adapter)
4444
// We should move this to config service decoding: https://github.com/scramjetorg/transform-hub/issues/279
45-
const decodedAdapterConfig = adapterConfigDecoder.decode(config);
45+
// const decodedAdapterConfig = adapterConfigDecoder.decode(config);
4646

47-
if (!decodedAdapterConfig.isOk()) {
48-
throw new Error("Invalid Kubernetes Adapter configuration");
49-
}
47+
// if (!decodedAdapterConfig.isOk()) {
48+
// throw new Error("Invalid Kubernetes Adapter configuration");
49+
// }
5050

51-
this.adapterConfig = decodedAdapterConfig.value;
51+
this.adapterConfig = config;//decodedAdapterConfig.value;
5252
this.logger = new ObjLogger(this);
5353
}
5454

Diff for: packages/adapter-k8s/src/kubernetes-sequence-adapter.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class KubernetesSequenceAdapter implements ISequenceAdapter {
5757

5858
private adapterConfig: K8SAdapterConfiguration;
5959

60-
constructor(config: KubernetesSequenceAdapter) {
60+
constructor(config: K8SAdapterConfiguration) {
6161
const decodedAdapterConfig = adapterConfigDecoder.decode(config);
6262

6363
if (!decodedAdapterConfig.isOk()) {

Diff for: packages/adapter-process/src/index.ts

+37-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,43 @@
1+
import { IInstanceAdapter, IRuntimeAdapter, ISequenceAdapter, ProcessAdapterConfiguration } from "@scramjet/types";
2+
import { ProcessInstanceAdapter } from "./process-instance-adapter";
3+
import { ProcessSequenceAdapter } from "./process-sequence-adapter";
4+
15
/**
2-
* Adapter module must provide SequenceAdapter, InstanceAdapter classes, init method and name field.
6+
* Adapter class must implement IRuntimeAdapter Interface.
37
*/
4-
export { ProcessSequenceAdapter as SequenceAdapter } from "./process-sequence-adapter";
5-
export { ProcessInstanceAdapter as InstanceAdapter } from "./process-instance-adapter";
68

7-
export const init = async (config: any) => {
8-
if (!config.sequencesRoot) {
9-
return Promise.reject({ error: "No 'sequencesRoot' in config" });
9+
export default class ProcessAdapter implements IRuntimeAdapter {
10+
name = "process";
11+
12+
#_instanceAdapter: IInstanceAdapter;
13+
#_sequenceAdapter: ISequenceAdapter;
14+
15+
get instanceAdapter() {
16+
return this.#_instanceAdapter;
17+
}
18+
19+
get sequenceAdapter() {
20+
return this.#_sequenceAdapter;
21+
}
22+
23+
config: ProcessAdapterConfiguration;
24+
25+
constructor(config: ProcessAdapterConfiguration) {
26+
this.config = config;
27+
28+
this.#_instanceAdapter = new ProcessInstanceAdapter(this.config);
29+
this.#_sequenceAdapter = new ProcessSequenceAdapter(this.config);
1030
}
1131

12-
return Promise.resolve({});
13-
};
32+
getSequenceAdapter(): ISequenceAdapter {
33+
return this.#_sequenceAdapter;
34+
}
35+
36+
init(config: any): Promise<{ error?: string }> {
37+
if (!config.sequencesRoot) {
38+
return Promise.reject({ error: "No 'sequencesRoot' in config" });
39+
}
1440

15-
export const name = "process";
41+
return Promise.resolve({});
42+
}
43+
}

Diff for: packages/adapter-process/src/process-instance-adapter.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { STHConfiguration,
1+
import {
22
ExitCode,
33
InstanceConfig,
44
InstanceLimits,
55
IObjectLogger,
66
MonitoringMessageData,
77
SequenceConfig,
8-
IInstanceAdapter
8+
IInstanceAdapter,
9+
ProcessAdapterConfiguration
910
} from "@scramjet/types";
1011
import { ObjLogger } from "@scramjet/obj-logger";
1112
import { streamToString } from "@scramjet/utility";
@@ -22,7 +23,7 @@ const gotPython = "\n _ \n __ _____ _ __ ___
2223
*/
2324
class ProcessInstanceAdapter implements IInstanceAdapter {
2425
logger: IObjectLogger;
25-
sthConfig: STHConfiguration;
26+
config: ProcessAdapterConfiguration;
2627

2728
private runnerProcess?: ChildProcess;
2829
private crashLogStreams?: Promise<string[]>;
@@ -34,9 +35,9 @@ class ProcessInstanceAdapter implements IInstanceAdapter {
3435
this.logger.warn("Limits are not yet supported in process runner");
3536
}
3637

37-
constructor(config: STHConfiguration) {
38+
constructor(config: ProcessAdapterConfiguration) {
3839
this.logger = new ObjLogger(this);
39-
this.sthConfig = config;
40+
this.config = config;
4041
}
4142

4243
async init(): Promise<void> {
@@ -71,7 +72,7 @@ class ProcessInstanceAdapter implements IInstanceAdapter {
7172
this.logger.trace(gotPython);
7273
const runnerPath = path.resolve(__dirname, require.resolve("@scramjet/python-runner"));
7374

74-
if (this.sthConfig.debug)
75+
if (this.config.debug)
7576
debugFlags = ["-m", "pdb", "-c", "continue"];
7677

7778
return [
@@ -82,7 +83,7 @@ class ProcessInstanceAdapter implements IInstanceAdapter {
8283
"./python-runner-startup.log",
8384
];
8485
}
85-
if (this.sthConfig.debug)
86+
if (this.config.debug)
8687
debugFlags = ["--inspect-brk=9229"];
8788

8889
return [

Diff for: packages/host/src/lib/adapter-manager.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { ObjLogger } from "@scramjet/obj-logger";
22
import { IRuntimeAdapter, InstanceRequirements, STHConfiguration } from "@scramjet/types";
33

4+
export type InitializedRuntimeAdapter = IRuntimeAdapter & {
5+
pkgName: string;
6+
status: "ready" | { error?: string };
7+
};
8+
49
export class AdapterManager {
5-
adapters: { [key: string]: IRuntimeAdapter } = {};
10+
adapters: { [key: string]: InitializedRuntimeAdapter } = {};
611
sthConfig: STHConfiguration;
712

813
logger = new ObjLogger(this);
@@ -23,8 +28,8 @@ export class AdapterManager {
2328
Object.keys(this.sthConfig.adapters).map(
2429
async (pkgName) => {
2530
const typedPkgName = pkgName as unknown as keyof STHConfiguration["adapters"];
26-
const adapter = Object.assign(await import(pkgName), { pkgName }) as IRuntimeAdapter;
27-
31+
const adapter = Object.assign(new ((await import(pkgName)).default), { pkgName }) as InitializedRuntimeAdapter;
32+
console.log(adapter)
2833
if (!AdapterManager.validateAdapter(adapter)) {
2934
throw new Error(`Invalid adapter provided ${adapter.pkgName}`);
3035
}
@@ -63,7 +68,7 @@ export class AdapterManager {
6368
* @returns {boolean} True if required fields are available.
6469
*/
6570
static validateAdapter(adapter: IRuntimeAdapter): boolean {
66-
return !!(adapter.name.trim() && ["SequenceAdapter", "InstanceAdapter", "init"].every((className: string) => className in adapter));
71+
return !!(adapter.name?.trim() && ["sequenceAdapter", "instanceAdapter", "init"].every((className: string) => className in adapter));
6772
}
6873

6974
/**
@@ -84,7 +89,7 @@ export class AdapterManager {
8489
* @param {string} pkgName Adapter package name.
8590
* @returns {IRuntimeAdapter} Adapter
8691
*/
87-
getAdapterByName(pkgName: string): IRuntimeAdapter | undefined {
92+
getAdapterByName(pkgName: string): InitializedRuntimeAdapter | undefined {
8893
return Object.values(this.adapters).find(a => a.pkgName === pkgName);
8994
}
9095

Diff for: packages/host/src/lib/host.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ export class Host implements IComponent {
104104
* Instance of CPMConnector used to communicate with Manager.
105105
*/
106106
cpmConnector?: CPMConnector;
107+
108+
/**
109+
*
110+
*/
107111
adapterManager!: AdapterManager;
108112

109113
/**
@@ -338,7 +342,7 @@ export class Host implements IComponent {
338342

339343
this.logger.info(`Default adapter for running Sequences: "${this.adapterName}" (${defaultAdapter?.name})`);
340344
} else {
341-
this.logger.warn("No RuntimeAdapters.");
345+
this.logger.warn("No Runtime Adapters.");
342346
}
343347

344348
this.pushTelemetry("Host started");
@@ -499,7 +503,6 @@ export class Host implements IComponent {
499503
});
500504

501505
this.api.op("delete", `${this.apiBase}/sequence/:id`, (req: ParsedMessage) => this.handleDeleteSequence(req));
502-
503506
this.api.op("post", `${this.apiBase}/sequence/:id/start`, async (req: ParsedMessage) => this.handleStartSequence(req));
504507

505508
this.api.get(`${this.apiBase}/sequence/:id`, (req) => this.getSequence(req.params?.id));
@@ -668,7 +671,7 @@ export class Host implements IComponent {
668671
};
669672
}
670673

671-
const sequenceAdapter = new adapter.SequenceAdapter(this.config);
674+
const sequenceAdapter = adapter.sequenceAdapter;
672675

673676
await sequenceAdapter.remove(sequenceInfo.config);
674677
this.sequencesStore.delete(id);
@@ -739,7 +742,7 @@ export class Host implements IComponent {
739742
throw new Error("Error identifying existing sequences. Adapter unavailable");
740743
}
741744

742-
const sequenceAdapter = new adapter!.SequenceAdapter(this.config);
745+
const sequenceAdapter = adapter!.sequenceAdapter;
743746

744747
try {
745748
await sequenceAdapter.init();
@@ -779,7 +782,7 @@ export class Host implements IComponent {
779782
};
780783
}
781784

782-
const sequenceAdapter = new adapter.SequenceAdapter(this.config);
785+
const sequenceAdapter = adapter.sequenceAdapter;
783786

784787
sequenceAdapter.logger.updateBaseLog({ id });
785788
sequenceAdapter.logger.pipe(this.logger);
@@ -1030,7 +1033,7 @@ export class Host implements IComponent {
10301033
throw new Error("Failed to use adapter");
10311034
}
10321035

1033-
const instanceAdapter = new adapter.InstanceAdapter(this.config);
1036+
const instanceAdapter = adapter.instanceAdapter;
10341037

10351038
const communicationHandler = new CommunicationHandler();
10361039
const id = payload.instanceId || IDProvider.generate();

Diff for: packages/sth-config/src/config-service.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { DeepPartial, PublicSTHConfiguration, STHConfiguration } from "@scramjet/types";
22

33
import { merge } from "@scramjet/utility";
4-
import path from "path";
54
import { homedir } from "os";
5+
import path from "path";
6+
// import path from "path";
7+
// import { homedir } from "os";
68

79
const imageConfig = require("./image-config.json");
810

@@ -54,7 +56,7 @@ const _defaultConfig: STHConfiguration = {
5456
},
5557
adapters: {
5658
"@scramjet/adapter-process": {
57-
sequencesRoot: path.join(homedir(), ".scramjet_sequences"),
59+
sequencesRoot: path.join(homedir(), ".scramjet_sequences")
5860
},
5961
"@scramjet/adapter-docker": {
6062
prerunner: {
@@ -122,7 +124,7 @@ export class ConfigService {
122124
}
123125

124126
static getConfigInfo(config: STHConfiguration): PublicSTHConfiguration {
125-
const kubeFull = config.adapters["@scramjet/adapter-k8s"]!;
127+
const kubeFull = config.adapters["@scramjet/adapter-k8s"] || {};
126128
const {
127129
cpmSslCaPath: optionsCpmSslCaPath,
128130
...safe

0 commit comments

Comments
 (0)