File Coverage

blib/lib/AWS/CLI/Config.pm
Criterion Covered Total %
statement 80 90 88.8
branch 21 30 70.0
condition 21 51 41.1
subroutine 20 23 86.9
pod 2 2 100.0
total 144 196 73.4


line stmt bran cond sub pod time code
1             package AWS::CLI::Config;
2 5     5   78104 use 5.008001;
  5         20  
3 5     5   28 use strict;
  5         25  
  5         104  
4 5     5   27 use warnings;
  5         12  
  5         144  
5              
6 5     5   22 use Carp ();
  5         10  
  5         68  
7 5     5   21 use File::Spec;
  5         8  
  5         112  
8 5     5   1954 use autodie;
  5         60430  
  5         27  
9              
10             our $VERSION = "0.04";
11              
12             my $DEFAULT_PROFILE = 'default';
13              
14             my $CREDENTIALS;
15             my %CREDENTIALS_PROFILE_OF;
16             my $CONFIG;
17             my %CONFIG_PROFILE_OF;
18              
19             BEGIN: {
20             my %accessor_of = (
21             access_key_id => +{ env => 'AWS_ACCESS_KEY_ID', key => 'aws_access_key_id' },
22             secret_access_key => +{ env => 'AWS_SECRET_ACCESS_KEY', key => 'aws_secret_access_key' },
23             session_token => +{ env => 'AWS_SESSION_TOKEN', key => 'aws_session_token' },
24             region => +{ env => 'AWS_DEFAULT_REGION' },
25             output => +{},
26             );
27              
28             MK_ACCESSOR: {
29 5     5   34438 no strict 'refs';
  5         13  
  5         4023  
30             for my $attr (keys %accessor_of) {
31             my $func = __PACKAGE__ . "::$attr";
32             *{$func} = _mk_accessor($attr, %{$accessor_of{$attr}});
33             }
34             }
35             }
36              
37             sub _mk_accessor {
38 25     25   38 my $attr = shift;
39 25         94 my %opt = @_;
40              
41 25         42 my $env_var = $opt{env};
42 25   66     83 my $profile_key = $opt{key} || $attr;
43              
44             return sub {
45 5 100 66 5   6434 if ($env_var && exists $ENV{$env_var} && $ENV{$env_var}) {
      33        
46 1         7 return $ENV{$env_var};
47             }
48              
49 4   33     22 my $profile = shift || _default_profile();
50              
51 4         14 my $credentials = credentials($profile);
52 4 100 66     87 if ($credentials && $credentials->$profile_key) {
53 2         45 return $credentials->$profile_key;
54             }
55              
56 2         7 my $config = config($profile);
57 2 50 33     50 if ($config && $config->$profile_key) {
58 2         43 return $config->$profile_key;
59             }
60              
61 0         0 return undef;
62 25         84 };
63             }
64              
65             sub credentials {
66 0   0 0 1 0 my $profile = shift || _default_profile();
67             $CREDENTIALS ||= sub {
68 0     0   0 my $path = File::Spec->catfile(_default_dir(), 'credentials');
69 0 0       0 return +{} unless (-r $path);
70 0         0 return _parse($path);
71 0   0     0 }->();
72 0 0       0 return unless (exists $CREDENTIALS->{$profile});
73 0   0     0 $CREDENTIALS_PROFILE_OF{$profile} ||= AWS::CLI::Config::Profile->_new($CREDENTIALS->{$profile});
74 0         0 return $CREDENTIALS_PROFILE_OF{$profile};
75             }
76              
77             sub config {
78 3   66 3 1 7811 my $profile = shift || _default_profile();
79              
80             $CONFIG ||= sub {
81             my $path
82             = (exists $ENV{AWS_CONFIG_FILE} && $ENV{AWS_CONFIG_FILE})
83             ? $ENV{AWS_CONFIG_FILE}
84 1 50 33 1   7 : File::Spec->catfile(_default_dir(), 'config');
85 1 50       17 return +{} unless (-r $path);
86              
87 1         14 return _parse($path);
88 3   66     16 }->();
89              
90 3 100       14 return unless (exists $CONFIG->{$profile});
91 2   33     15 $CONFIG_PROFILE_OF{$profile} ||= AWS::CLI::Config::Profile->_new($CONFIG->{$profile});
92 2         7 return $CONFIG_PROFILE_OF{$profile};
93             }
94              
95             sub _base_dir {
96 2 100   2   2394 ($^O eq 'MSWin32') ? $ENV{USERPROFILE} : $ENV{HOME};
97             }
98              
99             sub _default_dir {
100 0     0   0 File::Spec->catdir(_base_dir(), '.aws');
101             }
102              
103             sub _default_profile {
104             (exists $ENV{AWS_DEFAULT_PROFILE} && $ENV{AWS_DEFAULT_PROFILE})
105             ? $ENV{AWS_DEFAULT_PROFILE}
106 6 50 33 6   46 : $DEFAULT_PROFILE;
107             }
108              
109             sub _parse {
110 1     1   16 my $file = shift;
111 1   33     7 my $profile = shift || _default_profile();
112              
113 1         3 my $hash = {};
114 1         3 my $nested = {};
115              
116 1         1 my $contents;
117             {
118 1         2 local $/ = undef;
  1         5  
119 1         6 open my $fh, '<', $file;
120 1         2687 $contents = <$fh>;
121 1         5 close( $fh );
122             }
123              
124 1         741 foreach my $line (split /\n/, $contents) {
125 8         15 chomp $line;
126              
127 8 100       27 $profile = $1 if $line =~ /^\[(?:profile )?([\w]+)\]/;
128 8         29 my ($indent, $key, $value) = $line =~ /^(\s*)([\w]+)\s*=\s*(.*)/;
129              
130 8 100 66     34 next if !defined $key or $key eq q{};
131              
132 6 100       15 if (length $indent) {
133 1         4 $nested->{$key} = $value;
134             }
135             else {
136             # Reset nested hash
137 5 50       8 $nested = {} if keys %{$nested};
  5         13  
138 5 100 66     25 $hash->{$profile}{$key} = ($key and $value) ? $value : $nested;
139             }
140             }
141              
142 1         5 return $hash;
143             }
144              
145             PROFILE: {
146             package AWS::CLI::Config::Profile;
147 5     5   116 use 5.008001;
  5         35  
148 5     5   29 use strict;
  5         11  
  5         122  
149 5     5   68 use warnings;
  5         22  
  5         286  
150              
151             my @ACCESSORS;
152              
153             BEGIN {
154 5     5   121 @ACCESSORS = qw(
155             aws_access_key_id
156             aws_secret_access_key
157             aws_session_token
158             region
159             output
160             );
161             }
162              
163 5     5   2495 use Object::Tiny @ACCESSORS;
  5         1367  
  5         31  
164              
165             sub _new {
166 6     6   44 my $class = shift;
167 6         21 my $data = shift;
168 6         24 return bless $data, $class;
169             }
170             }
171              
172             1;
173             __END__