mirror of https://github.com/coder/code-server.git
Add support for a YAML config file
This commit is contained in:
parent
95ac0ddfb7
commit
c5179c2a06
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue