Add support for a YAML config file

This commit is contained in:
Anmol Sethi 2020-05-10 01:19:32 -04:00
parent 95ac0ddfb7
commit c5179c2a06
No known key found for this signature in database
GPG Key ID: 8CEF1878FF10ADEB
4 changed files with 67 additions and 2 deletions

View File

@ -33,6 +33,7 @@
"@types/adm-zip": "^0.4.32", "@types/adm-zip": "^0.4.32",
"@types/fs-extra": "^8.0.1", "@types/fs-extra": "^8.0.1",
"@types/http-proxy": "^1.17.4", "@types/http-proxy": "^1.17.4",
"@types/js-yaml": "^3.12.3",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",
"@types/node": "^12.12.7", "@types/node": "^12.12.7",
"@types/parcel-bundler": "^1.12.1", "@types/parcel-bundler": "^1.12.1",
@ -69,13 +70,15 @@
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"http-proxy": "^1.18.0", "http-proxy": "^1.18.0",
"httpolyglot": "^0.1.2", "httpolyglot": "^0.1.2",
"js-yaml": "^3.13.1",
"limiter": "^1.1.5", "limiter": "^1.1.5",
"pem": "^1.14.2", "pem": "^1.14.2",
"safe-compare": "^1.1.4", "safe-compare": "^1.1.4",
"semver": "^7.1.3", "semver": "^7.1.3",
"tar": "^6.0.1", "tar": "^6.0.1",
"tar-fs": "^2.0.0", "tar-fs": "^2.0.0",
"ws": "^7.2.0" "ws": "^7.2.0",
"xdg-basedir": "^4.0.0"
}, },
"bin": { "bin": {
"code-server": "out/node/entry.js" "code-server": "out/node/entry.js"

View File

@ -1,8 +1,11 @@
import * as fs from "fs-extra"
import yaml from "js-yaml"
import * as path from "path" import * as path from "path"
import { field, logger, Level } from "@coder/logger" import { field, logger, Level } from "@coder/logger"
import { Args as VsArgs } from "../../lib/vscode/src/vs/server/ipc" import { Args as VsArgs } from "../../lib/vscode/src/vs/server/ipc"
import { AuthType } from "./http" import { AuthType } from "./http"
import { xdgLocalDir } from "./util" import { xdgLocalDir } from "./util"
import xdgBasedir from "xdg-basedir"
export class Optional<T> { export class Optional<T> {
public constructor(public readonly value?: T) {} public constructor(public readonly value?: T) {}
@ -19,6 +22,7 @@ export enum LogLevel {
export class OptionalString extends Optional<string> {} export class OptionalString extends Optional<string> {}
export interface Args extends VsArgs { export interface Args extends VsArgs {
readonly config?: string
readonly auth?: AuthType readonly auth?: AuthType
readonly cert?: OptionalString readonly cert?: OptionalString
readonly "cert-key"?: string readonly "cert-key"?: string
@ -95,6 +99,8 @@ const options: Options<Required<Args>> = {
"bind-addr": { type: "string", description: "Address to bind to in host:port." }, "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. // These two have been deprecated by bindAddr.
host: { type: "string", description: "" }, host: { type: "string", description: "" },
port: { type: "number", description: "" }, port: { type: "number", description: "" },
@ -275,3 +281,47 @@ export const parse = (argv: string[]): Args => {
return 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<Args> {
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
}

View File

@ -9,7 +9,7 @@ import { ProxyHttpProvider } from "./app/proxy"
import { StaticHttpProvider } from "./app/static" import { StaticHttpProvider } from "./app/static"
import { UpdateHttpProvider } from "./app/update" import { UpdateHttpProvider } from "./app/update"
import { VscodeHttpProvider } from "./app/vscode" 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 { AuthType, HttpServer, HttpServerOptions } from "./http"
import { generateCertificate, generatePassword, hash, open } from "./util" import { generateCertificate, generatePassword, hash, open } from "./util"
import { ipcMain, wrap } from "./wrapper" import { ipcMain, wrap } from "./wrapper"
@ -32,6 +32,8 @@ const version = pkg.version || "development"
const commit = pkg.commit || "development" const commit = pkg.commit || "development"
const main = async (args: Args): Promise<void> => { const main = async (args: Args): Promise<void> => {
args = await readConfigFile(args)
const auth = args.auth || AuthType.Password const auth = args.auth || AuthType.Password
const originalPassword = auth === AuthType.Password && (process.env.PASSWORD || (await generatePassword())) const originalPassword = auth === AuthType.Password && (process.env.PASSWORD || (await generatePassword()))

View File

@ -931,6 +931,11 @@
dependencies: dependencies:
"@types/node" "*" "@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": "@types/json-schema@^7.0.3":
version "7.0.4" version "7.0.4"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" 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" resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.5.tgz#abb1370d4626a5a9cd79d8de404aa18b3465d10d"
integrity sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA== 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: xml-name-validator@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"