IO-Iron-Applications/lib/IO/Iron/Applications/Command/CommandBase.pm
package IO::Iron::Applications::Command::CommandBase;
## no critic (Documentation::RequirePodAtEnd)
## no critic (Documentation::RequirePodSections)
## no critic (RegularExpressions::RequireExtendedFormatting)
## no critic (RegularExpressions::RequireLineBoundaryMatching)
## no critic (RegularExpressions::ProhibitEscapedMetacharacters)
use 5.010_000;
use strict;
use warnings FATAL => 'all';
# Global creator
BEGIN {
# Export nothing.
}
# Global destructor
END {
}
# ABSTRACT: Internal base class for CLI commands.
our $VERSION = '0.12'; # VERSION: generated by DZP::OurPkgVersion
use Log::Any qw{$log};
require JSON::MaybeXS;
use Data::UUID ();
use Hash::Util 0.06 qw{lock_keys lock_keys_plus unlock_keys legal_keys};
use Carp::Assert;
use Carp::Assert::More;
use Carp;
use English '-no_match_vars';
use URI::Escape qw{uri_escape_utf8};
use Try::Tiny;
use Scalar::Util qw{blessed looks_like_number};
use Exception::Class (
'IronHTTPCallException' => {
fields => ['status_code', 'response_message'],
}
);
use IO::Iron::Common ();
use IO::Iron::Applications::IronCache::Functionality ();
use IO::Iron::Applications::IronCache::Templates ();
# CONSTANTS
use constant { ## no critic (ValuesAndExpressions::ProhibitConstantPragma)
HTTP_CODE_OK_MIN => 200,
HTTP_CODE_OK_MAX => 299,
HTTP_CODE_SERVICE_UNAVAILABLE => 503,
};
sub description {
return "Implemented in inheriting class.";
}
#sub abstract {
# return "Show an IronCache";
#}
sub usage_desc {
return "Implemented in inheriting class.";
}
sub opt_spec_base {
return (
[ "help", "This screen", { default => 0 } ],
[ "config|c=s", "Load Iron.io config from this file", ],
[ "policies=s", "Load policies from this file", ],
[ "no-policy", "Don't use policy to validate requests", { default => 0 }, ],
[ "warning|warn!", "Show warnings. Default: on. '--nowarn' to disable.", { default => 1 } ],
[ "verbose|info", "Give me information as things happen", { default => 0 } ],
[ "debug", "Give me more information as things happen", { default => 0 } ],
[ "trace", "Give me even more information as things happen", { default => 0 } ],
);
}
sub validate_args_base {
my ($self, $opt, $args) = @_;
# we need at least one argument beyond the options; die with that message
# and the complete "usage" text describing switches, etc
$self->usage_error("Help Requested") if defined $opt->{'help'} && $opt->{'help'};
}
sub validate_args {
my ($self, $opt, $args) = @_;
# we need at least one argument beyond the options; die with that message
# and the complete "usage" text describing switches, etc
return "Implemented in inheriting class.";
}
use Log::Log4perl;
use Log::Log4perl::Level;
my $conf = q(
log4perl.rootLogger = ERROR, Screen
log4perl.appender.Screen = Log::Log4perl::Appender::Screen
log4perl.appender.Screen.stderr = 0
log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout
);
Log::Log4perl::init( \$conf );
use Log::Any::Adapter;
Log::Any::Adapter->set('Log::Log4perl');
sub raise_logging_levels_from_options {
my ($self, $opts) = @_;
if($opts->{'warning'} > 0) {
Log::Log4perl->get_logger("")->level($WARN);
$log->info("Raised logging level to WARN.");
}
if($opts->{'verbose'} > 0) {
Log::Log4perl->get_logger("")->level($INFO);
$log->info("Raised logging level to INFO.");
}
if($opts->{'debug'} > 0) {
Log::Log4perl->get_logger("")->level($DEBUG);
$log->debug("Raised logging level to DEBUG.");
}
if($opts->{'trace'} > 0) {
Log::Log4perl->get_logger("")->level($TRACE);
$log->trace("Raised logging level to TRACE.");
}
return;
}
sub check_for_iron_io_config {
my ($self, $opts) = @_;
$log->tracef('Entering check_for_iron_io_config(%s)', $opts);
my %params;
$params{'config'} = $opts->{'config'} if defined $opts->{'config'};
my $config = IO::Iron::Common::get_config(%params);
if(! defined $config->{'project_id'}) {
$log->fatalf("Missing config item \'project_id\'. Please check that Iron.io config is accessible (by .json file or environmental variables).");
$log->tracef('Exiting check_for_iron_io_config():%d', -1);
return -1;
}
$log->tracef('Exiting check_for_iron_io_config():[NOT DEFINED]');
return
}
require Template;
$Template::Config::STASH = 'Template::Stash'; # Pure Perl implementation.
my %tt_config = (
#INCLUDE_PATH => '/search/path', # or list ref
#INTERPOLATE => 1, # expand "$var" in plain text
#POST_CHOMP => 1, # cleanup whitespace
#PRE_PROCESS => 'header', # prefix each template
#EVAL_PERL => 1, # evaluate Perl code blocks
# This is here to avoid the error "... used only once: possible typo ...":
dummy_use_for_config_stash => $Template::Config::STASH,
);
sub combine_template {
my ($self, $template_name, $data, $instructions) = @_;
$log->tracef('Entering combine_template(%s,%s)', $template_name, $data);
# Print with TT2
my $tt = Template->new(\%tt_config);
if(!$tt) {
croak(Template->error());
}
my $tt_output;
my $template_routine_name =
'IO::Iron::Applications::IronCache::Templates::'
. '_' . $template_name
. '_template';
$log->debugf('combine_template(): Fetching template from \'%s\'', $template_routine_name);
#my $tt_template = eval { $template_routine_name };
my $tt_template;
{
no strict 'refs';
$tt_template = &$template_routine_name();
}
$log->debugf('combine_template(): Found template:\'%s\'', $tt_template);
my %tt_input = (
'data' => $data,
'instructions' => $instructions,
);
if(! ($tt->process(\$tt_template, \%tt_input, \$tt_output))) {
$log->debug('\$template->error()=%s.\n', $tt->error());
croak($tt->error());
}
$log->tracef('Exiting combine_template():%s', $tt_output);
return $tt_output;
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
IO::Iron::Applications::Command::CommandBase - Internal base class for CLI commands.
=head1 VERSION
version 0.12
=head1 SYNOPSIS
This package is for internal use of IO::Iron packages.
=head1 DESCRIPTION
This class object handles the actual http traffic. Parameters are
passed from the calling object (partly from API class) via Connection
class object. This class can be mocked and replaced when
the client objects are created.
=head1 SUBROUTINES/METHODS
=head2 description
Describe the command.
=head2 abstract
This method returns a short description of the command's purpose.
If this method is not overridden, it will return the abstract
from the module's Pod. If it can't find the abstract, it will look
for a comment starting with "ABSTRACT:" like
the ones used by Pod::Weaver::Section::Name.
=head2 usage_desc
Describe usage of the command.
=head2 opt_spec_base
The options shared by all sub commands.
=head2 validate_args_base
Call this in the inheriting classes' validate_args method before any other validation.
=head2 validate_args
Validate the arguments (and options/flags) if required.
=head2 raise_logging_levels_from_options
Raise logging level according to specified options.
Available options: info, debug, trace.
=head2 check_for_iron_io_config
Check that config can be accessed.
=head2 combine_template
Find template (args[1]) and combine it with data in the referenced structure (args[2]).
=head1 AUTHOR
Mikko Koivunalho <mikko.koivunalho AT iki.fi>
=head1 BUGS
Please report any bugs or feature requests to bug-io-iron-applications@rt.cpan.org or through the web interface at:
http://rt.cpan.org/Public/Dist/Display.html?Name=IO-Iron-Applications
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2014 by Mikko Koivunalho.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
The full text of the license can be found in the
F<LICENSE> file included with this distribution.
=cut