line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package IO::Iron::Common; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
## no critic (Documentation::RequirePodAtEnd) |
4
|
|
|
|
|
|
|
## no critic (Documentation::RequirePodSections) |
5
|
|
|
|
|
|
|
## no critic (Subroutines::RequireArgUnpacking) |
6
|
|
|
|
|
|
|
|
7
|
8
|
|
|
8
|
|
744
|
use 5.010_000; |
|
8
|
|
|
|
|
25
|
|
8
|
8
|
|
|
8
|
|
59
|
use strict; |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
162
|
|
9
|
8
|
|
|
8
|
|
35
|
use warnings; |
|
8
|
|
|
|
|
22
|
|
|
8
|
|
|
|
|
199
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# Global creator |
12
|
|
|
|
8
|
|
|
BEGIN { |
13
|
|
|
|
|
|
|
# No exports |
14
|
|
|
|
|
|
|
} |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# Global destructor |
17
|
|
|
|
8
|
|
|
END { |
18
|
|
|
|
|
|
|
} |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# ABSTRACT: Common routines for Client Libraries to Iron services IronCache, IronMQ and IronWorker. |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
our $VERSION = '0.14'; # VERSION: generated by DZP::OurPkgVersion |
23
|
|
|
|
|
|
|
|
24
|
8
|
|
|
8
|
|
7560
|
use Path::Tiny qw{path}; |
|
8
|
|
|
|
|
108670
|
|
|
8
|
|
|
|
|
510
|
|
25
|
8
|
|
|
8
|
|
606
|
use Try::Tiny; |
|
8
|
|
|
|
|
2069
|
|
|
8
|
|
|
|
|
427
|
|
26
|
8
|
|
|
8
|
|
563
|
use Log::Any qw{$log}; |
|
8
|
|
|
|
|
8470
|
|
|
8
|
|
|
|
|
66
|
|
27
|
|
|
|
|
|
|
require JSON::MaybeXS; |
28
|
8
|
|
|
8
|
|
4169
|
use File::Spec (); |
|
8
|
|
|
|
|
19
|
|
|
8
|
|
|
|
|
111
|
|
29
|
8
|
|
|
8
|
|
3487
|
use File::HomeDir (); |
|
8
|
|
|
|
|
35056
|
|
|
8
|
|
|
|
|
271
|
|
30
|
8
|
|
|
8
|
|
623
|
use Hash::Util 0.06 qw{lock_keys unlock_keys}; |
|
8
|
|
|
|
|
3084
|
|
|
8
|
|
|
|
|
61
|
|
31
|
8
|
|
|
8
|
|
1202
|
use Carp::Assert::More; |
|
8
|
|
|
|
|
5076
|
|
|
8
|
|
|
|
|
1545
|
|
32
|
8
|
|
|
8
|
|
596
|
use English '-no_match_vars'; |
|
8
|
|
|
|
|
1807
|
|
|
8
|
|
|
|
|
67
|
|
33
|
8
|
|
|
8
|
|
3753
|
use Params::Validate qw(:all); |
|
8
|
|
|
|
|
7156
|
|
|
8
|
|
|
|
|
8027
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub IRON_CONFIG_KEYS { |
36
|
|
|
|
|
|
|
return ( |
37
|
|
|
|
|
|
|
# Iron.io standard: |
38
|
12
|
|
|
12
|
1
|
59
|
'project_id', # The ID of the project to use for requests. |
39
|
|
|
|
|
|
|
'token', # The OAuth token that should be used to authenticate requests. Can be found in the HUD. |
40
|
|
|
|
|
|
|
'host', # The domain name the API can be located at. Defaults to a product-specific value, but always using Amazon's cloud. |
41
|
|
|
|
|
|
|
'protocol' |
42
|
|
|
|
|
|
|
, # The protocol that will be used to communicate with the API. Defaults to "https", which should be sufficient for 99% of users. |
43
|
|
|
|
|
|
|
'port', # The port to connect to the API through. Defaults to 443, which should be sufficient for 99% of users. |
44
|
|
|
|
|
|
|
'api_version' |
45
|
|
|
|
|
|
|
, # The version of the API to connect through. Defaults to the version supported by the client. End-users should probably never change this. Except: IronMQ service upgraded from v2 to v3 in 2015! |
46
|
|
|
|
|
|
|
# IO::Iron additions: |
47
|
|
|
|
|
|
|
'timeout' |
48
|
|
|
|
|
|
|
, # REST client timeout (for REST calls accessing IronMQ). N.B. This is not a IronMQ config option! It only configures client this client. |
49
|
|
|
|
|
|
|
'policies', # Filename of JSON file containing policies. |
50
|
|
|
|
|
|
|
); |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub IRON_CLIENT_PARAMETERS { |
54
|
|
|
|
|
|
|
return ( |
55
|
3
|
|
|
3
|
1
|
10
|
IRON_CONFIG_KEYS(), |
56
|
|
|
|
|
|
|
'config', # The config file name. |
57
|
|
|
|
|
|
|
'connector', # Reference to a preinitiated connector object. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# 'policy', # Reference to a preinitiated policy hash. |
60
|
|
|
|
|
|
|
); |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub get_config { ## no critic (Subroutines::RequireArgUnpacking) |
64
|
|
|
|
|
|
|
my %params = validate( |
65
|
|
|
|
|
|
|
@_, |
66
|
|
|
|
|
|
|
{ |
67
|
3
|
|
|
3
|
1
|
19
|
map { $_ => { type => SCALAR, optional => 1 }, } IRON_CONFIG_KEYS(), ## no critic (ValuesAndExpressions::ProhibitCommaSeparatedStatements) |
|
30
|
|
|
|
|
168
|
|
68
|
|
|
|
|
|
|
'config' => { type => SCALAR, optional => 1, }, |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
); |
71
|
3
|
|
|
|
|
35
|
$log->tracef( 'Entering get_config(%s)', \%params ); |
72
|
3
|
|
|
|
|
505
|
my %config = ( map { $_ => undef } IRON_CONFIG_KEYS() ); ## preset config keys. |
|
24
|
|
|
|
|
82
|
|
73
|
3
|
|
|
|
|
11
|
lock_keys( %config, IRON_CONFIG_KEYS() ); |
74
|
3
|
|
|
|
|
315
|
_read_iron_config_file( \%config, File::Spec->catfile( File::HomeDir->my_home, '.iron.json' ) ); # Homedir |
75
|
3
|
|
|
|
|
26
|
_read_iron_config_env_vars( \%config ); # Global envs |
76
|
3
|
|
|
|
|
68
|
_read_iron_config_file( \%config, File::Spec->catfile( File::Spec->curdir(), 'iron.json' ) ); # current dir |
77
|
3
|
100
|
|
|
|
15
|
if ( defined $params{'config'} ) { # config file specified when creating the class, if given. |
78
|
|
|
|
|
|
|
_read_iron_config_file( \%config, |
79
|
|
|
|
|
|
|
File::Spec->file_name_is_absolute( $params{'config'} ) |
80
|
|
|
|
|
|
|
? $params{'config'} |
81
|
1
|
50
|
|
|
|
20
|
: File::Spec->catfile( File::Spec->curdir(), $params{'config'} ) ); |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# The parameters given when the object was created, except 'config' |
85
|
3
|
|
|
|
|
10
|
my @copy_param_keys = grep { !/^config$/msx } keys %params; |
|
5
|
|
|
|
|
20
|
|
86
|
3
|
|
|
|
|
11
|
@config{@copy_param_keys} = @params{@copy_param_keys}; |
87
|
|
|
|
|
|
|
|
88
|
3
|
|
|
|
|
12
|
$log->tracef( 'Exiting get_config: %s', \%config ); |
89
|
3
|
|
|
|
|
532
|
return \%config; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# Replace the existing values in $config if new environment variables found. |
93
|
|
|
|
|
|
|
# Vars: |
94
|
|
|
|
|
|
|
# $config->{'project_id'} = $ENV{'IRON_PROJECT_ID'} |
95
|
|
|
|
|
|
|
# $config->{'token'} = $ENV{'IRON_TOKEN'} |
96
|
|
|
|
|
|
|
# $config->{'host'} = $ENV{'IRON_HOST'} |
97
|
|
|
|
|
|
|
# $config->{'protocol'} = $ENV{'IRON_PROTOCOL'} |
98
|
|
|
|
|
|
|
# $config->{'port'} = $ENV{'IRON_PORT'} |
99
|
|
|
|
|
|
|
# $config->{'api_version'} = $ENV{'IRON_API_VERSION'} |
100
|
|
|
|
|
|
|
# $config->{'timeout'} = $ENV{'IRON_TIMEOUT'} |
101
|
|
|
|
|
|
|
sub _read_iron_config_env_vars { |
102
|
3
|
|
|
3
|
|
8
|
my ($config) = @_; |
103
|
3
|
|
|
|
|
10
|
$log->tracef( 'Entering _read_iron_config_env_vars(%s)', $config ); |
104
|
3
|
|
|
|
|
489
|
foreach my $config_key ( keys %{$config} ) { |
|
3
|
|
|
|
|
13
|
|
105
|
24
|
100
|
|
|
|
81
|
if ( defined $ENV{ 'IRON_' . uc $config_key } ) { |
106
|
6
|
|
|
|
|
12
|
$config->{$config_key} = $ENV{ 'IRON_' . uc $config_key }; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
} |
109
|
3
|
|
|
|
|
13
|
$log->tracef( 'Exiting _read_iron_config_env_vars: %s', $config ); |
110
|
3
|
|
|
|
|
466
|
return $config; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# Try to read the file given as second parameter. (if undef, fail). |
114
|
|
|
|
|
|
|
# If fails, gracefully return 0; if succeed, change configuration (first parameter) and return 1. |
115
|
|
|
|
|
|
|
sub _read_iron_config_file { |
116
|
7
|
|
|
7
|
|
195
|
my ( $config, $full_path_name ) = @_; |
117
|
7
|
|
|
|
|
27
|
$log->tracef( 'Entering _read_iron_config_file(%s, %s)', $full_path_name, $config ); |
118
|
|
|
|
|
|
|
|
119
|
7
|
|
|
|
|
1149
|
assert_nonblank( $full_path_name, 'full_path_name is not defined or is blank.' ); |
120
|
|
|
|
|
|
|
|
121
|
7
|
|
|
|
|
84
|
my $read_config; |
122
|
|
|
|
|
|
|
my $rval; |
123
|
7
|
|
|
|
|
25
|
my $file = path($full_path_name); |
124
|
7
|
100
|
|
|
|
315
|
if ( $file->is_file ) { |
125
|
2
|
|
|
|
|
46
|
$log->tracef( 'File %s exists', $full_path_name ); |
126
|
2
|
|
|
|
|
6
|
my $file_contents; |
127
|
2
|
|
|
2
|
|
13
|
try { $file_contents = $file->slurp_utf8 }; |
|
2
|
|
|
|
|
57
|
|
128
|
2
|
50
|
|
|
|
1556
|
if ($file_contents) { |
129
|
2
|
|
|
|
|
9
|
$log->tracef( 'Slurped file %s', $full_path_name ); |
130
|
2
|
|
|
|
|
29
|
my $json = JSON::MaybeXS->new( utf8 => 1, pretty => 1 ); |
131
|
2
|
|
|
|
|
54
|
$read_config = $json->decode($file_contents); |
132
|
2
|
|
|
|
|
4
|
foreach my $config_key ( keys %{$config} ) { |
|
2
|
|
|
|
|
7
|
|
133
|
16
|
100
|
|
|
|
35
|
if ( defined $read_config->{$config_key} ) { |
134
|
8
|
|
|
|
|
19
|
$config->{$config_key} = $read_config->{$config_key}; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
} |
137
|
2
|
|
|
|
|
14
|
$rval = 1; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
else { |
140
|
0
|
|
|
|
|
0
|
$log->debugf( 'Could not read file %s', $full_path_name ); |
141
|
0
|
|
|
|
|
0
|
$rval = 0; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
else { |
145
|
5
|
|
|
|
|
235
|
$log->tracef( 'File %s does not exist', $full_path_name ); |
146
|
5
|
|
|
|
|
326
|
$rval = 0; |
147
|
|
|
|
|
|
|
} |
148
|
7
|
|
|
|
|
28
|
$log->tracef( 'Exiting _read_iron_config_file: %s', $config ); |
149
|
7
|
|
|
|
|
1042
|
return $rval; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
#my $GEN_DELIMS = q{!} . q{$} . q{&} . q{'} . q{(} . q{)} |
153
|
|
|
|
|
|
|
# . q{*} . q{+} . q{,} . q{;} . q{=}; |
154
|
|
|
|
|
|
|
#my $SUB_DELIMS = q{:} . q{/} . q{?} . q{#} . q{[} . q{]} . q{@}; |
155
|
|
|
|
|
|
|
#my $RESERVED_CHARACTERS = $GEN_DELIMS . $SUB_DELIMS; |
156
|
|
|
|
|
|
|
#my $RFC_3986_RESERVED_CHARACTERS =~ s/(.{1})/\\$1/sg; # Escape every character. |
157
|
|
|
|
|
|
|
sub contains_rfc_3986_res_chars { |
158
|
11
|
|
|
11
|
1
|
1217
|
my @params = validate_pos( @_, { type => SCALAR } ); |
159
|
|
|
|
|
|
|
## no critic (ValuesAndExpressions::RequireInterpolationOfMetachars) |
160
|
11
|
|
|
|
|
39
|
my $rfc_3986_reserved_characters = q{\!\$\&\'\(\)\*\+\,\;\=\:\/\?\#\[\]\@}; |
161
|
|
|
|
|
|
|
## critic (ValuesAndExpressions::RequireInterpolationOfMetachars) |
162
|
11
|
100
|
|
|
|
177
|
return ( $params[0] =~ m/[$rfc_3986_reserved_characters]{1,}/msx ) ? 1 : 0; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
1; |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
__END__ |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=pod |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=encoding UTF-8 |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=head1 NAME |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
IO::Iron::Common - Common routines for Client Libraries to Iron services IronCache, IronMQ and IronWorker. |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head1 VERSION |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
version 0.14 |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=for stopwords IronCache IronMQ IronWorker config json Mikko Koivunalho |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=head1 REQUIREMENTS |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=head1 FUNCTIONS |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
Internal functions for use in the Client objects. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=head2 IRON_CONFIG_KEYS |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head2 IRON_CLIENT_PARAMETERS |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=head2 get_config |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
Get the config from file or from system environmental variables. |
196
|
|
|
|
|
|
|
Follows the global configuration scheme as explained in http://dev.iron.io/mq/reference/configuration/. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
The configuration is constructed as follows: |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=over 8 |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=item 1. The global configuration file sets the defaults according to the file hierarchy. (F<.iron.json> in home folder) |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=item 2. The global environment variables overwrite the global configuration file's values. |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=item 3. The product-specific environment variables overwrite everything before them. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=item 4. The local configuration file overwrites everything before it according to the file hierarchy. (F<iron.json> in the same directory as the script being run) |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=item 5. The configuration file specified when instantiating the client library overwrites everything before it according to the file hierarchy. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=item 6. The arguments passed when instantiating the client library overwrite everything before them. |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=back |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Return: ref to %config. |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=head2 contains_rfc_3986_res_chars |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Check that the string does not contain any RFC 3986 Reserved Characters: |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
!$&'()*+,;=:/?#[]@ |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
Return True (1) if contains. Otherwise False (0). |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=head1 AUTHOR |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
Mikko Koivunalho <mikko.koivunalho@iki.fi> |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=head1 BUGS |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
Please report any bugs or feature requests to bug-io-iron@rt.cpan.org or through the web interface at: |
233
|
|
|
|
|
|
|
http://rt.cpan.org/Public/Dist/Display.html?Name=IO-Iron |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
This software is copyright (c) 2023 by Mikko Koivunalho. |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
240
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
The full text of the license can be found in the |
243
|
|
|
|
|
|
|
F<LICENSE> file included with this distribution. |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=cut |