line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Clustericious::Config; |
2
|
|
|
|
|
|
|
|
3
|
20
|
|
|
20
|
|
203387
|
use strict; |
|
20
|
|
|
|
|
37
|
|
|
20
|
|
|
|
|
1026
|
|
4
|
18
|
|
|
18
|
|
96
|
use warnings; |
|
18
|
|
|
|
|
31
|
|
|
18
|
|
|
|
|
644
|
|
5
|
17
|
|
|
17
|
|
184
|
use v5.10; |
|
17
|
|
|
|
|
53
|
|
|
17
|
|
|
|
|
1069
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# ABSTRACT: Configuration files for Clustericious nodes. |
8
|
|
|
|
|
|
|
our $VERSION = '0.29'; # VERSION |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
|
11
|
16
|
|
|
16
|
|
7919
|
use Clustericious::Config::Password; |
|
16
|
|
|
|
|
43
|
|
|
16
|
|
|
|
|
506
|
|
12
|
16
|
|
|
16
|
|
90
|
use List::Util; |
|
16
|
|
|
|
|
29
|
|
|
16
|
|
|
|
|
1184
|
|
13
|
15
|
|
|
15
|
|
17089
|
use JSON::XS; |
|
15
|
|
|
|
|
105532
|
|
|
15
|
|
|
|
|
1052
|
|
14
|
15
|
|
|
15
|
|
4952
|
use YAML::XS (); |
|
15
|
|
|
|
|
19581
|
|
|
15
|
|
|
|
|
296
|
|
15
|
15
|
|
|
15
|
|
14316
|
use Mojo::Template; |
|
15
|
|
|
|
|
1066502
|
|
|
15
|
|
|
|
|
177
|
|
16
|
15
|
|
|
15
|
|
22550
|
use Log::Log4perl qw/:easy/; |
|
15
|
|
|
|
|
891344
|
|
|
15
|
|
|
|
|
118
|
|
17
|
15
|
|
|
15
|
|
26857
|
use Storable; |
|
15
|
|
|
|
|
57452
|
|
|
15
|
|
|
|
|
1044
|
|
18
|
15
|
|
|
15
|
|
10270
|
use Clustericious::Config::Helpers (); |
|
15
|
|
|
|
|
46
|
|
|
15
|
|
|
|
|
331
|
|
19
|
15
|
|
|
15
|
|
85
|
use Data::Dumper; |
|
15
|
|
|
|
|
33
|
|
|
15
|
|
|
|
|
612
|
|
20
|
15
|
|
|
15
|
|
78
|
use Cwd (); |
|
15
|
|
|
|
|
34
|
|
|
15
|
|
|
|
|
223
|
|
21
|
15
|
|
|
15
|
|
16046
|
use Module::Build; |
|
15
|
|
|
|
|
1640802
|
|
|
15
|
|
|
|
|
584
|
|
22
|
15
|
|
|
15
|
|
4461
|
use File::HomeDir (); |
|
15
|
|
|
|
|
40460
|
|
|
15
|
|
|
|
|
22661
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
our %Singletons; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub _is_subdir { |
27
|
0
|
|
|
0
|
|
0
|
my ($child,$parent) = @_; |
28
|
0
|
|
|
|
|
0
|
my $p = Cwd::abs_path($parent); |
29
|
0
|
|
|
|
|
0
|
my $c = Cwd::abs_path($child); |
30
|
0
|
0
|
|
|
|
0
|
return ($c =~ m[^\Q$p\E]) ? 1 : 0; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my $is_test = 0; |
34
|
|
|
|
|
|
|
sub _testing { |
35
|
52
|
|
|
52
|
|
108
|
my($class, $new) = @_; |
36
|
52
|
100
|
|
|
|
187
|
$is_test = $new if defined $new; |
37
|
52
|
|
|
|
|
6032
|
$is_test; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
our $class_suffix = {}; |
41
|
|
|
|
|
|
|
sub _uncache { |
42
|
10
|
|
|
10
|
|
24
|
my($class, $name) = @_; |
43
|
10
|
|
|
|
|
35
|
delete $Clustericious::Config::Singletons{$name}; |
44
|
10
|
|
100
|
|
|
74
|
$class_suffix->{$name} //= 1; |
45
|
10
|
|
|
|
|
33
|
$class_suffix->{$name}++; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
19
|
|
|
19
|
0
|
31
|
sub pre_rendered { } |
49
|
19
|
|
|
19
|
0
|
34
|
sub rendered { } |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub new { |
53
|
25
|
|
|
25
|
1
|
3467
|
my $class = shift; |
54
|
25
|
100
|
|
|
|
123
|
my %t_args = (ref $_[-1] eq 'ARRAY' ? @{( pop )} : () ); |
|
3
|
|
|
|
|
8
|
|
55
|
25
|
|
|
|
|
52
|
my $arg = $_[0]; |
56
|
25
|
50
|
|
|
|
82
|
($arg = caller) =~ s/:.*$// unless $arg; # Determine from caller's class |
57
|
25
|
50
|
|
|
|
100
|
return $Singletons{$arg} if exists($Singletons{$arg}); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
25
|
|
|
|
|
53
|
my $we_are_testing_this_module = 0; |
61
|
25
|
100
|
|
|
|
108
|
if(__PACKAGE__->_testing) { |
62
|
9
|
|
|
|
|
18
|
$we_are_testing_this_module = 0; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
25
|
|
|
|
|
90
|
my $conf_data; |
66
|
|
|
|
|
|
|
|
67
|
25
|
|
|
|
|
280
|
my $json = JSON::XS->new; |
68
|
|
|
|
|
|
|
|
69
|
25
|
|
|
|
|
55
|
state $package_counter = 0; |
70
|
25
|
|
|
|
|
77
|
my $namespace = "Clustericious::Config::TemplatePackage::Package$package_counter"; |
71
|
13
|
|
|
13
|
|
109
|
eval qq{ package $namespace; use Clustericious::Config::Helpers; }; |
|
13
|
|
|
|
|
23
|
|
|
13
|
|
|
|
|
1368
|
|
|
25
|
|
|
|
|
2440
|
|
72
|
25
|
50
|
|
|
|
98
|
die $@ if $@; |
73
|
25
|
|
|
|
|
46
|
$package_counter++; |
74
|
|
|
|
|
|
|
|
75
|
25
|
|
|
|
|
441
|
my $mt = Mojo::Template->new(namespace => $namespace)->auto_escape(0); |
76
|
25
|
|
|
|
|
1592
|
$mt->prepend( join "\n", map " my \$$_ = q{$t_args{$_}};", sort keys %t_args ); |
77
|
|
|
|
|
|
|
|
78
|
25
|
|
|
|
|
241
|
my $filename; |
79
|
25
|
100
|
0
|
|
|
184
|
if (ref $arg eq 'SCALAR') { |
|
|
100
|
33
|
|
|
|
|
|
|
50
|
|
|
|
|
|
80
|
4
|
|
|
|
|
25
|
$class->pre_rendered( $$arg ); |
81
|
4
|
|
|
|
|
24
|
my $rendered = $mt->render($$arg); |
82
|
4
|
|
|
|
|
6685
|
$class->rendered( SCALAR => $rendered ); |
83
|
4
|
50
|
|
|
|
18
|
die $rendered if ( (ref($rendered)) =~ /Exception/ ); |
84
|
4
|
100
|
|
|
|
21
|
my $type = $rendered =~ /^---/ ? 'yaml' : 'json'; |
85
|
|
|
|
|
|
|
$conf_data = $type eq 'yaml' ? |
86
|
1
|
|
|
|
|
229
|
eval { YAML::XS::Load( $rendered ); } |
87
|
4
|
100
|
|
|
|
14
|
: eval { $json->decode( $rendered ); }; |
|
3
|
|
|
|
|
47
|
|
88
|
4
|
50
|
|
|
|
28
|
LOGDIE "Could not parse $type \n-------\n$rendered\n---------\n$@\n" if $@; |
89
|
|
|
|
|
|
|
} elsif (ref $arg eq 'HASH') { |
90
|
4
|
|
|
|
|
395
|
$conf_data = Storable::dclone $arg; |
91
|
|
|
|
|
|
|
} elsif ( |
92
|
|
|
|
|
|
|
$we_are_testing_this_module |
93
|
|
|
|
|
|
|
&& !( |
94
|
|
|
|
|
|
|
$ENV{CLUSTERICIOUS_CONF_DIR} |
95
|
|
|
|
|
|
|
&& _is_subdir( $ENV{CLUSTERICIOUS_CONF_DIR}, Cwd::getcwd() ) |
96
|
|
|
|
|
|
|
)) { |
97
|
0
|
|
|
|
|
0
|
$conf_data = {}; |
98
|
|
|
|
|
|
|
} else { |
99
|
17
|
|
|
|
|
25
|
my @conf_dirs; |
100
|
|
|
|
|
|
|
|
101
|
17
|
100
|
|
|
|
90
|
@conf_dirs = $ENV{CLUSTERICIOUS_CONF_DIR} if defined( $ENV{CLUSTERICIOUS_CONF_DIR} ); |
102
|
|
|
|
|
|
|
|
103
|
17
|
100
|
66
|
|
|
147
|
push @conf_dirs, ( File::HomeDir->my_home . "/etc", "/util/etc", "/etc" ) unless $we_are_testing_this_module || __PACKAGE__->_testing; |
104
|
17
|
|
|
|
|
306
|
my $conf_file = "$arg.conf"; |
105
|
17
|
|
|
|
|
42
|
$conf_file =~ s/::/-/g; |
106
|
17
|
|
|
23
|
|
198
|
my ($dir) = List::Util::first { -e "$_/$conf_file" } @conf_dirs; |
|
23
|
|
|
|
|
506
|
|
107
|
17
|
100
|
|
|
|
92
|
if ($dir) { |
108
|
15
|
|
|
|
|
121
|
TRACE "reading from config file $dir/$conf_file"; |
109
|
15
|
|
|
|
|
230
|
$filename = "$dir/$conf_file"; |
110
|
15
|
|
|
|
|
71
|
$class->pre_rendered( $filename ); |
111
|
15
|
|
|
|
|
88
|
my $rendered = $mt->render_file($filename); |
112
|
15
|
|
|
|
|
327
|
$class->rendered( $filename => $rendered ); |
113
|
15
|
50
|
|
|
|
61
|
die $rendered if ( (ref $rendered) =~ /Exception/ ); |
114
|
15
|
100
|
|
|
|
82
|
my $type = $rendered =~ /^---/ ? 'yaml' : 'json'; |
115
|
15
|
50
|
|
|
|
78
|
if ($ENV{CL_CONF_TRACE}) { |
116
|
0
|
|
|
|
|
0
|
warn "configuration ($type) : \n"; |
117
|
0
|
|
|
|
|
0
|
warn $rendered; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
$conf_data = |
120
|
|
|
|
|
|
|
$type eq 'yaml' |
121
|
13
|
|
|
|
|
1081
|
? eval { YAML::XS::Load($rendered) } |
122
|
15
|
100
|
|
|
|
57
|
: eval { $json->decode($rendered) }; |
|
2
|
|
|
|
|
27
|
|
123
|
15
|
50
|
|
|
|
103
|
LOGDIE "Could not parse $type\n-------\n$rendered\n---------\n$@\n" if $@; |
124
|
|
|
|
|
|
|
} else { |
125
|
2
|
50
|
|
|
|
18
|
TRACE "could not find $conf_file file in: @conf_dirs" unless $dir; |
126
|
2
|
|
|
|
|
24
|
$conf_data = {}; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
} |
129
|
25
|
|
100
|
|
|
90
|
$conf_data ||= {}; |
130
|
25
|
|
|
|
|
186
|
Clustericious::Config::Helpers->_do_merges($conf_data); |
131
|
25
|
|
|
|
|
19732
|
_add_heuristics($filename,$conf_data); |
132
|
|
|
|
|
|
|
# Use derived classes so that AUTOLOADING keeps namespaces separate |
133
|
|
|
|
|
|
|
# for various apps. |
134
|
25
|
100
|
|
|
|
84
|
if ($class eq __PACKAGE__) { |
135
|
22
|
100
|
|
|
|
77
|
if (ref $arg) { |
136
|
5
|
|
|
|
|
14
|
$arg = "$arg"; |
137
|
5
|
|
|
|
|
25
|
$arg =~ tr/a-zA-Z0-9//cd; |
138
|
|
|
|
|
|
|
} |
139
|
22
|
|
|
|
|
83
|
$class = join '::', $class, 'App', $arg; |
140
|
22
|
100
|
|
|
|
109
|
$class .= $class_suffix->{$arg} if $class_suffix->{$arg}; |
141
|
22
|
|
|
|
|
106
|
my $dome = '@'."$class"."::ISA = ('".__PACKAGE__. "')"; |
142
|
22
|
|
|
|
|
1519
|
eval $dome; |
143
|
22
|
50
|
|
|
|
111
|
die "error setting ISA : $@" if $@; |
144
|
|
|
|
|
|
|
} |
145
|
25
|
|
|
|
|
425
|
bless $conf_data, $class; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub _add_heuristics { |
149
|
25
|
|
|
25
|
|
46
|
my $filename = shift; |
150
|
|
|
|
|
|
|
# Account for some mojo api changes |
151
|
25
|
|
|
|
|
45
|
my $conf_data = shift; |
152
|
25
|
50
|
33
|
|
|
128
|
if ($conf_data->{hypnotoad} && !ref($conf_data->{hypnotoad}{listen})) { |
153
|
0
|
|
|
|
|
0
|
warn "# hypnotoad->listen should be an arrayref in $filename\n"; |
154
|
0
|
|
|
|
|
0
|
$conf_data->{hypnotoad}{listen} = [ $conf_data->{hypnotoad}{listen} ]; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub dump_as_yaml { |
162
|
0
|
|
|
0
|
1
|
0
|
my $c = shift; |
163
|
0
|
|
|
|
|
0
|
return YAML::XS::Dump($c); |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub _stringify { |
167
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
168
|
0
|
|
|
|
|
0
|
return join ' ', map { ($_, $self->{$_}) } sort keys %$self; |
|
0
|
|
|
|
|
0
|
|
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
0
|
|
|
0
|
|
0
|
sub DESTROY { |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub AUTOLOAD { |
175
|
52
|
|
|
52
|
|
9495
|
my $self = shift; |
176
|
52
|
|
|
|
|
104
|
my %args = @_; |
177
|
52
|
|
|
|
|
84
|
my $default = $args{default}; |
178
|
52
|
|
|
|
|
101
|
my $default_exists = exists $args{default}; |
179
|
52
|
|
|
|
|
55
|
our $AUTOLOAD; |
180
|
52
|
|
|
|
|
73
|
my $called = $AUTOLOAD; |
181
|
52
|
|
|
|
|
317
|
$called =~ s/.*:://g; |
182
|
52
|
100
|
66
|
|
|
192
|
if ($default_exists && !exists($self->{$called})) { |
183
|
4
|
|
|
|
|
11
|
$self->{$called} = $args{default}; |
184
|
|
|
|
|
|
|
} |
185
|
52
|
100
|
66
|
|
|
404
|
Carp::cluck "config element '$called' not found for ".(ref $self)." (".(join ',',keys(%$self)).")" |
186
|
|
|
|
|
|
|
if $called =~ /^_/ || !exists($self->{$called}); |
187
|
52
|
|
|
|
|
101
|
my $value = $self->{$called}; |
188
|
52
|
|
|
|
|
58
|
my $obj; |
189
|
52
|
|
|
|
|
76
|
my $invocant = ref $self; |
190
|
52
|
100
|
|
|
|
133
|
if (ref $value eq 'HASH') { |
191
|
3
|
|
|
|
|
23
|
$obj = $invocant->new($value); |
192
|
|
|
|
|
|
|
} |
193
|
15
|
|
|
15
|
|
123
|
no strict 'refs'; |
|
15
|
|
|
|
|
33
|
|
|
15
|
|
|
|
|
2571
|
|
194
|
52
|
|
|
|
|
269
|
*{ $invocant . "::$called" } = sub { |
195
|
82
|
|
|
82
|
|
122
|
my $self = shift; |
196
|
82
|
100
|
100
|
|
|
286
|
$self->{$called} = $default if $default_exists && !exists($self->{$called}); |
197
|
82
|
100
|
|
|
|
428
|
die "'$called' not found in ".join ',',keys(%$self) |
198
|
|
|
|
|
|
|
unless exists($self->{$called}); |
199
|
79
|
|
|
|
|
137
|
my $value = $self->{$called}; |
200
|
79
|
50
|
100
|
|
|
814
|
return wantarray && (ref $value eq 'HASH' ) ? %$value |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
201
|
|
|
|
|
|
|
: wantarray && (ref $value eq 'ARRAY') ? @$value |
202
|
|
|
|
|
|
|
: defined($obj) ? $obj |
203
|
|
|
|
|
|
|
: Clustericious::Config::Password->is_sentinel($value) ? Clustericious::Config::Password->get |
204
|
|
|
|
|
|
|
: $value; |
205
|
52
|
|
|
|
|
262
|
}; |
206
|
15
|
|
|
15
|
|
81
|
use strict 'refs'; |
|
15
|
|
|
|
|
30
|
|
|
15
|
|
|
|
|
1661
|
|
207
|
52
|
|
|
|
|
149
|
$self->$called; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub set_singleton { |
212
|
0
|
|
|
0
|
1
|
|
my $class = shift; |
213
|
0
|
|
|
|
|
|
my $app = shift; |
214
|
0
|
|
|
|
|
|
my $obj = shift; |
215
|
0
|
|
|
|
|
|
our %Singletons; |
216
|
0
|
|
|
|
|
|
$Singletons{$app} = $obj; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
1; |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
__END__ |