Check some fs operation to async

This commit is contained in:
Louis Lam 2023-12-04 16:24:35 +08:00
parent 3537b842ec
commit e9f1bde8cc
3 changed files with 27 additions and 17 deletions

View File

@ -12,7 +12,7 @@ export class DockerSocketHandler extends SocketHandler {
socket.on("deployStack", async (name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown, callback) => { socket.on("deployStack", async (name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown, callback) => {
try { try {
checkLogin(socket); checkLogin(socket);
const stack = this.saveStack(socket, server, name, composeYAML, composeENV, isAdd); const stack = await this.saveStack(socket, server, name, composeYAML, composeENV, isAdd);
await stack.deploy(socket); await stack.deploy(socket);
server.sendStackList(); server.sendStackList();
callback({ callback({
@ -264,7 +264,7 @@ export class DockerSocketHandler extends SocketHandler {
}); });
} }
saveStack(socket : DockgeSocket, server : DockgeServer, name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown) : Stack { async saveStack(socket : DockgeSocket, server : DockgeServer, name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown) : Promise<Stack> {
// Check types // Check types
if (typeof(name) !== "string") { if (typeof(name) !== "string") {
throw new ValidationError("Name must be a string"); throw new ValidationError("Name must be a string");
@ -280,7 +280,7 @@ export class DockerSocketHandler extends SocketHandler {
} }
const stack = new Stack(server, name, composeYAML, composeENV, false); const stack = new Stack(server, name, composeYAML, composeENV, false);
stack.save(isAdd); await stack.save(isAdd);
return stack; return stack;
} }

View File

@ -1,8 +1,8 @@
import { DockgeServer } from "./dockge-server"; import { DockgeServer } from "./dockge-server";
import fs from "fs"; import fs, { promises as fsAsync } from "fs";
import { log } from "./log"; import { log } from "./log";
import yaml from "yaml"; import yaml from "yaml";
import { DockgeSocket, ValidationError } from "./util-server"; import { DockgeSocket, fileExists, ValidationError } from "./util-server";
import path from "path"; import path from "path";
import { import {
COMBINED_TERMINAL_COLS, COMBINED_TERMINAL_COLS,
@ -105,7 +105,7 @@ export class Stack {
// Check if the .env is able to pass docker-compose // Check if the .env is able to pass docker-compose
// Prevent "setenv: The parameter is incorrect" // Prevent "setenv: The parameter is incorrect"
// It only happens when there is one line and it doesn't contain "=" // It only happens when there is one line and it doesn't contain "="
if (lines.length === 1 && !lines[0].includes("=")) { if (lines.length === 1 && !lines[0].includes("=") && lines[0].length > 0) {
throw new ValidationError("Invalid .env format"); throw new ValidationError("Invalid .env format");
} }
} }
@ -155,31 +155,34 @@ export class Stack {
* Save the stack to the disk * Save the stack to the disk
* @param isAdd * @param isAdd
*/ */
save(isAdd : boolean) { async save(isAdd : boolean) {
this.validate(); this.validate();
let dir = this.path; let dir = this.path;
// Check if the name is used if isAdd // Check if the name is used if isAdd
if (isAdd) { if (isAdd) {
if (fs.existsSync(dir)) { if (await fileExists(dir)) {
throw new ValidationError("Stack name already exists"); throw new ValidationError("Stack name already exists");
} }
// Create the stack folder // Create the stack folder
fs.mkdirSync(dir); await fsAsync.mkdir(dir);
} else { } else {
if (!fs.existsSync(dir)) { if (!await fileExists(dir)) {
throw new ValidationError("Stack not found"); throw new ValidationError("Stack not found");
} }
} }
// Write or overwrite the compose.yaml // Write or overwrite the compose.yaml
fs.writeFileSync(path.join(dir, this._composeFileName), this.composeYAML); await fsAsync.writeFile(path.join(dir, this._composeFileName), this.composeYAML);
const envPath = path.join(dir, ".env");
// Write or overwrite the .env // Write or overwrite the .env
if (this.composeENV.trim() !== "") { // If .env is not existing and the composeENV is empty, we don't need to write it
fs.writeFileSync(path.join(dir, ".env"), this.composeENV); if (await fileExists(envPath) || this.composeENV.trim() !== "") {
await fsAsync.writeFile(envPath, this.composeENV);
} }
} }
@ -200,7 +203,7 @@ export class Stack {
} }
// Remove the stack folder // Remove the stack folder
fs.rmSync(this.path, { await fsAsync.rm(this.path, {
recursive: true, recursive: true,
force: true force: true
}); });
@ -230,12 +233,12 @@ export class Stack {
stackList = new Map<string, Stack>(); stackList = new Map<string, Stack>();
// Scan the stacks directory, and get the stack list // Scan the stacks directory, and get the stack list
let filenameList = fs.readdirSync(stacksDir); let filenameList = await fsAsync.readdir(stacksDir);
for (let filename of filenameList) { for (let filename of filenameList) {
try { try {
// Check if it is a directory // Check if it is a directory
let stat = fs.statSync(path.join(stacksDir, filename)); let stat = await fsAsync.stat(path.join(stacksDir, filename));
if (!stat.isDirectory()) { if (!stat.isDirectory()) {
continue; continue;
} }
@ -326,7 +329,7 @@ export class Stack {
let dir = path.join(server.stacksDir, stackName); let dir = path.join(server.stacksDir, stackName);
if (!skipFSOperations) { if (!skipFSOperations) {
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) { if (!await fileExists(dir) || !(await fsAsync.stat(dir)).isDirectory()) {
// Maybe it is a stack managed by docker compose directly // Maybe it is a stack managed by docker compose directly
let stackList = await this.getStackList(server, true); let stackList = await this.getStackList(server, true);
let stack = stackList.get(stackName); let stack = stackList.get(stackName);

View File

@ -5,6 +5,7 @@ import { log } from "./log";
import { ERROR_TYPE_VALIDATION } from "./util-common"; import { ERROR_TYPE_VALIDATION } from "./util-common";
import { R } from "redbean-node"; import { R } from "redbean-node";
import { verifyPassword } from "./password-hash"; import { verifyPassword } from "./password-hash";
import fs from "fs";
export interface JWTDecoded { export interface JWTDecoded {
username : string; username : string;
@ -82,3 +83,9 @@ export async function doubleCheckPassword(socket : DockgeSocket, currentPassword
return user; return user;
} }
export function fileExists(file : string) {
return fs.promises.access(file, fs.constants.F_OK)
.then(() => true)
.catch(() => false);
}