-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcli.js
executable file
·231 lines (200 loc) · 7.62 KB
/
cli.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#!/usr/bin/env node
const commander = require('commander')
const { spawn, exec } = require('child_process');
const program = new commander.Command();
const SERVICES = ['rsyslog', 'kafka', 'kafka2', 'kafka3', 'zookeeper', 'influxdb', 'chronograf', 'consumer']
const SERVICE_LISTING = `
service description
------- -----------
rsyslog Rsyslog Central Server
zookeeper Apache Zookeeper
kafka Kafka Broker 1
kafka2 Kafka Broker 2
kafka3 Kafka Broker 3
influxdb InfluxDB
chronograf Chronograf
consumer Kafka Consumer for AWS S3 & InfluxDB`
const NAMES = {
'rsyslog': 'Rsyslog Central Server',
'zookeeper': 'Zookeeper',
'kafka': 'Kafka Broker 1',
'kafka2': 'Kafka Broker 2',
'kafka3': 'Kafka Broker 3',
'influxdb': 'influxdb',
'chronograf': 'chronograf',
'consumer': 'Consumers API Server',
};
const configQuestions = [{
type: 'input',
name: 'AWS_ACCESS_KEY_ID',
message: 'Enter your Amazon Web Services (AWS) access key ID...'
},
{
type: 'input',
name: 'AWS_SECRET_ACCESS_KEY',
message: 'Enter your Amazon Web Services (AWS) secret access key...'
},
{
type: 'input',
name: 'AWS_S3_BUCKET_NAME',
message: 'Enter your Amazon Web Services (AWS) S3 bucket name...'
},
{
type: 'input',
name: 'QUEUE_MAX_SIZE',
message: 'Enter the maximum number of logs to be queued before being uploaded to AWS S3'
}
];
const log = (message) => {
console.log(`📦 ${message}`)
}
const deployCrato = () => {
log('Crato is booting up the system...')
log('This may take several minutes to install all dependencies.')
exec('docker-compose up -d zookeeper', (err, stdout, stderr) => {
setTimeout(() => {
exec('docker-compose up -d').on('close', (err, stdout, stderr) => {
log('Crato is now fully running.')
});
}, 7000);
});
}
const displayDockerLogs = (service) => {
let cmd = `docker-compose logs -t ${cmdFlags} ${service}`
service = service.toLowerCase()
if (SERVICES.includes(service)) {
log(`Displaying logs for ${NAMES[service]}...`)
exec(cmd, (err, stdout, stderr) => {
console.log(stdout)
});
} else {
log(`${service} is not a valid service.`)
log(`{SERVICE_LISTING}`)
}
}
const liveTail = () => {
const tailingDockerCmd = () => {
spawn('docker-compose', ['exec', 'rsyslog', 'tail', '-f', '/var/log/syslog'], { stdio: 'inherit' });
}
log('Crato will shortly be live tailing logs streaming into the system...')
log(`Enter Ctrl-C to exit live-tail mode`)
setTimeout(tailingDockerCmd, 2000)
}
const openShell = (service) => {
if (!NAMES[service]) {
log(`${service} is not a valid service.`)
console.log(SERVICE_LISTING)
return;
}
log(`Opening a shell for the ${NAMES[service]}`)
const shFunc = () => spawn('docker-compose', ['exec', service, 'sh'], { stdio: 'inherit' });
setTimeout(shFunc, 2000)
}
const stopCrato = () => {
log('Crato is now shutting down...')
exec('docker-compose stop').on('close', (err, stdout, stderr) => {
log('Crato has now fully shutdown. Goodbye.')
})
}
const displaySystemStatus = () => (exec('docker ps -a', (err, stdout, stderr) => console.log(stdout)))
const startService = (service) => {
service = service.toLowerCase()
if (SERVICES.includes(service)) {
log(`Starting ${NAMES[service]}...`)
exec(`docker-compose start ${service}`).on('close', () => {
log(`${NAMES[service]} has successfully started`)
});
} else if (!service) {
log("Starting up Crato...")
deployCrato()
} else {
log(`${service} is not a valid service.`)
log(`{SERVICE_LISTING}`)
}
}
const stopService = (service) => {
service = service.toLowerCase()
if (SERVICES.includes(service)) {
log(`Stopping ${NAMES[service]}...`)
exec(`docker-compose stop ${service}`).on('close', () => {
log(`${NAMES[service]} has been shut down`)
});
} else if (!service) {
log("Shutting down Crato...")
stopCrato()
} else {
log(`${service} is not a valid service.`)
log(`{SERVICE_LISTING}`)
}
}
const installKafka = () => {
log('Installing Kafka...');
exec('docker-compose up -d zookeeper', (err, stdout, stderr) => {
log('Starting Zookeeper...');
setTimeout(() => {
log('Starting Kafka Brokers...');
exec('docker-compose up -d kafka').on('close', () => {
log('1st Kafka broker running');
exec('docker-compose up -d kafka2').on('close', () => {
log('2nd Kafka broker running');
exec('docker-compose up -d kafka3').on('close', () => {
log('3rd Kafka broker running');
setTimeout(() => {
log("Setting up 'textlogs' & 'jsonlogs' topic...")
exec('docker-compose exec kafka kafka-topics --create --zookeeper zookeeper:8092 --create --topic textlogs --replication-factor 3 --partitions 6 --if-not-exists').on('close', () => {
log('textlogs topic created')
exec('docker-compose exec kafka kafka-topics --create --zookeeper zookeeper:8092 --create --topic jsonlogs --replication-factor 3 --partitions 6 --if-not-exists').on('close', () => {
log('jsonlogs topic created')
exec('docker-compose stop');
log('Stopping Zookeeper and Kafka Brokers...')
})
})
}, 7000);
});
});
});
log('Kafka cluster created with 3 brokers!');
}, 7000);
});
}
program.version('0.7')
.description('📦 Crato: Log Management Framework.')
program.command('services')
.description("Provides a listing and description of all of Crato's services")
.action(() => { console.log(SERVICE_LISTING) })
program.command('deploy')
.description('Starts up Crato system')
.action(deployCrato)
program.command('shutdown')
.description('Stops Crato system and all services')
.action(stopCrato)
program.command('start <service>')
.description('Starts a specific Crato service')
.action((service) => startService(service))
program.command('stop <service>')
.description('Stops a specific Crato service')
.action((service) => stopService(service))
program.command('install-kafka')
.description("Installs Kafka cluster and textlogs & jsonlogs topics")
.action(installKafka)
program.command('container-logs <service>')
.alias('cl')
.description('Displays Docker container logs for a specific service')
.action((service) => displayDockerLogs(service))
program.command('live-tail')
.alias('lt')
.description('See all external logs streaming into Crato. Press Ctrl-C to exit')
.action(liveTail)
program.command('shell <service>')
.alias('sh')
.description('Attaches a shell to a specific Crato service')
.action(openShell)
program.command('status')
.description("Displays the status of all of Crato's services")
.action(displaySystemStatus)
// Assert that a VALID command is provided
if (!process.argv.slice(2).length || !/[arudl]/.test(process.argv.slice(2))) {
program.outputHelp();
process.exit();
}
program.parse(process.argv)