Skip to content

Commit b07ac76

Browse files
committed
Specify Adapter when sending Sequence
1 parent 1dcb09a commit b07ac76

File tree

7 files changed

+61
-43
lines changed

7 files changed

+61
-43
lines changed

packages/api-client/src/host-client.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ export class HostClient implements ClientProvider {
2626
/**
2727
* Returns list of all Sequences on Host.
2828
*
29-
* @returns {Promise<STHRestAPI.GetSequencesResponse[]>} Promise resolving to list of Sequences.
29+
* @returns {Promise<STHRestAPI.GetSequencesResponse>} Promise resolving to list of Sequences.
3030
*/
31-
async listSequences() {
31+
async listSequences(): Promise<STHRestAPI.GetSequencesResponse> {
3232
return this.client.get<STHRestAPI.GetSequencesResponse>("sequences");
3333
}
3434

@@ -37,7 +37,7 @@ export class HostClient implements ClientProvider {
3737
*
3838
* @returns {Promise<STHRestAPI.GetInstancesResponse>} Promise resolving to list of Instances.
3939
*/
40-
async listInstances() {
40+
async listInstances(): Promise<STHRestAPI.GetInstancesResponse> {
4141
return this.client.get<STHRestAPI.GetInstancesResponse>("instances");
4242
}
4343

@@ -46,7 +46,7 @@ export class HostClient implements ClientProvider {
4646
*
4747
* @returns {Promise<STHRestAPI.GetEntitiesResponse>} Promise resolving to list of entities.
4848
*/
49-
async listEntities() {
49+
async listEntities(): Promise<STHRestAPI.GetEntitiesResponse> {
5050
return this.client.get<STHRestAPI.GetEntitiesResponse>("entities");
5151
}
5252

@@ -80,7 +80,7 @@ export class HostClient implements ClientProvider {
8080
*/
8181
async sendSequence(
8282
sequencePackage: Parameters<HttpClient["sendStream"]>[1],
83-
requestInit?: RequestInit,
83+
requestInit: RequestInit = {},
8484
update?: boolean
8585
): Promise<SequenceClient> {
8686
const response = await this.client.sendStream<any>("sequence", sequencePackage, requestInit, {
@@ -96,7 +96,7 @@ export class HostClient implements ClientProvider {
9696
* @param {string} sequenceId Sequence id.
9797
* @returns {Promise<STHRestAPI.GetSequenceResponse>} Promise resolving to Sequence details.
9898
*/
99-
async getSequence(sequenceId: string) {
99+
async getSequence(sequenceId: string): Promise<STHRestAPI.GetSequenceResponse> {
100100
return this.client.get<STHRestAPI.GetSequenceResponse>(`sequence/${sequenceId}`);
101101
}
102102

@@ -122,7 +122,7 @@ export class HostClient implements ClientProvider {
122122
* @param {string} instanceId Instance id.
123123
* @returns {Promise<STHRestAPI.GetInstanceResponse>} Promise resolving to Instance details.
124124
*/
125-
async getInstanceInfo(instanceId: string) {
125+
async getInstanceInfo(instanceId: string): Promise<STHRestAPI.GetInstanceResponse> {
126126
return this.client.get<STHRestAPI.GetInstanceResponse>(`instance/${instanceId}`);
127127
}
128128

@@ -131,7 +131,7 @@ export class HostClient implements ClientProvider {
131131
*
132132
* @returns {Promise<STHRestAPI.GetLoadCheckResponse>} Promise resolving to Host load check data.
133133
*/
134-
async getLoadCheck() {
134+
async getLoadCheck(): Promise<STHRestAPI.GetLoadCheckResponse> {
135135
return this.client.get<STHRestAPI.GetLoadCheckResponse>("load-check");
136136
}
137137

@@ -140,7 +140,7 @@ export class HostClient implements ClientProvider {
140140
*
141141
* @returns {Promise<STHRestAPI.GetVersionResponse>} Promise resolving to Host version.
142142
*/
143-
async getVersion() {
143+
async getVersion(): Promise<STHRestAPI.GetVersionResponse> {
144144
return this.client.get<STHRestAPI.GetVersionResponse>("version");
145145
}
146146

@@ -154,9 +154,9 @@ export class HostClient implements ClientProvider {
154154
/**
155155
* Returns Host public configuration.
156156
*
157-
* @returns {Promise<GetConfigResponse>} Promise resolving to Host configuration (public part).
157+
* @returns {Promise<STHRestAPI.GetConfigResponse>} Promise resolving to Host configuration (public part).
158158
*/
159-
async getConfig() {
159+
async getConfig(): Promise<STHRestAPI.GetConfigResponse> {
160160
return this.client.get<STHRestAPI.GetConfigResponse>("config");
161161
}
162162

packages/cli/src/lib/commands/sequence.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,11 @@ export const sequence: CommandDefinition = (program) => {
7878
.command("send")
7979
.argument("<package>", "The file or directory to upload or '-' to use the last packed. If directory, it will be packed and sent.")
8080
.option("--name <name>", "Allows to name sequence")
81+
.option("--runtime-adapter <adapter>", "STH will try to use Adapter with this name or it's default when Adapter name is not provided.")
8182
.description("Send the Sequence package to the Hub")
8283
.action(
83-
async (sequencePackage: string, { name }) => {
84-
const sequenceClient = await sequenceSendPackage(sequencePackage, { name }, false, { progress: sequenceCmd.parent?.getOptionValue("progress") });
84+
async (sequencePackage: string, { name, runtimeAdapter })=> {
85+
const sequenceClient = await sequenceSendPackage(sequencePackage, { name, runtimeAdapter }, false, { progress: sequenceCmd.parent?.getOptionValue("progress") });
8586

8687
displayObject(sequenceClient, profileManager.getProfileConfig().format);
8788
}
@@ -91,10 +92,11 @@ export const sequence: CommandDefinition = (program) => {
9192
.command("update")
9293
.argument("<query>", "Sequence id or name to be overwritten")
9394
.argument("<package>", "The file to upload")
95+
.option("--runtime-adapter <adapter>", "STH will try to use Adapter with this name or it's default when Adapter name is not provided.")
9496
.description("Update Sequence with given name")
9597
.action(
96-
async (query: string, sequencePackage: string) => {
97-
const sequenceClient = await sequenceSendPackage(sequencePackage, { name: query }, true);
98+
async (query: string, sequencePackage: string, { runtimeAdapter }) => {
99+
const sequenceClient = await sequenceSendPackage(sequencePackage, { name: query, runtimeAdapter }, true);
98100

99101
displayObject(sequenceClient, profileManager.getProfileConfig().format);
100102
}
@@ -233,3 +235,4 @@ export const sequence: CommandDefinition = (program) => {
233235
displayMessage("Sequences removed successfully.");
234236
});
235237
};
238+

packages/cli/src/lib/helpers/sequence.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const { F_OK, R_OK } = constants;
2020

2121
type SequenceUploadOptions = {
2222
name?: string;
23+
runtimeAdapter?: string;
2324
}
2425

2526
/**
@@ -134,6 +135,10 @@ export const sequenceSendPackage = async (
134135
headers["x-name"] = options.name;
135136
}
136137

138+
if (options.runtimeAdapter) {
139+
headers["x-runtime-adapter"] = options.runtimeAdapter;
140+
}
141+
137142
seq = await getHostClient().sendSequence(
138143
sequenceStream,
139144
{ headers }

packages/host/src/lib/adapter-manager.ts

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export type InitializedRuntimeAdapter = IRuntimeAdapter & {
66
status: "ready" | { error?: string };
77
};
88

9-
export type AdaptersStore = { [key: string]: InitializedRuntimeAdapter };
9+
export type AdaptersStore = Record<string, InitializedRuntimeAdapter>;
1010

1111
export class AdapterManager {
1212
adapters: AdaptersStore = {};
@@ -38,34 +38,33 @@ export class AdapterManager {
3838
moduleNames.map(
3939
async (moduleName) => {
4040
const typedModuleName = moduleName as unknown as keyof STHConfiguration["adapters"];
41-
const config = this.sthConfig.adapters[typedModuleName]!;
42-
4341
const adapter = Object.assign(
44-
new (await import(moduleName)).default(config),
42+
new (await import(moduleName)).default(
43+
this.sthConfig.adapters[typedModuleName]!
44+
),
4545
{ moduleName }
4646
) as InitializedRuntimeAdapter;
4747

4848
if (!AdapterManager.validateAdapter(adapter)) {
4949
throw new Error(`Invalid Runtime Adapter provided ${adapter.moduleName}`);
5050
}
5151

52-
adapter.config = config;
5352
adapter.status = await this.initAdapter(adapter);
5453

5554
if (adapter.status !== "ready") {
5655
this.logger.warn(`Failed to initialize "${adapter.moduleName}" Adapter: ${adapter.status.error}`);
5756
}
5857

59-
if (this.adapters[adapter.moduleName]) {
60-
throw new Error("Invalid Runtime Adapters configuration, duplicated Runtime Adapter name");
61-
}
62-
6358
return adapter;
6459
}
6560
)
66-
).then((adapterList) =>
67-
adapterList.reduce((a: AdaptersStore, c) => { a[c.moduleName] = c; return a; }, {})
68-
);
61+
).then((adapterList) => adapterList.reduce((a: AdaptersStore, c) => {
62+
if (a[c.moduleName]) throw new Error("Invalid Runtime Adapters configuration, duplicated Runtime Adapter name");
63+
64+
a[c.moduleName] = c;
65+
66+
return a;
67+
}, {}));
6968

7069
const adaptersCount = Object.keys(this.adapters).length;
7170

@@ -83,11 +82,14 @@ export class AdapterManager {
8382
/**
8483
* Validates adapter.
8584
*
86-
* @param {IRuntimeAdapter} adapter Checks if adapter provides required fields.
87-
* @returns {boolean} True if required fields are available.
85+
* @param {IRuntimeAdapter} adapter Checks if adapter provides required functions.
86+
* @returns {boolean} True if required functions are available.
8887
*/
8988
static validateAdapter(adapter: IRuntimeAdapter): boolean {
90-
return !!(adapter.name?.trim() && ["sequenceAdapter", "instanceAdapter", "init"].every((className: string) => className in adapter));
89+
return !!(adapter.alias?.trim() &&
90+
["sequenceAdapter", "instanceAdapter", "init"].every(
91+
(field: string) => typeof adapter[field as keyof IRuntimeAdapter] === "function")
92+
);
9193
}
9294

9395
/**
@@ -112,12 +114,18 @@ export class AdapterManager {
112114
return Object.values(this.adapters).find(a => a.moduleName === moduleName);
113115
}
114116

115-
getDefaultAdapter(prefferedAdapter: string) {
117+
/**
118+
* Returns first Adapter with "ready" status if prefferedAdapter is "detect".
119+
* Returns Adapter with name provided by prefferedAdapter.
120+
* @param prefferedAdapter
121+
* @returns
122+
*/
123+
getDefaultAdapter(prefferedAdapter: string): InitializedRuntimeAdapter | undefined {
116124
if (prefferedAdapter === "detect") {
117125
return Object.values(this.adapters).filter(adapter => adapter.status === "ready")[0];
118126
}
119127

120-
return Object.values(this.adapters).find(a => a.name === prefferedAdapter);
128+
return Object.values(this.adapters).find(a => a.alias === prefferedAdapter);
121129
}
122130

123131
/**

packages/host/src/lib/host.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ export class Host implements IComponent {
344344
throw new Error("Can't set default adapter");
345345
}
346346

347-
this.logger.info(`Default adapter for running Sequences: "${this.adapterName}" (${defaultAdapter?.name})`);
347+
this.logger.info(`Default adapter for running Sequences: "${this.adapterName}" (${defaultAdapter?.alias})`);
348348
} else {
349349
this.logger.warn("No Runtime Adapters.");
350350
}
@@ -767,16 +767,17 @@ export class Host implements IComponent {
767767
stream.params ||= {};
768768

769769
const sequenceName = stream.params.id_name || stream.headers["x-name"];
770+
const requestedAdapter = stream.headers["x-runtime-adapter"] as string;
770771

771-
this.logger.info("New Sequence incoming", { name: sequenceName });
772+
this.logger.info("New Sequence incoming", { name: sequenceName, requestedAdapter });
772773

773774
try {
774-
const adapter = this.adapterManager.getDefaultAdapter(this.adapterName);
775+
const adapter = this.adapterManager.getDefaultAdapter(requestedAdapter || this.adapterName);
775776

776777
if (!adapter) {
777778
return {
778-
opStatus: ReasonPhrases.FAILED_DEPENDENCY,
779-
error: "Can't initialize Adapter"
779+
opStatus: ReasonPhrases.NOT_ACCEPTABLE,
780+
error: "Can't initialize Runtime Adapter"
780781
};
781782
}
782783

@@ -808,7 +809,7 @@ export class Host implements IComponent {
808809

809810
const config = await sequenceAdapter.identify(stream, id);
810811

811-
config.packageSize = stream.socket?.bytesRead;
812+
config.packageSize = stream.socket.bytesRead - stream.rawHeaders.reduce((p, c) => p += c.length, 0);
812813

813814
this.sequenceStore.set({ id, config, instances: new Set(), name: sequenceName });
814815

@@ -1004,7 +1005,7 @@ export class Host implements IComponent {
10041005
* @param {STHRestAPI.StartSequencePayload} payload App start configuration.
10051006
*/
10061007
async startCSIController(sequence: SequenceInfo, payload: STHRestAPI.StartSequencePayload): Promise<CSIController> {
1007-
const adapter = this.adapterManager.getDefaultAdapter(this.adapterName);
1008+
const adapter = this.adapterManager.getDefaultAdapter(sequence.config.type || this.adapterName);
10081009

10091010
if (!adapter) {
10101011
throw new Error("Failed to use adapter");

packages/types/src/runner-config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,6 @@ export type KubernetesSequenceConfig = CommonSequenceConfig & {
4545
type: "kubernetes"
4646
}
4747

48-
export type SequenceConfig = DockerSequenceConfig | ProcessSequenceConfig | KubernetesSequenceConfig
48+
export type SequenceConfig = DockerSequenceConfig | ProcessSequenceConfig | KubernetesSequenceConfig;
4949

5050
export type InstanceConfig = SequenceConfig & { instanceAdapterExitDelay: number, limits: InstanceLimits }

packages/types/src/runtime-adapter.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import { IInstanceAdapter } from "./instance-adapter";
22
import { ISequenceAdapter } from "./sequence-adapter";
33

44
export interface IRuntimeAdapter {
5-
name: string;
5+
alias: string;
66

7+
/**
8+
* Initializes Runtime Adapter.
9+
*/
710
init(): Promise<{ error?: string }>;
811

9-
config: { [key: string]: any };
10-
1112
instanceAdapter: IInstanceAdapter;
1213
sequenceAdapter: ISequenceAdapter;
1314
}

0 commit comments

Comments
 (0)