Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(code)!: make the code more general #57

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions src/darwin.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import cp from "node:child_process";
import fs from "node:fs/promises";
import { Remitter } from "remitter";
import { OVMStatusName } from "./type";
import type { OVMDarwinOptions, OVMEventData, OVMInfo, OVMState } from "./type";
import { OVMDarwinStatusName } from "./type";
import type { OVMDarwinOptions, OVMDarwinEventData, OVMDarwinInfo, OVMDarwinState } from "./type";
import { Restful } from "./event_restful";
import { Request } from "./request";
import path from "node:path";
import { tmpdir } from "node:os";

export class DarwinOVM {
private readonly remitter = new Remitter<OVMEventData>();
private readonly remitter = new Remitter<OVMDarwinEventData>();
private eventSocketPath: string;
private request: Request;

Expand All @@ -23,13 +25,24 @@ export class DarwinOVM {
return ovm;
}

public on(event: keyof OVMEventData, listener: (datum: OVMEventData["status"]) => void): void {
public on(event: keyof OVMDarwinEventData, listener: (datum: OVMDarwinEventData["status"]) => void): void {
this.remitter.on(event, listener);
}

private async initEventRestful(): Promise<void> {
const restful = new Restful(this.remitter);
this.eventSocketPath = await restful.start();
const restful = new Restful((name, message) => {
if (name in OVMDarwinStatusName) {
this.remitter.emit("status", {
name: name as OVMDarwinStatusName,
message,
});
}
});

const dir = await fs.mkdtemp(path.join(tmpdir(), "ovm-"));
const socketPath = path.join(dir, "event-restful.sock");
restful.start(socketPath);
this.eventSocketPath = socketPath;
}

private initRequest(): void {
Expand Down Expand Up @@ -90,17 +103,17 @@ export class DarwinOVM {
launchTimeout
.catch(() => {
this.remitter.emit("status", {
name: OVMStatusName.Error,
name: OVMDarwinStatusName.Error,
message: "OVM start timeout",
});
});
}

public async info(): Promise<OVMInfo> {
public async info(): Promise<OVMDarwinInfo> {
return this.request.info();
}

public async state(): Promise<OVMState> {
public async state(): Promise<OVMDarwinState> {
return this.request.state();
}

Expand Down
25 changes: 4 additions & 21 deletions src/event_restful.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import url from "node:url";
import http from "node:http";
import type { OVMEventData } from "./type";
import { OVMStatusName } from "./type";
import type { Remitter } from "remitter";
import fs from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";


export class Restful {
private readonly server: http.Server;

public constructor(
private readonly emitter: Remitter<OVMEventData>,
callback: (name: string, message: string) => void,
) {
this.server = http.createServer((request, response) => {
if (!request.url) {
Expand All @@ -23,28 +18,16 @@ export class Restful {
response.statusCode = 200;
response.end("ok");

const event = parsedUrl.query.event as OVMStatusName;
const message = parsedUrl.query.message as string;

if (event in OVMStatusName) {
this.emitter.emit("status", {
name: event,
message: message,
});
}
callback(parsedUrl.query.event as string, parsedUrl.query.message as string);
} else {
response.statusCode = 404;
response.end("Not Found");
}
});
}

public async start(): Promise<string> {
const dir = await fs.mkdtemp(path.join(tmpdir(), "ovm-"));
const socketPath = path.join(dir, "event-restful.sock");
public start(socketPath: string): void {
this.server.listen(socketPath);

return socketPath;
}

public stop(): void {
Expand Down
10 changes: 5 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ export const createDarwinOVM = (options: OVMDarwinOptions): Promise<DarwinOVM> =
};

export {
OVMStatusName,
OVMVzState,
OVMDarwinStatusName,
OVMDarwinVzState,
} from "./type";

export type {
OVMEventData,
OVMDarwinEventData,
OVMDarwinOptions,
OVMInfo,
OVMState,
OVMDarwinInfo,
OVMDarwinState,
} from "./type";
export type { DarwinOVM };
71 changes: 39 additions & 32 deletions src/request.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
import path from "node:path";
import http from "node:http";
import type { OVMInfo, OVMState } from "./type";
import type { OVMDarwinInfo, OVMDarwinState } from "./type";
import type { RequestOptions } from "http";

const generateRequest = async (option: RequestOptions): Promise<string> => {
return new Promise<string>((resolve, reject) => {
http.request({
timeout: 200,
...option,
}, (response) => {
response.setEncoding("utf8");

let body = "";
response.on("data", (chunk) => {
body += chunk;
});

response.on("end", () => {
const { statusCode } = response;
if (!statusCode || statusCode >= 400) {
return reject(new Error(`Request Failed. Status Code: ${statusCode}, Response: ${body}`));
}

return resolve(body);
});
})
.once("error", (error) => {
reject(error);
})
.end();
});
};

export class Request {
private readonly socketPath: string;
Expand All @@ -10,33 +40,10 @@ export class Request {
}

private async request(p: string, method: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
http.request({
socketPath: this.socketPath,
path: `http://ovm/${p}`,
method: method,
timeout: 200,
}, (response) => {
response.setEncoding("utf8");

let body = "";
response.on("data", (chunk) => {
body += chunk;
});

response.on("end", () => {
const { statusCode } = response;
if (!statusCode || statusCode >= 400) {
return reject(new Error(`Request Failed. Status Code: ${statusCode}, Response: ${body}`));
} else {
resolve(body);
}
});
})
.once("error", (error) => {
reject(error);
})
.end();
return await generateRequest({
socketPath: this.socketPath,
path: `http://ovm/${p}`,
method: method,
});
}

Expand All @@ -58,12 +65,12 @@ export class Request {
}
}

public async state(): Promise<OVMState> {
return JSON.parse(await this.send("state")) as OVMState;
public async state(): Promise<OVMDarwinState> {
return JSON.parse(await this.send("state")) as OVMDarwinState;
}

public async info(): Promise<OVMInfo> {
return JSON.parse(await this.send("info")) as OVMInfo;
public async info(): Promise<OVMDarwinInfo> {
return JSON.parse(await this.send("info")) as OVMDarwinInfo;
}

public async pause(): Promise<void> {
Expand Down
14 changes: 7 additions & 7 deletions src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface OVMDarwinOptions {
extendShareDir?: string,
}

export enum OVMStatusName {
export enum OVMDarwinStatusName {
Initializing = "Initializing",
GVProxyReady = "GVProxyReady",
IgnitionProgress = "IgnitionProgress",
Expand All @@ -27,21 +27,21 @@ export enum OVMStatusName {
Error = "Error",
}

export interface OVMEventData {
export interface OVMDarwinEventData {
status: {
name: OVMStatusName,
name: OVMDarwinStatusName,
message: string,
}
}

export interface OVMInfo {
export interface OVMDarwinInfo {
podmanSocketPath: string;
}

/**
* @see https://github.com/Code-Hex/vz/blob/bd29a7ea3d39465c4224bfb01e990e8c220a8449/virtualization.go#L23
*/
export enum OVMVzState {
export enum OVMDarwinVzState {
VirtualMachineStateStopped = "VirtualMachineStateStopped",
VirtualMachineStateRunning = "VirtualMachineStateRunning",
VirtualMachineStatePaused = "VirtualMachineStatePaused",
Expand All @@ -54,8 +54,8 @@ export enum OVMVzState {
VirtualMachineStateRestoring = "VirtualMachineStateRestoring",
}

export interface OVMState {
state: OVMVzState;
export interface OVMDarwinState {
state: OVMDarwinVzState;
canStart: boolean;
canPause: boolean;
canResume: boolean;
Expand Down
Loading