Skip to content

Commit

Permalink
Env follow up (#231)
Browse files Browse the repository at this point in the history
* Create the env file only if not empty

* Update

* Check some fs operation to async
  • Loading branch information
louislam authored Dec 4, 2023
1 parent 0df3fee commit 793a9de
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 15 deletions.
2 changes: 2 additions & 0 deletions backend/dockge-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import User from "./models/user";
import childProcessAsync from "promisify-child-process";
import { Terminal } from "./terminal";

import "dotenv/config";

export class DockgeServer {
app : Express;
httpServer : http.Server;
Expand Down
6 changes: 3 additions & 3 deletions backend/socket-handlers/docker-socket-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class DockerSocketHandler extends SocketHandler {
socket.on("deployStack", async (name : unknown, composeYAML : unknown, composeENV : unknown, isAdd : unknown, callback) => {
try {
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);
server.sendStackList();
callback({
Expand Down Expand Up @@ -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
if (typeof(name) !== "string") {
throw new ValidationError("Name must be a string");
Expand All @@ -280,7 +280,7 @@ export class DockerSocketHandler extends SocketHandler {
}

const stack = new Stack(server, name, composeYAML, composeENV, false);
stack.save(isAdd);
await stack.save(isAdd);
return stack;
}

Expand Down
39 changes: 27 additions & 12 deletions backend/stack.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { DockgeServer } from "./dockge-server";
import fs from "fs";
import fs, { promises as fsAsync } from "fs";
import { log } from "./log";
import yaml from "yaml";
import { DockgeSocket, ValidationError } from "./util-server";
import { DockgeSocket, fileExists, ValidationError } from "./util-server";
import path from "path";
import {
COMBINED_TERMINAL_COLS,
Expand Down Expand Up @@ -99,6 +99,15 @@ export class Stack {

// Check YAML format
yaml.parse(this.composeYAML);

let lines = this.composeENV.split("\n");

// Check if the .env is able to pass docker-compose
// Prevent "setenv: The parameter is incorrect"
// It only happens when there is one line and it doesn't contain "="
if (lines.length === 1 && !lines[0].includes("=") && lines[0].length > 0) {
throw new ValidationError("Invalid .env format");
}
}

get composeYAML() : string {
Expand Down Expand Up @@ -146,29 +155,35 @@ export class Stack {
* Save the stack to the disk
* @param isAdd
*/
save(isAdd : boolean) {
async save(isAdd : boolean) {
this.validate();

let dir = this.path;

// Check if the name is used if isAdd
if (isAdd) {
if (fs.existsSync(dir)) {
if (await fileExists(dir)) {
throw new ValidationError("Stack name already exists");
}

// Create the stack folder
fs.mkdirSync(dir);
await fsAsync.mkdir(dir);
} else {
if (!fs.existsSync(dir)) {
if (!await fileExists(dir)) {
throw new ValidationError("Stack not found");
}
}

// 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
fs.writeFileSync(path.join(dir, ".env"), this.composeENV);
// If .env is not existing and the composeENV is empty, we don't need to write it
if (await fileExists(envPath) || this.composeENV.trim() !== "") {
await fsAsync.writeFile(envPath, this.composeENV);
}
}

async deploy(socket? : DockgeSocket) : Promise<number> {
Expand All @@ -188,7 +203,7 @@ export class Stack {
}

// Remove the stack folder
fs.rmSync(this.path, {
await fsAsync.rm(this.path, {
recursive: true,
force: true
});
Expand Down Expand Up @@ -218,12 +233,12 @@ export class Stack {
stackList = new Map<string, Stack>();

// 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) {
try {
// 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()) {
continue;
}
Expand Down Expand Up @@ -314,7 +329,7 @@ export class Stack {
let dir = path.join(server.stacksDir, stackName);

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
let stackList = await this.getStackList(server, true);
let stack = stackList.get(stackName);
Expand Down
7 changes: 7 additions & 0 deletions backend/util-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { log } from "./log";
import { ERROR_TYPE_VALIDATION } from "./util-common";
import { R } from "redbean-node";
import { verifyPassword } from "./password-hash";
import fs from "fs";

export interface JWTDecoded {
username : string;
Expand Down Expand Up @@ -82,3 +83,9 @@ export async function doubleCheckPassword(socket : DockgeSocket, currentPassword

return user;
}

export function fileExists(file : string) {
return fs.promises.access(file, fs.constants.F_OK)
.then(() => true)
.catch(() => false);
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"composerize": "~1.4.1",
"croner": "~7.0.5",
"dayjs": "~1.11.10",
"dotenv": "~16.3.1",
"express": "~4.18.2",
"express-static-gzip": "~2.1.7",
"http-graceful-shutdown": "~3.1.13",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 793a9de

Please sign in to comment.