| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#!/usr/bin/env perl |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Core |
|
4
|
12
|
|
|
12
|
|
43431
|
use warnings; |
|
|
12
|
|
|
|
|
13
|
|
|
|
12
|
|
|
|
|
572
|
|
|
5
|
12
|
|
|
12
|
|
40
|
use strict; |
|
|
12
|
|
|
|
|
15
|
|
|
|
12
|
|
|
|
|
295
|
|
|
6
|
12
|
|
|
12
|
|
4269
|
use utf8; |
|
|
12
|
|
|
|
|
2624
|
|
|
|
12
|
|
|
|
|
53
|
|
|
7
|
12
|
|
|
12
|
|
428
|
use v5.28; |
|
|
12
|
|
|
|
|
44
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# Experimental (stable) |
|
10
|
12
|
|
|
12
|
|
4582
|
use experimental 'signatures'; |
|
|
12
|
|
|
|
|
37316
|
|
|
|
12
|
|
|
|
|
50
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
# External modules |
|
13
|
12
|
|
|
12
|
|
6058
|
use YAML::XS; |
|
|
12
|
|
|
|
|
30791
|
|
|
|
12
|
|
|
|
|
658
|
|
|
14
|
12
|
|
|
12
|
|
5712
|
use Getopt::Long::Descriptive; |
|
|
12
|
|
|
|
|
488076
|
|
|
|
12
|
|
|
|
|
78
|
|
|
15
|
12
|
|
|
12
|
|
8678
|
use POE qw(Session::PlainCall); |
|
|
12
|
|
|
|
|
426605
|
|
|
|
12
|
|
|
|
|
67
|
|
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# Our modules |
|
18
|
12
|
|
|
12
|
|
618524
|
use App::aep; |
|
|
12
|
|
|
|
|
49
|
|
|
|
12
|
|
|
|
|
663
|
|
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# Debug |
|
21
|
12
|
|
|
12
|
|
71
|
use Data::Dumper; |
|
|
12
|
|
|
|
|
18
|
|
|
|
12
|
|
|
|
|
708
|
|
|
22
|
12
|
|
|
12
|
|
54
|
use Carp qw(cluck longmess shortmess); |
|
|
12
|
|
|
|
|
26
|
|
|
|
12
|
|
|
|
|
985540
|
|
|
23
|
|
|
|
|
|
|
|
|
24
|
12
|
|
|
|
|
1707753
|
STDOUT->autoflush(1); |
|
25
|
12
|
|
|
|
|
605
|
STDERR->autoflush(1); |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# Version of this software |
|
28
|
12
|
|
|
|
|
263
|
our $VERSION = '0.013'; |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# Config defaults |
|
31
|
12
|
|
|
|
|
51
|
my $opt_conf_def = { 'AEP_SOCKETPATH' => '/tmp/aep.sock', }; |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# Option specs |
|
34
|
|
|
|
|
|
|
my @opt_desc = ( |
|
35
|
|
|
|
|
|
|
'aep %o ', |
|
36
|
|
|
|
|
|
|
[ |
|
37
|
|
|
|
|
|
|
'config-env', |
|
38
|
|
|
|
|
|
|
'Read config values from the environment only.', |
|
39
|
|
|
|
|
|
|
{ |
|
40
|
|
|
|
|
|
|
'default' => 0, |
|
41
|
|
|
|
|
|
|
}, |
|
42
|
|
|
|
|
|
|
], |
|
43
|
|
|
|
|
|
|
[ |
|
44
|
|
|
|
|
|
|
'config-file=s', |
|
45
|
|
|
|
|
|
|
'Read config from a config file only.', |
|
46
|
|
|
|
|
|
|
{ |
|
47
|
|
|
|
|
|
|
'default' => '$unset', |
|
48
|
|
|
|
|
|
|
'callbacks' => { |
|
49
|
2
|
|
|
2
|
|
7432
|
'exists' => sub { _check_exists( shift ) }, |
|
50
|
|
|
|
|
|
|
}, |
|
51
|
|
|
|
|
|
|
}, |
|
52
|
|
|
|
|
|
|
], |
|
53
|
|
|
|
|
|
|
[ |
|
54
|
|
|
|
|
|
|
'config-args', |
|
55
|
|
|
|
|
|
|
'Read config values from arguments only.', |
|
56
|
|
|
|
|
|
|
{ |
|
57
|
|
|
|
|
|
|
'default' => 0, |
|
58
|
|
|
|
|
|
|
}, |
|
59
|
|
|
|
|
|
|
], |
|
60
|
|
|
|
|
|
|
[ |
|
61
|
|
|
|
|
|
|
'config-merge', |
|
62
|
|
|
|
|
|
|
'Merge together env, file and args to generate a config.', |
|
63
|
|
|
|
|
|
|
{ |
|
64
|
|
|
|
|
|
|
'default' => 1, |
|
65
|
|
|
|
|
|
|
}, |
|
66
|
|
|
|
|
|
|
], |
|
67
|
|
|
|
|
|
|
[ |
|
68
|
|
|
|
|
|
|
'config-order=s', |
|
69
|
|
|
|
|
|
|
'The order to merge options together, comma separated, default is: env,file,args', |
|
70
|
|
|
|
|
|
|
{ |
|
71
|
|
|
|
|
|
|
'default' => 'env,file,args', |
|
72
|
|
|
|
|
|
|
}, |
|
73
|
|
|
|
|
|
|
], |
|
74
|
|
|
|
|
|
|
[], |
|
75
|
|
|
|
|
|
|
[ |
|
76
|
|
|
|
|
|
|
'env-prefix=s', |
|
77
|
|
|
|
|
|
|
'What prefix to look for aep config environmentals, default is AEP_', |
|
78
|
|
|
|
|
|
|
{ |
|
79
|
|
|
|
|
|
|
'default' => 'AEP_', |
|
80
|
|
|
|
|
|
|
}, |
|
81
|
|
|
|
|
|
|
], |
|
82
|
|
|
|
|
|
|
[], |
|
83
|
|
|
|
|
|
|
[ |
|
84
|
|
|
|
|
|
|
'command=s', |
|
85
|
|
|
|
|
|
|
'What to actually run within the container, default is print aes help.', |
|
86
|
|
|
|
|
|
|
{ |
|
87
|
|
|
|
|
|
|
'default' => 'aep --help', |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
], |
|
90
|
|
|
|
|
|
|
[ |
|
91
|
|
|
|
|
|
|
'command-args=s', |
|
92
|
|
|
|
|
|
|
'The arguments to add to the command comma separated, default is nothing.', |
|
93
|
|
|
|
|
|
|
{ |
|
94
|
|
|
|
|
|
|
'default' => "", |
|
95
|
|
|
|
|
|
|
}, |
|
96
|
|
|
|
|
|
|
], |
|
97
|
|
|
|
|
|
|
[ 'command-norestart', 'If the command exits then do not attempt to restart it.', ], |
|
98
|
|
|
|
|
|
|
[ |
|
99
|
|
|
|
|
|
|
'command-restart=i', |
|
100
|
|
|
|
|
|
|
'If the command exits how many times to retry it, default 0. Set to -1 for infinite.', |
|
101
|
|
|
|
|
|
|
{ |
|
102
|
|
|
|
|
|
|
'default' => 0, |
|
103
|
|
|
|
|
|
|
'callbacks' => { |
|
104
|
1
|
|
|
1
|
|
4252
|
'is_positive' => sub { _check_positive_number( shift ) }, |
|
105
|
|
|
|
|
|
|
}, |
|
106
|
|
|
|
|
|
|
}, |
|
107
|
12
|
|
|
|
|
740
|
], |
|
108
|
|
|
|
|
|
|
[ |
|
109
|
|
|
|
|
|
|
'command-restart-delay=i', |
|
110
|
|
|
|
|
|
|
'The time in milliseconds to wait before retrying the command, default 1000', |
|
111
|
|
|
|
|
|
|
{ |
|
112
|
|
|
|
|
|
|
'default' => 1000, |
|
113
|
|
|
|
|
|
|
}, |
|
114
|
|
|
|
|
|
|
], |
|
115
|
|
|
|
|
|
|
[], |
|
116
|
|
|
|
|
|
|
[ |
|
117
|
|
|
|
|
|
|
'lock-server', |
|
118
|
|
|
|
|
|
|
'Act like a lock server, this means we will expect other apps to ' |
|
119
|
|
|
|
|
|
|
. 'connect to us, we in turn will say when they should actually start, ' |
|
120
|
|
|
|
|
|
|
. 'this is to counter-act race issues when starting multi image ' |
|
121
|
|
|
|
|
|
|
. 'containers such as docker-compose, default: no', |
|
122
|
|
|
|
|
|
|
{ |
|
123
|
|
|
|
|
|
|
'default' => 0, |
|
124
|
|
|
|
|
|
|
}, |
|
125
|
|
|
|
|
|
|
], |
|
126
|
|
|
|
|
|
|
[ |
|
127
|
|
|
|
|
|
|
'lock-server-host=s', |
|
128
|
|
|
|
|
|
|
'What host to bind to, defaults to 0.0.0.0', |
|
129
|
|
|
|
|
|
|
{ |
|
130
|
|
|
|
|
|
|
'default' => '0.0.0.0', |
|
131
|
|
|
|
|
|
|
}, |
|
132
|
|
|
|
|
|
|
], |
|
133
|
|
|
|
|
|
|
[ |
|
134
|
|
|
|
|
|
|
'lock-server-port=i', |
|
135
|
|
|
|
|
|
|
'What port to bind to, defaults to 60000', |
|
136
|
|
|
|
|
|
|
{ |
|
137
|
|
|
|
|
|
|
'default' => 60000, |
|
138
|
|
|
|
|
|
|
}, |
|
139
|
|
|
|
|
|
|
], |
|
140
|
|
|
|
|
|
|
[ |
|
141
|
|
|
|
|
|
|
'lock-server-default=s', |
|
142
|
|
|
|
|
|
|
'If we get sent an ID we do not know, the default action to take. ' |
|
143
|
|
|
|
|
|
|
. 'Valid options are: "ignore", "run" or "runlast" the default is ignore.', |
|
144
|
|
|
|
|
|
|
{ |
|
145
|
|
|
|
|
|
|
'default' => 'ignore', |
|
146
|
|
|
|
|
|
|
}, |
|
147
|
|
|
|
|
|
|
], |
|
148
|
|
|
|
|
|
|
[ |
|
149
|
|
|
|
|
|
|
'lock-server-order=s', |
|
150
|
|
|
|
|
|
|
'The list of ids and the order to allow them to run, ' |
|
151
|
|
|
|
|
|
|
. 'comma separated. Use || for parallel groups, e.g.: db,redis1||redis2,nginx', |
|
152
|
|
|
|
|
|
|
{ |
|
153
|
|
|
|
|
|
|
'default' => '', |
|
154
|
|
|
|
|
|
|
}, |
|
155
|
|
|
|
|
|
|
], |
|
156
|
|
|
|
|
|
|
[ |
|
157
|
|
|
|
|
|
|
'lock-server-exhaust-action=s', |
|
158
|
|
|
|
|
|
|
'What to do when all clients in the order have started. ' |
|
159
|
|
|
|
|
|
|
. 'Valid options: "exit", "idle", "restart", "execute". Default is idle.', |
|
160
|
|
|
|
|
|
|
{ |
|
161
|
|
|
|
|
|
|
'default' => 'idle', |
|
162
|
|
|
|
|
|
|
}, |
|
163
|
|
|
|
|
|
|
], |
|
164
|
|
|
|
|
|
|
[], |
|
165
|
|
|
|
|
|
|
[ |
|
166
|
|
|
|
|
|
|
'lock-client', |
|
167
|
|
|
|
|
|
|
'Become a lock client, this will mean your aep will connect to ' |
|
168
|
|
|
|
|
|
|
. 'another aep to learn when it should run its command.', |
|
169
|
|
|
|
|
|
|
{ |
|
170
|
|
|
|
|
|
|
'default' => 0, |
|
171
|
|
|
|
|
|
|
}, |
|
172
|
|
|
|
|
|
|
], |
|
173
|
|
|
|
|
|
|
[ 'lock-client-noretry', 'If the connection to a master fails, do not retry - overrides lock-client-retry', ], |
|
174
|
|
|
|
|
|
|
[ |
|
175
|
|
|
|
|
|
|
'lock-client-retry=i', |
|
176
|
|
|
|
|
|
|
'If the connection to a master fails, do not fail retry n many times, ' |
|
177
|
|
|
|
|
|
|
. 'if this is set to 0 it will retry infinately, defaults to: 3 (seconds)', |
|
178
|
|
|
|
|
|
|
{ |
|
179
|
|
|
|
|
|
|
'default' => 3, |
|
180
|
|
|
|
|
|
|
}, |
|
181
|
|
|
|
|
|
|
], |
|
182
|
|
|
|
|
|
|
[ |
|
183
|
|
|
|
|
|
|
'lock-client-retry-delay=i', |
|
184
|
|
|
|
|
|
|
'How long to wait before retrying, default 5 (seconds)', |
|
185
|
|
|
|
|
|
|
{ |
|
186
|
|
|
|
|
|
|
'default' => 5, |
|
187
|
|
|
|
|
|
|
}, |
|
188
|
|
|
|
|
|
|
], |
|
189
|
|
|
|
|
|
|
[ |
|
190
|
|
|
|
|
|
|
'lock-client-timeout=i', |
|
191
|
|
|
|
|
|
|
'Maximum seconds to wait for the lock server to send run. 0 = wait forever. Default 0.', |
|
192
|
|
|
|
|
|
|
{ |
|
193
|
|
|
|
|
|
|
'default' => 0, |
|
194
|
|
|
|
|
|
|
}, |
|
195
|
|
|
|
|
|
|
], |
|
196
|
|
|
|
|
|
|
[ |
|
197
|
|
|
|
|
|
|
'lock-transport=s', |
|
198
|
|
|
|
|
|
|
'Transport to use for lock client: tcp, unix, or auto (try TCP then Unix). Default auto.', |
|
199
|
|
|
|
|
|
|
{ |
|
200
|
|
|
|
|
|
|
'default' => 'auto', |
|
201
|
|
|
|
|
|
|
}, |
|
202
|
|
|
|
|
|
|
], |
|
203
|
|
|
|
|
|
|
[], |
|
204
|
|
|
|
|
|
|
[ |
|
205
|
|
|
|
|
|
|
'lock-client-host=s', |
|
206
|
|
|
|
|
|
|
'What host to connect to, defaults to: aep-master', |
|
207
|
|
|
|
|
|
|
{ |
|
208
|
|
|
|
|
|
|
'default' => 'aep-master' |
|
209
|
|
|
|
|
|
|
}, |
|
210
|
|
|
|
|
|
|
], |
|
211
|
|
|
|
|
|
|
[ |
|
212
|
|
|
|
|
|
|
'lock-client-port=i', |
|
213
|
|
|
|
|
|
|
'What port to connect to, defaults to 60000', |
|
214
|
|
|
|
|
|
|
{ |
|
215
|
|
|
|
|
|
|
'default' => 60000, |
|
216
|
|
|
|
|
|
|
}, |
|
217
|
|
|
|
|
|
|
], |
|
218
|
|
|
|
|
|
|
[ |
|
219
|
|
|
|
|
|
|
'lock-trigger=s', |
|
220
|
|
|
|
|
|
|
'Please read --help-config lock-trigger, default is: none:time:10000 (milliseconds)', |
|
221
|
|
|
|
|
|
|
{ |
|
222
|
|
|
|
|
|
|
'default' => 'none:time:10000' |
|
223
|
|
|
|
|
|
|
}, |
|
224
|
|
|
|
|
|
|
], |
|
225
|
|
|
|
|
|
|
[ |
|
226
|
|
|
|
|
|
|
'lock-id=s', |
|
227
|
|
|
|
|
|
|
'What ID we should say we are, mandatory when acting as a lock-client', |
|
228
|
|
|
|
|
|
|
{ |
|
229
|
|
|
|
|
|
|
'default' => $$, |
|
230
|
|
|
|
|
|
|
}, |
|
231
|
|
|
|
|
|
|
], |
|
232
|
|
|
|
|
|
|
[], |
|
233
|
|
|
|
|
|
|
[ |
|
234
|
|
|
|
|
|
|
'quiet', |
|
235
|
|
|
|
|
|
|
'Suppress informational output, only show errors.', |
|
236
|
|
|
|
|
|
|
{ |
|
237
|
|
|
|
|
|
|
'default' => 0, |
|
238
|
|
|
|
|
|
|
}, |
|
239
|
|
|
|
|
|
|
], |
|
240
|
|
|
|
|
|
|
[ |
|
241
|
|
|
|
|
|
|
'verbose', |
|
242
|
|
|
|
|
|
|
'Show detailed debug output including packet contents.', |
|
243
|
|
|
|
|
|
|
{ |
|
244
|
|
|
|
|
|
|
'default' => 0, |
|
245
|
|
|
|
|
|
|
}, |
|
246
|
|
|
|
|
|
|
], |
|
247
|
|
|
|
|
|
|
[], |
|
248
|
|
|
|
|
|
|
[ |
|
249
|
|
|
|
|
|
|
'help', |
|
250
|
|
|
|
|
|
|
'print usage message and exit', |
|
251
|
|
|
|
|
|
|
{ |
|
252
|
|
|
|
|
|
|
'shortcircuit' => 1, |
|
253
|
|
|
|
|
|
|
}, |
|
254
|
|
|
|
|
|
|
], |
|
255
|
|
|
|
|
|
|
[ |
|
256
|
|
|
|
|
|
|
'help-config=s', |
|
257
|
|
|
|
|
|
|
'print configuration examples for: config-env, config-files, ' |
|
258
|
|
|
|
|
|
|
. 'config-arg, config-merge or lock-trigger eg: help-config config-env', |
|
259
|
|
|
|
|
|
|
{ |
|
260
|
|
|
|
|
|
|
'shortcircuit' => 1, |
|
261
|
|
|
|
|
|
|
}, |
|
262
|
|
|
|
|
|
|
], |
|
263
|
|
|
|
|
|
|
[ |
|
264
|
|
|
|
|
|
|
'docker-health-check', |
|
265
|
|
|
|
|
|
|
'Call this from docker-compose for a health report, returns an exit of 0(success) or 1(failure)', |
|
266
|
|
|
|
|
|
|
{ |
|
267
|
|
|
|
|
|
|
'default' => 0, |
|
268
|
|
|
|
|
|
|
}, |
|
269
|
|
|
|
|
|
|
], |
|
270
|
|
|
|
|
|
|
); |
|
271
|
|
|
|
|
|
|
# Read in our options |
|
272
|
12
|
|
|
|
|
108
|
my ( $opt, $usage ) = describe_options( @opt_desc ); |
|
273
|
|
|
|
|
|
|
|
|
274
|
10
|
100
|
|
|
|
54133
|
if ( $opt->help ) |
|
275
|
|
|
|
|
|
|
{ |
|
276
|
1
|
|
|
|
|
9
|
say $usage->text; |
|
277
|
1
|
|
|
|
|
0
|
exit 0; |
|
278
|
|
|
|
|
|
|
} |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# Define our main function that starts out perl POE kernel |
|
281
|
|
|
|
|
|
|
sub main ( @args ) |
|
282
|
9
|
|
|
9
|
|
12
|
{ |
|
|
9
|
|
|
|
|
20
|
|
|
|
9
|
|
|
|
|
14
|
|
|
283
|
9
|
|
|
|
|
28
|
my $options = {}; |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# Default exit code of error |
|
286
|
9
|
|
|
|
|
28
|
my $exit_code = 1; |
|
287
|
9
|
|
|
|
|
29
|
my $exit_reason = 'Unknown'; |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# Create a function to handle setting exit |
|
290
|
|
|
|
|
|
|
my $exit_func = sub { |
|
291
|
9
|
|
|
9
|
|
86
|
my ( $code, $reason ) = @_; |
|
292
|
9
|
50
|
33
|
|
|
163
|
if ( defined $code && $code =~ m#^\d+$# ) { $exit_code = $code } |
|
|
9
|
|
|
|
|
30
|
|
|
293
|
0
|
|
|
|
|
0
|
else { $exit_code = 1 } |
|
294
|
9
|
50
|
|
|
|
42
|
if ( defined $reason ) { $exit_reason = $reason } |
|
|
9
|
|
|
|
|
45
|
|
|
295
|
0
|
|
|
|
|
0
|
else { $reason = 'Unknown' } |
|
296
|
9
|
|
|
|
|
33
|
}; |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# Create an appropriate heap for our session |
|
299
|
9
|
|
|
|
|
33
|
my $func_map = _create_heap( $args[ 0 ], $args[ 1 ] ); |
|
300
|
|
|
|
|
|
|
|
|
301
|
9
|
50
|
|
|
|
24
|
my $log_level = $opt->quiet ? 'quiet' : ( $opt->verbose ? 'verbose' : 'info' ); |
|
|
|
50
|
|
|
|
|
|
|
302
|
9
|
|
|
|
|
68
|
$func_map->{ '_' }->{ 'log_level' } = $log_level; |
|
303
|
9
|
|
|
80
|
|
41
|
$func_map->{ '_' }->{ 'debug' } = sub { _func_debug( $log_level, @_ ) }; |
|
|
80
|
|
|
|
|
622
|
|
|
304
|
9
|
|
|
|
|
19
|
$func_map->{ '_' }->{ 'set_exit' } = $exit_func; |
|
305
|
|
|
|
|
|
|
|
|
306
|
9
|
|
|
|
|
154
|
my $session = POE::Session::PlainCall->create( |
|
307
|
|
|
|
|
|
|
'package' => 'App::aep', |
|
308
|
|
|
|
|
|
|
'ctor_args' => [ $options ], |
|
309
|
|
|
|
|
|
|
'heap' => $func_map, |
|
310
|
|
|
|
|
|
|
'states' => [ |
|
311
|
|
|
|
|
|
|
qw( |
|
312
|
|
|
|
|
|
|
_start sig_int sig_term sig_chld sig_usr scheduler |
|
313
|
|
|
|
|
|
|
command_start command_stdout command_stderr command_close command_error |
|
314
|
|
|
|
|
|
|
lock_trigger_fire lock_trigger_connect lock_trigger_script |
|
315
|
|
|
|
|
|
|
lock_client_timeout_fire lock_client_timeout_cancel |
|
316
|
|
|
|
|
|
|
) |
|
317
|
|
|
|
|
|
|
], |
|
318
|
|
|
|
|
|
|
); |
|
319
|
|
|
|
|
|
|
|
|
320
|
9
|
|
|
|
|
1157
|
$poe_kernel->run(); |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# Return an appropriate code and reason |
|
323
|
9
|
|
|
|
|
14124
|
return ( $exit_code, $exit_reason ); |
|
324
|
|
|
|
|
|
|
} |
|
325
|
|
|
|
|
|
|
|
|
326
|
9
|
|
|
|
|
12
|
sub _create_heap ( $opt, $usage ) |
|
327
|
9
|
|
|
9
|
|
14
|
{ |
|
|
9
|
|
|
|
|
62
|
|
|
|
9
|
|
|
|
|
33
|
|
|
328
|
9
|
|
|
|
|
21
|
my $map = { '_' => {}, }; |
|
329
|
9
|
|
|
|
|
26
|
$map->{ '_' }->{ 'opt' } = $opt; |
|
330
|
9
|
|
|
|
|
15
|
$map->{ '_' }->{ 'usage' } = $usage; |
|
331
|
9
|
|
|
|
|
18
|
$map->{ '_' }->{ 'default' } = $opt_conf_def; |
|
332
|
9
|
|
|
|
|
20
|
$map->{ '_' }->{ 'config' } = {}; |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
# As it will be accessed a lot, keep a copy here |
|
335
|
9
|
|
|
|
|
24
|
my $env_prefix = $opt->env_prefix; |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
# Collect appropriate environmental variables and stash them in the funcmap/heap |
|
338
|
9
|
|
|
|
|
84
|
foreach my $env_key ( keys %ENV ) |
|
339
|
|
|
|
|
|
|
{ |
|
340
|
244
|
|
|
|
|
232
|
my $env_val = $ENV{ $env_key }; |
|
341
|
244
|
100
|
|
|
|
464
|
if ( $env_key =~ m{^\Q$env_prefix\E} ) |
|
342
|
|
|
|
|
|
|
{ |
|
343
|
1
|
|
|
|
|
3
|
$map->{ '_' }->{ 'aep' }->{ $env_key } = $env_val; |
|
344
|
|
|
|
|
|
|
} |
|
345
|
|
|
|
|
|
|
else |
|
346
|
|
|
|
|
|
|
{ |
|
347
|
243
|
|
|
|
|
388
|
$map->{ '_' }->{ 'env' }->{ $env_key } = $env_val; |
|
348
|
|
|
|
|
|
|
} |
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# Process the resultant config by merging sources in the specified order |
|
352
|
9
|
|
|
|
|
20
|
my $merged = { %{ $opt_conf_def } }; |
|
|
9
|
|
|
|
|
23
|
|
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
# Read config file if specified |
|
355
|
9
|
|
|
|
|
15
|
my $file_config = {}; |
|
356
|
9
|
|
|
|
|
23
|
my $config_file = $opt->config_file; |
|
357
|
9
|
100
|
66
|
|
|
88
|
if ( defined $config_file && $config_file ne '$unset' && -e $config_file ) |
|
|
|
|
66
|
|
|
|
|
|
358
|
|
|
|
|
|
|
{ |
|
359
|
1
|
|
|
|
|
2
|
my $yaml_content = do { |
|
360
|
1
|
50
|
|
|
|
48
|
open my $fh, '<', $config_file or die "Cannot open config file '$config_file': $!"; |
|
361
|
1
|
|
|
|
|
5
|
local $/; |
|
362
|
1
|
|
|
|
|
40
|
<$fh>; |
|
363
|
|
|
|
|
|
|
}; |
|
364
|
1
|
|
50
|
|
|
64
|
$file_config = YAML::XS::Load( $yaml_content ) || {}; |
|
365
|
|
|
|
|
|
|
} |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
# Build source maps for merging |
|
368
|
|
|
|
|
|
|
my $sources = { |
|
369
|
9
|
|
100
|
|
|
56
|
'env' => $map->{ '_' }->{ 'aep' } || {}, |
|
370
|
|
|
|
|
|
|
'file' => $file_config, |
|
371
|
|
|
|
|
|
|
'args' => {}, |
|
372
|
|
|
|
|
|
|
}; |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# Use AEP_ prefixed env vars as config keys directly (preserve full key name) |
|
375
|
9
|
|
|
|
|
15
|
my $env_config = {}; |
|
376
|
9
|
|
|
|
|
12
|
for my $key ( keys %{ $sources->{ 'env' } } ) |
|
|
9
|
|
|
|
|
36
|
|
|
377
|
|
|
|
|
|
|
{ |
|
378
|
1
|
|
|
|
|
3
|
$env_config->{ $key } = $sources->{ 'env' }->{ $key }; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
9
|
|
|
|
|
17
|
$sources->{ 'env' } = $env_config; |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# Determine merge order |
|
383
|
9
|
|
50
|
|
|
22
|
my $order_str = $opt->config_order || 'env,file,args'; |
|
384
|
9
|
|
|
|
|
55
|
my @order = split( /,/, $order_str ); |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
# Apply sources in order (later overrides earlier) |
|
387
|
9
|
|
|
|
|
17
|
for my $source_name ( @order ) |
|
388
|
|
|
|
|
|
|
{ |
|
389
|
27
|
|
|
|
|
80
|
$source_name =~ s{^\s+|\s+$}{}g; |
|
390
|
27
|
|
50
|
|
|
46
|
my $source_data = $sources->{ $source_name } || {}; |
|
391
|
27
|
|
|
|
|
18
|
for my $key ( keys %{ $source_data } ) |
|
|
27
|
|
|
|
|
42
|
|
|
392
|
|
|
|
|
|
|
{ |
|
393
|
2
|
|
|
|
|
4
|
$merged->{ $key } = $source_data->{ $key }; |
|
394
|
|
|
|
|
|
|
} |
|
395
|
|
|
|
|
|
|
} |
|
396
|
|
|
|
|
|
|
|
|
397
|
9
|
|
|
|
|
57
|
$map->{ '_' }->{ 'config' } = $merged; |
|
398
|
|
|
|
|
|
|
|
|
399
|
9
|
|
|
|
|
64
|
return $map; |
|
400
|
|
|
|
|
|
|
} |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub _check_exists ( $val ) |
|
403
|
2
|
|
|
2
|
|
6
|
{ |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
4
|
|
|
404
|
2
|
50
|
|
|
|
9
|
if ( $val ne '$unset' ) { return $val ? -e $val : undef } |
|
|
2
|
50
|
|
|
|
177
|
|
|
405
|
0
|
|
|
|
|
0
|
else { return 1 } |
|
406
|
|
|
|
|
|
|
} |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub _check_positive_number ( $val ) |
|
409
|
1
|
|
|
1
|
|
2
|
{ |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
2
|
|
|
410
|
1
|
50
|
33
|
|
|
18
|
return ( $val >= 0 || $val == -1 ) ? 1 : undef; |
|
411
|
|
|
|
|
|
|
} |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
# Show debug messages |
|
414
|
|
|
|
|
|
|
# $log_level: 'quiet', 'info', or 'verbose' (global setting from --quiet/--verbose) |
|
415
|
|
|
|
|
|
|
# $level: 'error', 'info', or 'debug' (per-message level, defaults to 'info') |
|
416
|
89
|
|
|
|
|
150
|
sub _func_debug ( $log_level, $pipe, $line, $message, $level = 'info' ) |
|
|
89
|
|
|
|
|
173
|
|
|
|
89
|
|
|
|
|
117
|
|
|
|
89
|
|
|
|
|
108
|
|
|
|
89
|
|
|
|
|
160
|
|
|
417
|
89
|
|
|
89
|
|
99
|
{ |
|
|
89
|
|
|
|
|
56
|
|
|
418
|
|
|
|
|
|
|
# Filter messages based on log level |
|
419
|
89
|
50
|
33
|
|
|
192
|
if ( $log_level eq 'quiet' && $level ne 'error' ) |
|
420
|
|
|
|
|
|
|
{ |
|
421
|
0
|
|
|
|
|
0
|
return; |
|
422
|
|
|
|
|
|
|
} |
|
423
|
89
|
50
|
33
|
|
|
317
|
if ( $log_level eq 'info' && $level eq 'debug' ) |
|
424
|
|
|
|
|
|
|
{ |
|
425
|
0
|
|
|
|
|
0
|
return; |
|
426
|
|
|
|
|
|
|
} |
|
427
|
|
|
|
|
|
|
# 'verbose' shows everything |
|
428
|
|
|
|
|
|
|
|
|
429
|
89
|
|
|
|
|
87
|
my @buffer; |
|
430
|
|
|
|
|
|
|
|
|
431
|
89
|
100
|
66
|
|
|
296
|
if ( $message && ref( $message ) eq 'HASH' ) |
|
432
|
|
|
|
|
|
|
{ |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
# Fancy message - Add a default for lefttab (add more later) |
|
435
|
9
|
50
|
33
|
|
|
76
|
if ( $message->{ 'lines' } && ref( $message->{ 'lines' } ) eq 'ARRAY' ) |
|
436
|
|
|
|
|
|
|
{ |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
# nothing to do, makes sense |
|
439
|
9
|
|
|
|
|
15
|
@buffer = @{ $message->{ 'lines' } }; |
|
|
9
|
|
|
|
|
28
|
|
|
440
|
|
|
|
|
|
|
} |
|
441
|
|
|
|
|
|
|
else |
|
442
|
|
|
|
|
|
|
{ |
|
443
|
|
|
|
|
|
|
# No idea what to do, re-pop it as dumper |
|
444
|
0
|
|
|
|
|
0
|
push @buffer, 'Unexpected multiline format log packet, using data::dumper'; |
|
445
|
0
|
|
|
|
|
0
|
push @buffer, split( /\n/, Dumper( $message->{ 'lines' } ) ); |
|
446
|
|
|
|
|
|
|
} |
|
447
|
|
|
|
|
|
|
} |
|
448
|
|
|
|
|
|
|
else |
|
449
|
|
|
|
|
|
|
{ |
|
450
|
80
|
|
|
|
|
91
|
push @buffer, $message; |
|
451
|
|
|
|
|
|
|
} |
|
452
|
|
|
|
|
|
|
|
|
453
|
89
|
|
|
|
|
90
|
my $msg_first = 1; |
|
454
|
89
|
|
|
|
|
111
|
my $left_buffer_size = 0; |
|
455
|
89
|
|
|
|
|
133
|
foreach my $out_msg ( @buffer ) |
|
456
|
|
|
|
|
|
|
{ |
|
457
|
107
|
100
|
|
|
|
192
|
if ( $msg_first++ == 1 ) |
|
458
|
|
|
|
|
|
|
{ |
|
459
|
89
|
|
|
|
|
149
|
my $msg_prefix = "AEP($pipe:$line) "; |
|
460
|
89
|
|
|
|
|
74
|
$left_buffer_size = length( $msg_prefix ); |
|
461
|
89
|
|
|
|
|
3342
|
say STDERR "\r$msg_prefix$out_msg"; |
|
462
|
|
|
|
|
|
|
} |
|
463
|
|
|
|
|
|
|
else |
|
464
|
|
|
|
|
|
|
{ |
|
465
|
18
|
|
|
|
|
351
|
say STDERR ' ' x $left_buffer_size, $out_msg; |
|
466
|
|
|
|
|
|
|
} |
|
467
|
|
|
|
|
|
|
} |
|
468
|
|
|
|
|
|
|
|
|
469
|
89
|
|
|
|
|
245
|
return; |
|
470
|
|
|
|
|
|
|
} |
|
471
|
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
# Call the main function with selected options |
|
473
|
|
|
|
|
|
|
exit do |
|
474
|
9
|
|
|
|
|
72
|
{ |
|
475
|
9
|
|
|
|
|
36
|
my ( $exit_code, $exit_reason ) = main( $opt, $usage ); |
|
476
|
|
|
|
|
|
|
|
|
477
|
9
|
50
|
33
|
|
|
1391
|
if ( ( !defined $exit_code ) || ( $exit_code !~ m#^\d+$# ) || ( $exit_code > 255 ) || ( $exit_code < 0 ) ) |
|
|
|
|
33
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
478
|
|
|
|
|
|
|
{ |
|
479
|
0
|
|
|
|
|
0
|
$exit_code = 255; |
|
480
|
|
|
|
|
|
|
} |
|
481
|
|
|
|
|
|
|
|
|
482
|
9
|
50
|
|
|
|
60
|
my $final_log_level = $opt->quiet ? 'quiet' : ( $opt->verbose ? 'verbose' : 'info' ); |
|
|
|
50
|
|
|
|
|
|
|
483
|
9
|
|
|
|
|
251
|
_func_debug( |
|
484
|
|
|
|
|
|
|
$final_log_level, 'STDERR', __LINE__, |
|
485
|
|
|
|
|
|
|
{ |
|
486
|
|
|
|
|
|
|
'lines' => [ "Child exiting with: $exit_code", "Status: $exit_reason", 'Perl exception: ' . $!, ] |
|
487
|
|
|
|
|
|
|
} |
|
488
|
|
|
|
|
|
|
); |
|
489
|
|
|
|
|
|
|
|
|
490
|
9
|
|
|
|
|
0
|
$exit_code; |
|
491
|
|
|
|
|
|
|
}; |
|
492
|
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
__END__ |