line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Clustericious::Config; |
2
|
|
|
|
|
|
|
|
3
|
19
|
|
|
19
|
|
203939
|
use strict; |
|
19
|
|
|
|
|
40
|
|
|
19
|
|
|
|
|
1003
|
|
4
|
17
|
|
|
17
|
|
99
|
use warnings; |
|
17
|
|
|
|
|
32
|
|
|
17
|
|
|
|
|
662
|
|
5
|
16
|
|
|
16
|
|
183
|
use v5.10; |
|
16
|
|
|
|
|
46
|
|
|
16
|
|
|
|
|
1133
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# ABSTRACT: configuration files for Clustericious nodes. |
8
|
|
|
|
|
|
|
our $VERSION = '0.28'; # VERSION |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
|
11
|
15
|
|
|
15
|
|
7646
|
use Clustericious::Config::Password; |
|
15
|
|
|
|
|
51
|
|
|
15
|
|
|
|
|
503
|
|
12
|
15
|
|
|
15
|
|
94
|
use List::Util; |
|
15
|
|
|
|
|
31
|
|
|
15
|
|
|
|
|
1149
|
|
13
|
14
|
|
|
14
|
|
16475
|
use JSON::XS; |
|
14
|
|
|
|
|
99888
|
|
|
14
|
|
|
|
|
969
|
|
14
|
14
|
|
|
14
|
|
11732
|
use YAML::XS (); |
|
14
|
|
|
|
|
18126
|
|
|
14
|
|
|
|
|
318
|
|
15
|
14
|
|
|
14
|
|
12654
|
use Mojo::Template; |
|
14
|
|
|
|
|
1057216
|
|
|
14
|
|
|
|
|
188
|
|
16
|
14
|
|
|
14
|
|
32779
|
use Log::Log4perl qw/:easy/; |
|
14
|
|
|
|
|
831942
|
|
|
14
|
|
|
|
|
116
|
|
17
|
14
|
|
|
14
|
|
25308
|
use Storable; |
|
14
|
|
|
|
|
53135
|
|
|
14
|
|
|
|
|
937
|
|
18
|
14
|
|
|
14
|
|
9478
|
use Clustericious::Config::Helpers (); |
|
14
|
|
|
|
|
43
|
|
|
14
|
|
|
|
|
365
|
|
19
|
14
|
|
|
14
|
|
88
|
use Data::Dumper; |
|
14
|
|
|
|
|
24
|
|
|
14
|
|
|
|
|
598
|
|
20
|
14
|
|
|
14
|
|
71
|
use Cwd (); |
|
14
|
|
|
|
|
24
|
|
|
14
|
|
|
|
|
210
|
|
21
|
14
|
|
|
14
|
|
15459
|
use Module::Build; |
|
14
|
|
|
|
|
1581490
|
|
|
14
|
|
|
|
|
602
|
|
22
|
14
|
|
|
14
|
|
4381
|
use File::HomeDir (); |
|
14
|
|
|
|
|
34000
|
|
|
14
|
|
|
|
|
23526
|
|
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
|
49
|
|
|
49
|
|
99
|
my($class, $new) = @_; |
36
|
49
|
100
|
|
|
|
182
|
$is_test = $new if defined $new; |
37
|
49
|
|
|
|
|
5629
|
$is_test; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
our $class_suffix = {}; |
41
|
|
|
|
|
|
|
sub _uncache { |
42
|
9
|
|
|
9
|
|
31
|
my($class, $name) = @_; |
43
|
9
|
|
|
|
|
25
|
delete $Clustericious::Config::Singletons{$name}; |
44
|
9
|
|
100
|
|
|
70
|
$class_suffix->{$name} //= 1; |
45
|
9
|
|
|
|
|
30
|
$class_suffix->{$name}++; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
18
|
|
|
18
|
0
|
28
|
sub pre_rendered { } |
49
|
18
|
|
|
18
|
0
|
32
|
sub rendered { } |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub new { |
53
|
24
|
|
|
24
|
1
|
4138
|
my $class = shift; |
54
|
24
|
100
|
|
|
|
126
|
my %t_args = (ref $_[-1] eq 'ARRAY' ? @{( pop )} : () ); |
|
3
|
|
|
|
|
10
|
|
55
|
24
|
|
|
|
|
56
|
my $arg = $_[0]; |
56
|
24
|
50
|
|
|
|
85
|
($arg = caller) =~ s/:.*$// unless $arg; # Determine from caller's class |
57
|
24
|
50
|
|
|
|
99
|
return $Singletons{$arg} if exists($Singletons{$arg}); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
24
|
|
|
|
|
44
|
my $we_are_testing_this_module = 0; |
61
|
24
|
100
|
|
|
|
113
|
if(__PACKAGE__->_testing) { |
62
|
8
|
|
|
|
|
17
|
$we_are_testing_this_module = 0; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
24
|
|
|
|
|
85
|
my $conf_data; |
66
|
|
|
|
|
|
|
|
67
|
24
|
|
|
|
|
282
|
my $json = JSON::XS->new; |
68
|
|
|
|
|
|
|
|
69
|
24
|
|
|
|
|
54
|
state $package_counter = 0; |
70
|
24
|
|
|
|
|
75
|
my $namespace = "Clustericious::Config::TemplatePackage::Package$package_counter"; |
71
|
12
|
|
|
12
|
|
106
|
eval qq{ package $namespace; use Clustericious::Config::Helpers; }; |
|
12
|
|
|
|
|
24
|
|
|
12
|
|
|
|
|
1279
|
|
|
24
|
|
|
|
|
2459
|
|
72
|
24
|
50
|
|
|
|
100
|
die $@ if $@; |
73
|
24
|
|
|
|
|
81
|
$package_counter++; |
74
|
|
|
|
|
|
|
|
75
|
24
|
|
|
|
|
386
|
my $mt = Mojo::Template->new(namespace => $namespace)->auto_escape(0); |
76
|
24
|
|
|
|
|
1582
|
$mt->prepend( join "\n", map " my \$$_ = q{$t_args{$_}};", sort keys %t_args ); |
77
|
|
|
|
|
|
|
|
78
|
24
|
|
|
|
|
235
|
my $filename; |
79
|
24
|
100
|
0
|
|
|
187
|
if (ref $arg eq 'SCALAR') { |
|
|
100
|
33
|
|
|
|
|
|
|
50
|
|
|
|
|
|
80
|
4
|
|
|
|
|
21
|
$class->pre_rendered( $$arg ); |
81
|
4
|
|
|
|
|
24
|
my $rendered = $mt->render($$arg); |
82
|
4
|
|
|
|
|
10735
|
$class->rendered( SCALAR => $rendered ); |
83
|
4
|
50
|
|
|
|
16
|
die $rendered if ( (ref($rendered)) =~ /Exception/ ); |
84
|
4
|
100
|
|
|
|
19
|
my $type = $rendered =~ /^---/ ? 'yaml' : 'json'; |
85
|
|
|
|
|
|
|
$conf_data = $type eq 'yaml' ? |
86
|
1
|
|
|
|
|
143
|
eval { YAML::XS::Load( $rendered ); } |
87
|
4
|
100
|
|
|
|
15
|
: eval { $json->decode( $rendered ); }; |
|
3
|
|
|
|
|
42
|
|
88
|
4
|
50
|
|
|
|
17
|
LOGDIE "Could not parse $type \n-------\n$rendered\n---------\n$@\n" if $@; |
89
|
|
|
|
|
|
|
} elsif (ref $arg eq 'HASH') { |
90
|
4
|
|
|
|
|
446
|
$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
|
16
|
|
|
|
|
27
|
my @conf_dirs; |
100
|
|
|
|
|
|
|
|
101
|
16
|
100
|
|
|
|
100
|
@conf_dirs = $ENV{CLUSTERICIOUS_CONF_DIR} if defined( $ENV{CLUSTERICIOUS_CONF_DIR} ); |
102
|
|
|
|
|
|
|
|
103
|
16
|
100
|
66
|
|
|
92
|
push @conf_dirs, ( File::HomeDir->my_home . "/etc", "/util/etc", "/etc" ) unless $we_are_testing_this_module || __PACKAGE__->_testing; |
104
|
16
|
|
|
|
|
381
|
my $conf_file = "$arg.conf"; |
105
|
16
|
|
|
|
|
51
|
$conf_file =~ s/::/-/g; |
106
|
16
|
|
|
22
|
|
219
|
my ($dir) = List::Util::first { -e "$_/$conf_file" } @conf_dirs; |
|
22
|
|
|
|
|
505
|
|
107
|
16
|
100
|
|
|
|
87
|
if ($dir) { |
108
|
14
|
|
|
|
|
117
|
TRACE "reading from config file $dir/$conf_file"; |
109
|
14
|
|
|
|
|
226
|
$filename = "$dir/$conf_file"; |
110
|
14
|
|
|
|
|
103
|
$class->pre_rendered( $filename ); |
111
|
14
|
|
|
|
|
110
|
my $rendered = $mt->render_file($filename); |
112
|
14
|
|
|
|
|
252
|
$class->rendered( $filename => $rendered ); |
113
|
14
|
50
|
|
|
|
56
|
die $rendered if ( (ref $rendered) =~ /Exception/ ); |
114
|
14
|
100
|
|
|
|
75
|
my $type = $rendered =~ /^---/ ? 'yaml' : 'json'; |
115
|
14
|
50
|
|
|
|
67
|
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
|
12
|
|
|
|
|
1113
|
? eval { YAML::XS::Load($rendered) } |
122
|
14
|
100
|
|
|
|
56
|
: eval { $json->decode($rendered) }; |
|
2
|
|
|
|
|
28
|
|
123
|
14
|
50
|
|
|
|
106
|
LOGDIE "Could not parse $type\n-------\n$rendered\n---------\n$@\n" if $@; |
124
|
|
|
|
|
|
|
} else { |
125
|
2
|
50
|
|
|
|
17
|
TRACE "could not find $conf_file file in: @conf_dirs" unless $dir; |
126
|
2
|
|
|
|
|
23
|
$conf_data = {}; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
} |
129
|
24
|
|
100
|
|
|
82
|
$conf_data ||= {}; |
130
|
24
|
|
|
|
|
192
|
Clustericious::Config::Helpers->_do_merges($conf_data); |
131
|
24
|
|
|
|
|
14306
|
_add_heuristics($filename,$conf_data); |
132
|
|
|
|
|
|
|
# Use derived classes so that AUTOLOADING keeps namespaces separate |
133
|
|
|
|
|
|
|
# for various apps. |
134
|
24
|
100
|
|
|
|
85
|
if ($class eq __PACKAGE__) { |
135
|
21
|
100
|
|
|
|
66
|
if (ref $arg) { |
136
|
5
|
|
|
|
|
15
|
$arg = "$arg"; |
137
|
5
|
|
|
|
|
15
|
$arg =~ tr/a-zA-Z0-9//cd; |
138
|
|
|
|
|
|
|
} |
139
|
21
|
|
|
|
|
72
|
$class = join '::', $class, 'App', $arg; |
140
|
21
|
100
|
|
|
|
129
|
$class .= $class_suffix->{$arg} if $class_suffix->{$arg}; |
141
|
21
|
|
|
|
|
86
|
my $dome = '@'."$class"."::ISA = ('".__PACKAGE__. "')"; |
142
|
21
|
|
|
|
|
1577
|
eval $dome; |
143
|
21
|
50
|
|
|
|
152
|
die "error setting ISA : $@" if $@; |
144
|
|
|
|
|
|
|
} |
145
|
24
|
|
|
|
|
413
|
bless $conf_data, $class; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub _add_heuristics { |
149
|
24
|
|
|
24
|
|
51
|
my $filename = shift; |
150
|
|
|
|
|
|
|
# Account for some mojo api changes |
151
|
24
|
|
|
|
|
58
|
my $conf_data = shift; |
152
|
24
|
50
|
33
|
|
|
159
|
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
|
48
|
|
|
48
|
|
11574
|
my $self = shift; |
176
|
48
|
|
|
|
|
98
|
my %args = @_; |
177
|
48
|
|
|
|
|
91
|
my $default = $args{default}; |
178
|
48
|
|
|
|
|
93
|
my $default_exists = exists $args{default}; |
179
|
48
|
|
|
|
|
61
|
our $AUTOLOAD; |
180
|
48
|
|
|
|
|
70
|
my $called = $AUTOLOAD; |
181
|
48
|
|
|
|
|
257
|
$called =~ s/.*:://g; |
182
|
48
|
100
|
66
|
|
|
190
|
if ($default_exists && !exists($self->{$called})) { |
183
|
4
|
|
|
|
|
14
|
$self->{$called} = $args{default}; |
184
|
|
|
|
|
|
|
} |
185
|
48
|
100
|
66
|
|
|
799
|
Carp::cluck "config element '$called' not found for ".(ref $self)." (".(join ',',keys(%$self)).")" |
186
|
|
|
|
|
|
|
if $called =~ /^_/ || !exists($self->{$called}); |
187
|
48
|
|
|
|
|
492
|
my $value = $self->{$called}; |
188
|
48
|
|
|
|
|
61
|
my $obj; |
189
|
48
|
|
|
|
|
80
|
my $invocant = ref $self; |
190
|
48
|
100
|
|
|
|
137
|
if (ref $value eq 'HASH') { |
191
|
3
|
|
|
|
|
23
|
$obj = $invocant->new($value); |
192
|
|
|
|
|
|
|
} |
193
|
14
|
|
|
14
|
|
113
|
no strict 'refs'; |
|
14
|
|
|
|
|
32
|
|
|
14
|
|
|
|
|
2547
|
|
194
|
48
|
|
|
|
|
254
|
*{ $invocant . "::$called" } = sub { |
195
|
67
|
|
|
67
|
|
98
|
my $self = shift; |
196
|
67
|
100
|
100
|
|
|
225
|
$self->{$called} = $default if $default_exists && !exists($self->{$called}); |
197
|
67
|
100
|
|
|
|
395
|
die "'$called' not found in ".join ',',keys(%$self) |
198
|
|
|
|
|
|
|
unless exists($self->{$called}); |
199
|
64
|
|
|
|
|
113
|
my $value = $self->{$called}; |
200
|
64
|
50
|
100
|
|
|
674
|
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
|
48
|
|
|
|
|
265
|
}; |
206
|
14
|
|
|
14
|
|
75
|
use strict 'refs'; |
|
14
|
|
|
|
|
30
|
|
|
14
|
|
|
|
|
1545
|
|
207
|
48
|
|
|
|
|
152
|
$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__ |