From c5179c2a06b6e7f47ac1244b2f75db0a0a6f4e0e Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Sun, 10 May 2020 01:19:32 -0400 Subject: [PATCH] Add support for a YAML config file --- package.json | 5 ++++- src/node/cli.ts | 50 +++++++++++++++++++++++++++++++++++++++++++++++ src/node/entry.ts | 4 +++- yarn.lock | 10 ++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d27eff82..f1813e89 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@types/adm-zip": "^0.4.32", "@types/fs-extra": "^8.0.1", "@types/http-proxy": "^1.17.4", + "@types/js-yaml": "^3.12.3", "@types/mocha": "^5.2.7", "@types/node": "^12.12.7", "@types/parcel-bundler": "^1.12.1", @@ -69,13 +70,15 @@ "fs-extra": "^8.1.0", "http-proxy": "^1.18.0", "httpolyglot": "^0.1.2", + "js-yaml": "^3.13.1", "limiter": "^1.1.5", "pem": "^1.14.2", "safe-compare": "^1.1.4", "semver": "^7.1.3", "tar": "^6.0.1", "tar-fs": "^2.0.0", - "ws": "^7.2.0" + "ws": "^7.2.0", + "xdg-basedir": "^4.0.0" }, "bin": { "code-server": "out/node/entry.js" diff --git a/src/node/cli.ts b/src/node/cli.ts index 5b207551..f135d32a 100644 --- a/src/node/cli.ts +++ b/src/node/cli.ts @@ -1,8 +1,11 @@ +import * as fs from "fs-extra" +import yaml from "js-yaml" import * as path from "path" import { field, logger, Level } from "@coder/logger" import { Args as VsArgs } from "../../lib/vscode/src/vs/server/ipc" import { AuthType } from "./http" import { xdgLocalDir } from "./util" +import xdgBasedir from "xdg-basedir" export class Optional { public constructor(public readonly value?: T) {} @@ -19,6 +22,7 @@ export enum LogLevel { export class OptionalString extends Optional {} export interface Args extends VsArgs { + readonly config?: string readonly auth?: AuthType readonly cert?: OptionalString readonly "cert-key"?: string @@ -95,6 +99,8 @@ const options: Options> = { "bind-addr": { type: "string", description: "Address to bind to in host:port." }, + config: { type: "string", description: "Path to yaml config file." }, + // These two have been deprecated by bindAddr. host: { type: "string", description: "" }, port: { type: "number", description: "" }, @@ -275,3 +281,47 @@ export const parse = (argv: string[]): Args => { return args } + +// readConfigFile reads the config file specified in the config flag +// and loads it's configuration. +// +// Flags set on the CLI take priority. +// +// The config file can also be passed via $CODE_SERVER_CONFIG and defaults +// to ~/.config/code-server/config.yaml. +export async function readConfigFile(args: Args): Promise { + const configPath = getConfigPath(args) + if (configPath === undefined) { + return args + } + + if (!(await fs.pathExists(configPath))) { + await fs.outputFile(configPath, `default: hello`) + } + + const configFile = await fs.readFile(configPath) + const config = yaml.safeLoad(configFile.toString(), { + filename: args.config, + }) + + // We convert the config file into a set of flags. + // This is a temporary measure until we add a proper CLI library. + const configFileArgv = Object.entries(config).map(([optName, opt]) => `--${optName}=${opt}`) + const configFileArgs = parse(configFileArgv) + + // This prioritizes the flags set in args over the ones in the config file. + return Object.assign(configFileArgs, args) +} + +function getConfigPath(args: Args): string | undefined { + if (args.config !== undefined) { + return args.config + } + if (process.env.CODE_SERVER_CONFIG !== undefined) { + return process.env.CODE_SERVER_CONFIG + } + if (xdgBasedir.config !== undefined) { + return `${xdgBasedir.config}/code-server/config.yaml` + } + return undefined +} diff --git a/src/node/entry.ts b/src/node/entry.ts index c4b0cbc8..493d2689 100644 --- a/src/node/entry.ts +++ b/src/node/entry.ts @@ -9,7 +9,7 @@ import { ProxyHttpProvider } from "./app/proxy" import { StaticHttpProvider } from "./app/static" import { UpdateHttpProvider } from "./app/update" import { VscodeHttpProvider } from "./app/vscode" -import { Args, optionDescriptions, parse } from "./cli" +import { Args, optionDescriptions, parse, readConfigFile } from "./cli" import { AuthType, HttpServer, HttpServerOptions } from "./http" import { generateCertificate, generatePassword, hash, open } from "./util" import { ipcMain, wrap } from "./wrapper" @@ -32,6 +32,8 @@ const version = pkg.version || "development" const commit = pkg.commit || "development" const main = async (args: Args): Promise => { + args = await readConfigFile(args) + const auth = args.auth || AuthType.Password const originalPassword = auth === AuthType.Password && (process.env.PASSWORD || (await generatePassword())) diff --git a/yarn.lock b/yarn.lock index 473107bb..470f299f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -931,6 +931,11 @@ dependencies: "@types/node" "*" +"@types/js-yaml@^3.12.3": + version "3.12.3" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.3.tgz#abf383c5b639d0aa8b8c4a420d6a85f703357d6c" + integrity sha512-otRe77JNNWzoVGLKw8TCspKswRoQToys4tuL6XYVBFxjgeM0RUrx7m3jkaTdxILxeGry3zM8mGYkGXMeQ02guA== + "@types/json-schema@^7.0.3": version "7.0.4" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" @@ -7373,6 +7378,11 @@ ws@^7.2.0: resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.5.tgz#abb1370d4626a5a9cd79d8de404aa18b3465d10d" integrity sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA== +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"