autorestic/src/config.ts

122 lines
3.0 KiB
TypeScript
Raw Normal View History

import { readFileSync, writeFileSync, statSync, copyFileSync } from 'fs'
import { resolve } from 'path'
2019-12-22 13:25:22 +00:00
import { homedir } from 'os'
2019-06-20 21:09:47 +00:00
import yaml from 'js-yaml'
import CronParser from 'cron-parser'
2019-12-22 13:25:22 +00:00
import { flags } from './autorestic'
2019-06-20 21:09:47 +00:00
import { Backend, Config } from './types'
2019-12-04 23:23:49 +00:00
import { makeArrayIfIsNot, makeObjectKeysLowercase, rand } from './utils'
2019-06-20 21:09:47 +00:00
2019-12-03 22:37:55 +00:00
2019-12-24 15:52:27 +00:00
export enum LocationFromPrefixes {
Filesystem,
DockerVolume
}
2019-06-20 21:09:47 +00:00
export const normalizeAndCheckBackends = (config: Config) => {
2019-12-03 22:37:55 +00:00
config.backends = makeObjectKeysLowercase(config.backends)
for (const [name, { type, path, key, ...rest }] of Object.entries(
config.backends,
)) {
if (!type || !path)
throw new Error(
`The backend "${name}" is missing some required attributes`,
)
const tmp: any = {
type,
path,
key: key || rand(128),
}
for (const [key, value] of Object.entries(rest))
tmp[key.toUpperCase()] = value
config.backends[name] = tmp as Backend
}
2019-06-20 21:09:47 +00:00
}
export const normalizeAndCheckLocations = (config: Config) => {
2019-12-03 22:37:55 +00:00
config.locations = makeObjectKeysLowercase(config.locations)
const backends = Object.keys(config.backends)
const checkDestination = (backend: string, location: string) => {
2019-12-03 22:37:55 +00:00
if (!backends.includes(backend))
throw new Error(`Cannot find the backend "${backend}" for "${location}"`)
2019-12-03 22:37:55 +00:00
}
for (const [name, { from, to, cron, ...rest }] of Object.entries(config.locations)) {
if (!from)
2020-05-17 13:37:38 +00:00
throw new Error(`The location "${name.blue}" is missing the "${'from'.underline.red}" source folder. See https://git.io/Jf0xw`)
if (!to || (Array.isArray(to) && !to.length))
2020-05-17 13:37:38 +00:00
throw new Error(`The location "${name.blue}" has no backend "${'to'.underline.red}" to save the backups. See https://git.io/Jf0xw`)
2019-12-03 22:37:55 +00:00
2019-12-04 23:23:49 +00:00
for (const t of makeArrayIfIsNot(to))
checkDestination(t, name)
if (cron) {
try {
CronParser.parseExpression(cron)
} catch {
2020-05-17 13:37:38 +00:00
throw new Error(`The location "${name.blue}" has an invalid ${'cron'.underline.red} entry. See https://git.io/Jf0xP`)
}
}
2019-12-03 22:37:55 +00:00
}
}
const findConfigFile = (): string => {
2019-12-03 22:37:55 +00:00
const config = '.autorestic.yml'
const paths = [
resolve(flags.config || ''),
resolve('./' + config),
homedir() + '/' + config,
]
for (const path of paths) {
try {
const file = statSync(path)
if (file.isFile()) return path
} catch (e) {
}
}
throw new Error('Config file not found')
2019-06-20 21:09:47 +00:00
}
export let CONFIG_FILE: string = ''
2019-06-20 21:09:47 +00:00
export const init = (): Config => {
2019-12-03 22:37:55 +00:00
const file = findConfigFile()
CONFIG_FILE = file
2019-12-03 22:37:55 +00:00
const raw: Config = makeObjectKeysLowercase(
yaml.safeLoad(readFileSync(CONFIG_FILE).toString()),
)
2019-06-20 21:09:47 +00:00
const current = JSON.stringify(raw)
2019-12-03 22:37:55 +00:00
normalizeAndCheckBackends(raw)
normalizeAndCheckLocations(raw)
2019-06-20 21:09:47 +00:00
const changed = JSON.stringify(raw) !== current
if (changed) {
const OLD_CONFIG_FILE = CONFIG_FILE + '.old'
copyFileSync(CONFIG_FILE, OLD_CONFIG_FILE)
writeFileSync(CONFIG_FILE, yaml.safeDump(raw))
console.log(
'\n' +
'⚠️ MOVED OLD CONFIG FILE TO: ⚠️'.red.underline.bold +
'\n' +
OLD_CONFIG_FILE +
'\n' +
2020-05-17 13:37:38 +00:00
'What? Why? '.grey + 'https://git.io/Jf0xK'.underline.grey +
'\n'
)
}
2019-06-20 21:09:47 +00:00
2019-12-03 22:37:55 +00:00
return raw
2019-06-20 21:09:47 +00:00
}