This repository has been archived by the owner on Jul 29, 2022. It is now read-only.
forked from ruimarinho/gsts
-
Notifications
You must be signed in to change notification settings - Fork 1
/
daemonizer.js
122 lines (93 loc) · 3.13 KB
/
daemonizer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/**
* Module dependencies.
*/
const childProcess = require('child_process');
const fs = require('fs').promises;
const homedir = require('os').homedir();
const path = require('path');
const plist = require('plist');
// Project namespace to be used for plist generation.
const PROJECT_NAMESPACE = 'io.github.ruimarinho.gsts';
/**
* Create daemon to periodically refresh credentials.
*/
class Daemonizer {
constructor(logger, args) {
this.args = args;
this.logger = logger;
}
/**
* Generate a launch agent plist based on dynamic values.
*/
generateLaunchAgentPlist() {
const programArguments = ['/usr/local/bin/gsts']
for (let [key, value] of Object.entries(this.args)) {
if (key.includes('daemon') || value === undefined) {
continue;
}
programArguments.push(`--${key}${typeof value === 'boolean' ? '' : `=${value}`}`);
}
const payload = {
Label: PROJECT_NAMESPACE,
EnvironmentVariables: {
PATH: '/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin'
},
RunAtLoad: true,
StartInterval: 600,
StandardErrorPath: this.args['daemon-out-log-path'],
StandardOutPath: this.args['daemon-error-log-path'],
ProgramArguments: programArguments
};
return plist.build(payload);
}
/**
* Only available for macOS: generates dynamic plist and attempts to install and load a launch agent
* from the user's home directory.
*/
async install(platform) {
if (platform !== 'darwin') {
this.logger.error('Sorry, this feature is only available on macOS at this time');
return;
}
return await this.installMacOS();
}
async installMacOS() {
// LaunchAgents plist path.
const plistPath = path.join(homedir, 'Library', 'LaunchAgents', `${PROJECT_NAMESPACE}.plist`);
this.logger.debug('Unloading potentially existing launch agent at %s', plistPath);
await childProcess.execFile('launchctl', ['unload', plistPath], (error, stdout, stderr) => {
if (!error) {
return;
}
if (stderr) {
this.logger.error('Result from stderr while attempting to unload agent was "%s"', stderr);
}
if (stdout) {
this.logger.info('Result from stdout while attempting to unload agent was "%s"', stdout);
}
this.logger.error(error);
});
const plist = this.generateLaunchAgentPlist().toString();
this.logger.debug('Generated launch agent plist file %s', plist);
await fs.writeFile(plistPath, plist);
this.logger.debug('Successfully wrote the launch agent plist to %s', plistPath);
await childProcess.execFile('launchctl', ['load', plistPath], (error, stdout, stderr) => {
if (error) {
this.logger.error(error);
return;
}
if (stderr) {
this.logger.error('Result from stderr while attempting to load agent was "%s"', stderr);
}
if (stdout) {
this.logger.info('Result from stdout while attempting to load agent was "%s"', stdout);
} else {
this.logger.info('Daemon installed successfully at %s', plistPath)
}
});
}
}
/**
* Exports.
*/
module.exports = Daemonizer;