File Coverage

blib/lib/Clustericious/App.pm
Criterion Covered Total %
statement 104 115 90.4
branch 15 22 68.1
condition 6 8 75.0
subroutine 25 27 92.5
pod 4 4 100.0
total 154 176 87.5


line stmt bran cond sub pod time code
1             package Clustericious::App;
2              
3 24     24   48387 use strict;
  24         58  
  24         747  
4 24     24   122 use warnings;
  24         227  
  24         591  
5 24     24   477 use 5.010;
  24         85  
6 24     24   133 use List::Util qw( first );
  24         115  
  24         1534  
7 24     24   1475 use MojoX::Log::Log4perl;
  24         101927  
  24         221  
8 24     24   2002 use Mojo::UserAgent;
  24         719392  
  24         194  
9 24     24   655 use Data::Dumper;
  24         50  
  24         1272  
10 24     24   1885 use Clustericious::Log;
  24         56  
  24         341  
11 24     24   16156 use Mojo::URL;
  24         68  
  24         199  
12 24     24   699 use Scalar::Util qw( weaken );
  24         59  
  24         1267  
13 24     24   143 use Mojo::Base 'Mojolicious';
  24         54  
  24         122  
14 24     24   725476 use File::Glob qw( bsd_glob );
  24         108  
  24         1494  
15 24     24   146 use File::Path qw( mkpath );
  24         57  
  24         1211  
16 24     24   146 use Carp qw( croak carp );
  24         54  
  24         1044  
17 24     24   133 use Clustericious;
  24         61  
  24         500  
18 24     24   1972 use Clustericious::Controller;
  24         57  
  24         204  
19 24     24   671 use Clustericious::Config;
  24         52  
  24         398  
20 24     24   1534 use Clustericious::Commands;
  24         61  
  24         194  
21 24     24   2468 use Path::Class::Dir;
  24         295014  
  24         21121  
22              
23             # ABSTRACT: Clustericious app base class
24             our $VERSION = '1.27'; # VERSION
25              
26              
27             has commands => sub {
28             my $commands = Clustericious::Commands->new(app => shift);
29             weaken $commands->{app};
30             return $commands;
31             };
32              
33              
34             sub startup {
35 30     30 1 196293 my $self = shift;
36              
37 30         182 $self->init_logging();
38 30         339 $self->plugins->namespaces(['Clustericious::Plugin','Mojolicious::Plugin']);
39 30         578 $self->controller_class('Clustericious::Controller');
40 30         284 $self->renderer->classes(['Clustericious::App']);
41              
42             # this is questionable
43 30         402 my $home = $self->home;
44 30         252 $self->renderer->paths([ Path::Class::Dir->new($home)->subdir('templates')->stringify ]);
45              
46 30         6250 $self->plugin('CommonRoutes');
47 30         6755 $self->plugin('AutodataHandler');
48 30         388 $self->plugin('ClustericiousHelpers');
49              
50 30         826 @{ $self->static->paths } = (
  30         5698  
51             Clustericious
52             ->_dist_dir
53             ->subdir(qw( www 1.08 ))
54             ->stringify
55             );
56              
57 30         458 my $config = $self->config;
58 30         63 my $auth_plugin;
59 30 100       344 if(my $auth_config = $config->plug_auth(default => '')) {
60 7         35 $self->log->info("Loading auth plugin plug_auth");
61 7         240 my $name = 'plug_auth';
62 7 100 66     53 if(ref($auth_config) && $auth_config->{plugin})
63 1         2 { $name = $auth_config->{plugin} }
64 7         37 $auth_plugin = $self->plugin($name, plug_auth => $auth_config);
65             } else {
66 23         108 $self->log->info("No auth configured");
67             }
68              
69 30 100       1566 $self->startup_route_builder($auth_plugin) if $self->can('startup_route_builder');
70              
71 30 50       1124 my $url = $config->url(default => '') or do {
72 0         0 $self->log->warn("Configuration file should contain 'url'.");
73             };
74              
75             $self->hook( before_dispatch => sub {
76 86   100 86   728920 Log::Log4perl::MDC->put(remote_ip => shift->tx->remote_address || 'unknown');
77 30         259 });
78              
79 30 50       606 if ( my $cors_allowed_origins = $config->cors_allowed_origins( default => '' ) ) {
80             $self->hook(
81             after_dispatch => sub {
82 0     0   0 my $c = shift;
83 0         0 $c->res->headers->add( 'Access-Control-Allow-Origin' => $cors_allowed_origins );
84 0         0 $c->res->headers->add( 'Access-Control-Allow-Headers' => 'Authorization' );
85             }
86 0         0 );
87             }
88              
89             }
90              
91              
92             sub init_logging {
93 30     30 1 68 my $self = shift;
94 30 50       123 croak "cannot be called as class method" unless ref $self;
95 30         249 my $logger = Clustericious::Log->init_logging($self);
96 30         524 $self->log( $logger );
97             }
98              
99              
100             sub _my_dist_data
101             {
102 28     28   741 my $dir = bsd_glob '~/.local/share/Perl/dist/Clustericious';
103 28         5453 mkpath $dir, 0, 0700;
104 28         170 $dir;
105             }
106              
107             sub config
108             {
109 126     126 1 21670 my($self, $what) = @_;
110              
111 126 100       487 unless($self->{_config})
112             {
113 30         68 my $config = $self->{_config} = eval { Clustericious::Config->new(ref $self) };
  30         255  
114 30 100       142 if(my $error = $@)
115             {
116 1         5 $self->log->error("error loading config $error");
117 1         38 $config = $self->{_config} = Clustericious::Config->new({ clustericious_config_error => $error });
118             }
119              
120 30   66     263 $config->{url} //= Clustericious->_default_url(ref $self);
121            
122 30 50       364 if(grep { $_ eq 'hypnotoad' } $config->start_mode(default => [ 'hypnotoad' ]) )
  30         153  
123             {
124             my $hypnotoad = $config->hypnotoad(
125             default => sub {
126 28     28   202 my $url = Mojo::URL->new($config->{url});
127             {
128 28         6520 pid_file => File::Spec->catfile( _my_dist_data(), 'hypnotoad-' . $url->port . '-' . $url->host . '.pid' ),
129             listen => [
130             $url->to_string,
131             ],
132             };
133             }
134 30         312 );
135             }
136             }
137              
138 126         308 my $config = $self->{_config};
139              
140             # Mojo uses $app->config('what');
141             # Clustericious usually uses $app->config->what;
142 126 50       861 $what ? $config->{$what} : $config;
143             }
144              
145              
146             sub sanity_check
147             {
148 0     0 1   my($self) = @_;
149 0           my $sane = 1;
150            
151 0 0         if(my $error = $self->config->clustericious_config_error(default => ''))
152             {
153 0           say "error loading configuration: $error";
154 0           $sane = 0;
155             }
156            
157 0           $sane;
158             }
159              
160             1;
161              
162             =pod
163              
164             =encoding UTF-8
165              
166             =head1 NAME
167              
168             Clustericious::App - Clustericious app base class
169              
170             =head1 VERSION
171              
172             version 1.27
173              
174             =head1 SYNOPSIS
175              
176             use Mojo::Base 'Clustericious::App';
177              
178             =head1 DESCRIPTION
179              
180             This class is the base class for all Clustericious applications. It
181             inherits everything from L<Mojolicious> and adds a few Clustericious
182             specific methods documented here.
183              
184             =head1 SUPER CLASS
185              
186             L<Mojolicious>
187              
188             =head1 ATTRIBUTES
189              
190             =head2 commands
191              
192             An instance of L<Clustericious::Commands> for use with this application.
193              
194             =head1 METHODS
195              
196             =head2 startup
197              
198             $app->startup;
199              
200             Adds the autodata_handler plugin, common routes,
201             and sets up logging for the client using log::log4perl.
202              
203             =head2 init_logging
204              
205             $app->init_logging;
206              
207             Initializing logging using ~/etc/log4perl.conf
208              
209             =head2 config
210              
211             my $config = $app->config;
212              
213             Returns the config (an instance of L<Clustericious::Config>) for the application.
214              
215             =head2 sanity_check
216              
217             my $ok = $app->sanity_check;
218              
219             This method is executed after C<startup>, but before the application
220             actually starts with the L<start|Clustericious::Command::start> command.
221             If it returns 1 then the configuration is considered sane and the
222             application will start. If it returns 0 then the configuration has
223             problems and start will be aborted with an appropriate message to the user
224             attempting start.
225              
226             By default this just checks that the application's configuration file
227             (usually located in ~/etc/MyApp.conf) is correctly formatted as either
228             YAML or JSON.
229              
230             You can override this in your application, but don't forget to call
231             the base class's version of sanity_check before making your own checks.
232              
233             =head1 SEE ALSO
234              
235             L<Clustericious>
236              
237             =head1 AUTHOR
238              
239             Original author: Brian Duggan
240              
241             Current maintainer: Graham Ollis E<lt>plicease@cpan.orgE<gt>
242              
243             Contributors:
244              
245             Curt Tilmes
246              
247             Yanick Champoux
248              
249             =head1 COPYRIGHT AND LICENSE
250              
251             This software is copyright (c) 2013 by NASA GSFC.
252              
253             This is free software; you can redistribute it and/or modify it under
254             the same terms as the Perl 5 programming language system itself.
255              
256             =cut
257              
258             __DATA__
259              
260             @@ not_found.html.ep
261             NOT FOUND: "<%= $self->req->url->path || '/' %>"
262              
263             @@ not_found.development.html.ep
264             NOT FOUND: "<%= $self->req->url->path || '/' %>"
265              
266             @@ layouts/default.html.ep
267             <!doctype html><html>
268             <head><title>Welcome</title></head>
269             <body><%== content %></body>
270             </html>
271              
272             @@ exception.html.ep
273             % my $s = $self->stash;
274             % my $e = $self->stash('exception');
275             % delete $s->{inner_template};
276             % delete $s->{exception};
277             % my $dump = dumper $s;
278             % $s->{exception} = $e;
279             % use Mojo::ByteStream qw/b/;
280             ERROR: <%= b($e); %>
281