view release on metacpan or search on metacpan
1.25 2017-07-10
- resolved https://github.com/lucastheisen/footprintless/issues/4 get_entity fails if value is falsey
1.24 2017-03-16
- resolved https://github.com/lucastheisen/footprintless/issues/3 Add support for one action to be applied to multiple services in one call
1.23 2016-12-16
- fixed multi-template support for resource based overlay
1.22 2016-12-16
- added resource based overlay support
1.21 2016-11-18
- added sorting to config dumper and changed json default to json3
1.20 2016-10-21
- added support for resource manager provider configuration
1.19 2016-10-20
- added support for clean in .footprintless placeholders for overlay update
1.18 2016-10-12
- resolved https://rt.cpan.org/Ticket/Display.html?id=118019 Can't redeclare "my" in "my"
- resolved https://rt.cpan.org/Ticket/Display.html?id=118162 Using File::Temp::HIGH() is problematic
- resolved https://rt.cpan.org/Ticket/Display.html?id=114358 Fails with perls < 5.14
1.17 2016-10-05
- fixed bug causing footprintless to get initialized 3 times
- added ActionCommand and Action to cut down on boilerplate
- added MixableBase to cut down on boilerplate initialization
- added configurable tries and wait_seconds for tunnel startup
- modified tunnel init to allow options to override entity for config
1.10 2016-08-20
- added Footprintless::Extract implementation
1.09 2016-08-19
- added support for extract_to in resources for Deployment
- fixed overlay to use dot footprintless resolver on update as well as initialize
- added prefix to temp_[dir/file] to provide easier cleanup in case process exits abnormally
1.08 2016-08-18
- changed Footprintless::agent from a singleton to a factory
1.07 2016-08-17
- fixed deployment extra to supply actual to_dir even if there is a resource_dir
1.06 2016-08-02
- added documentation for deploy option 'extra'
- cleaned up dumper
- added pod documentation to tunnel
1.04 2016-07-21
- added ability to pass runner options to service
- fixed logger message in Footprintless::_init
- fixed Footprintless_App_Command_log logger to use STDERR to avoid STDOUT conflicts
- fixed out_handle for until to print a newline after each line
- modified temp_dir and added temp_file both of which are now secure, reimplemented service status to better handle su
- added missing dependency on URI
- added resolution during overlay if .footprintless is encountered
- updated service to support sub commands with sudo if needed
- updated pod for Footprintless::Util::slurp
- fixed invalid variable reference in Footprintless::Util::exit_due_to, and added support for STDIN in Footprintless::
- added Tunnel.pm and associated factory methods
- updated tests to included --no-overwrite-dir for the cp_command tar
- added --no-overwrite-dir to the cp_command tar to avoid needing permissions on folders we are not adding to/deleting
1.03 2016-04-30
- Fixed Bug #113348 for Footprintless: Undeclared dependency App::Cmd::Tester
docs/Footprintless-App-Command-config.html
docs/Footprintless-App-Command-deployment-clean.html
docs/Footprintless-App-Command-deployment-deploy.html
docs/Footprintless-App-Command-deployment.html
docs/Footprintless-App-Command-log-cat.html
docs/Footprintless-App-Command-log-follow.html
docs/Footprintless-App-Command-log-grep.html
docs/Footprintless-App-Command-log-head.html
docs/Footprintless-App-Command-log-tail.html
docs/Footprintless-App-Command-log.html
docs/Footprintless-App-Command-overlay-clean.html
docs/Footprintless-App-Command-overlay-initialize.html
docs/Footprintless-App-Command-overlay-update.html
docs/Footprintless-App-Command-overlay.html
docs/Footprintless-App-Command-service.html
docs/Footprintless-App-DocumentationUtil.html
docs/Footprintless-App-UsageException.html
docs/Footprintless-App.html
docs/Footprintless-Command.html
docs/Footprintless-CommandOptionsFactory.html
docs/Footprintless-CommandRunner-ExecutionException.html
docs/Footprintless-CommandRunner-IPCRun.html
docs/Footprintless-CommandRunner-IPCRun3.html
docs/Footprintless-CommandRunner.html
lib/Footprintless/App/Command/config.pm
lib/Footprintless/App/Command/deployment.pm
lib/Footprintless/App/Command/deployment/clean.pm
lib/Footprintless/App/Command/deployment/deploy.pm
lib/Footprintless/App/Command/log.pm
lib/Footprintless/App/Command/log/cat.pm
lib/Footprintless/App/Command/log/follow.pm
lib/Footprintless/App/Command/log/grep.pm
lib/Footprintless/App/Command/log/head.pm
lib/Footprintless/App/Command/log/tail.pm
lib/Footprintless/App/Command/overlay.pm
lib/Footprintless/App/Command/overlay/clean.pm
lib/Footprintless/App/Command/overlay/initialize.pm
lib/Footprintless/App/Command/overlay/update.pm
lib/Footprintless/App/Command/service.pm
lib/Footprintless/App/DocumentationUtil.pm
lib/Footprintless/App/UsageException.pm
lib/Footprintless/Command.pm
lib/Footprintless/CommandOptionsFactory.pm
lib/Footprintless/CommandRunner.pm
lib/Footprintless/CommandRunner/ExecutionException.pm
lib/Footprintless/CommandRunner/IPCRun.pm
lib/Footprintless/CommandRunner/IPCRun3.pm
lib/Footprintless/Deployment.pm
lib/Footprintless/ResourceManager.pm
lib/Footprintless/Service.pm
lib/Footprintless/Tunnel.pm
lib/Footprintless/Util.pm
t/00-report-prereqs.dd
t/00-report-prereqs.t
t/Footprintless.t
t/Footprintless_App_Command_config.t
t/Footprintless_App_Command_deploy.t
t/Footprintless_App_Command_log.t
t/Footprintless_App_Command_overlay.t
t/Footprintless_App_Command_service.t
t/Footprintless_Command.t
t/Footprintless_CommandOptionsFactory.t
t/Footprintless_CommandRunner.t
t/Footprintless_Deployment.t
t/Footprintless_Extract.t
t/Footprintless_Localhost.t
t/Footprintless_Log.t
t/Footprintless_Overlay.t
t/Footprintless_Plugin.t
t/data/maven/HOME/dot_m2/settings.xml
t/data/resources/bar.tar
t/data/resources/bar.tgz
t/data/resources/bar.war
t/data/resources/bar/META-INF/MANIFEST.MF
t/data/resources/bar/META-INF/maven/com.pastdev/bar/pom.properties
t/data/resources/bar/META-INF/maven/com.pastdev/bar/pom.xml
t/data/resources/bar/WEB-INF/web.xml
t/data/resources/bar/index.html
t/data/resources/baz.war
t/data/resources/overlay.zip
t/data/resources/overlay/base/foo.txt
t/data/resources/overlay/template/first/bar.txt
t/data/resources/overlay/template/first/baz.txt
t/data/resources/overlay/template/second/bar.txt
t/data/template/bin/catalina.sh
t/data/template/bin/setenv.sh
t/data/template/conf/jndi-resources.xml
t/data/template/conf/server.xml
t/lib/Footprintless/CommandRunner/Echo.pm
t/lib/Footprintless/CommandRunner/Mock.pm
t/lib/Footprintless/EchoCommandRunnerTestFactory.pm
t/lib/Footprintless/ExtendedTestFactory.pm
t/lib/Footprintless/Test/Echo.pm
t/lib/Footprintless/Test/EchoPlugin.pm
"version" : "1.29"
},
"Footprintless::App::Command::log::head" : {
"file" : "lib/Footprintless/App/Command/log/head.pm",
"version" : "1.29"
},
"Footprintless::App::Command::log::tail" : {
"file" : "lib/Footprintless/App/Command/log/tail.pm",
"version" : "1.29"
},
"Footprintless::App::Command::overlay" : {
"file" : "lib/Footprintless/App/Command/overlay.pm",
"version" : "1.29"
},
"Footprintless::App::Command::overlay::clean" : {
"file" : "lib/Footprintless/App/Command/overlay/clean.pm",
"version" : "1.29"
},
"Footprintless::App::Command::overlay::initialize" : {
"file" : "lib/Footprintless/App/Command/overlay/initialize.pm",
"version" : "1.29"
},
"Footprintless::App::Command::overlay::update" : {
"file" : "lib/Footprintless/App/Command/overlay/update.pm",
"version" : "1.29"
},
"Footprintless::App::Command::service" : {
"file" : "lib/Footprintless/App/Command/service.pm",
"version" : "1.29"
},
"Footprintless::App::DocumentationUtil" : {
"file" : "lib/Footprintless/App/DocumentationUtil.pm",
"version" : "1.29"
},
version: '1.29'
Footprintless::App::Command::log::grep:
file: lib/Footprintless/App/Command/log/grep.pm
version: '1.29'
Footprintless::App::Command::log::head:
file: lib/Footprintless/App/Command/log/head.pm
version: '1.29'
Footprintless::App::Command::log::tail:
file: lib/Footprintless/App/Command/log/tail.pm
version: '1.29'
Footprintless::App::Command::overlay:
file: lib/Footprintless/App/Command/overlay.pm
version: '1.29'
Footprintless::App::Command::overlay::clean:
file: lib/Footprintless/App/Command/overlay/clean.pm
version: '1.29'
Footprintless::App::Command::overlay::initialize:
file: lib/Footprintless/App/Command/overlay/initialize.pm
version: '1.29'
Footprintless::App::Command::overlay::update:
file: lib/Footprintless/App/Command/overlay/update.pm
version: '1.29'
Footprintless::App::Command::service:
file: lib/Footprintless/App/Command/service.pm
version: '1.29'
Footprintless::App::DocumentationUtil:
file: lib/Footprintless/App/DocumentationUtil.pm
version: '1.29'
Footprintless::App::UsageException:
file: lib/Footprintless/App/UsageException.pm
version: '1.29'
version 1.29
SYNOPSIS
use Footprintless;
my $footprintless = Footprintless->new();
# Deploy initialize, start, and follow the log of the foo
$footprintless->overlay('dev.foo.overlay')->initialize();
$footprintless->service('dev.foo.service')->start();
$footprintless->log('dev.foo.logs.app')->follow();
DESCRIPTION
Footprintless is an automation framework with an application frontend
for managing diverse software stacks in a consistent fashion. It
provides a minimally invasive approach to configuration management. At
its core, Config::Entities are used to define the whole system
<https://en.wikipedia.org/wiki/System>. Once defined, the entities are
resources => {
bar => 'com.pastdev:bar:war:1.0',
baz => 'com.pastdev:baz:war:1.0'
},
to_dir => '/opt/foo/tomcat/webapps'
},
hostname => 'app.pastdev.com',
logs => {
catalina => '/opt/foo/tomcat/logs/catalina.out'
},
overlay => {
'Config::Entities::inherit' => ['hostname', 'sudo_username'],
base_dir => '/home/me/git/foo/base',
clean => [
'/opt/foo/tomcat/'
],
deployment_coordinate => 'foo.dev.app.deployment',
key => 'T',
os => 'linux',
resolver_coordinate => 'foo.dev',
template_dir => '/home/me/git/foo/template',
command_runner
A command_runner to use instead of that which is supplied by this
footprintless instance.
localhost
A localhost to use instead of that which is supplied by this
footprintless instance.
overlay($coordinate, %options)
Returns a new instance of Footprintless::Overlay preconfigured to
operate on the overlay at $coordinate. Supported options are
command_options_factory
A command_options_factory to use instead of that which is supplied by
this footprintless instance.
command_runner
A command_runner to use instead of that which is supplied by this
footprintless instance.
docs/Footprintless-App-Command-overlay-clean.html view on Meta::CPAN
<html><head><title>Footprintless::App::Command::overlay::clean</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
BODY {
background: white;
color: black;
font-family: arial,sans-serif;
margin: 0;
padding: 1ex;
docs/Footprintless-App-Command-overlay-clean.html view on Meta::CPAN
<li class='indexItem indexItem1'><a href='#AUTHOR'>AUTHOR</a>
<li class='indexItem indexItem1'><a href='#COPYRIGHT_AND_LICENSE'>COPYRIGHT AND LICENSE</a>
<li class='indexItem indexItem1'><a href='#SEE_ALSO'>SEE ALSO</a>
</ul>
</div>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="NAME"
>NAME</a></h1>
<p>Footprintless::App::Command::overlay::clean - removes all files managed by the overlay</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="VERSION"
>VERSION</a></h1>
<p>version 1.29</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="AUTHOR"
>AUTHOR</a></h1>
docs/Footprintless-App-Command-overlay-initialize.html view on Meta::CPAN
<html><head><title>Footprintless::App::Command::overlay::initialize</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
BODY {
background: white;
color: black;
font-family: arial,sans-serif;
margin: 0;
padding: 1ex;
docs/Footprintless-App-Command-overlay-initialize.html view on Meta::CPAN
<li class='indexItem indexItem1'><a href='#AUTHOR'>AUTHOR</a>
<li class='indexItem indexItem1'><a href='#COPYRIGHT_AND_LICENSE'>COPYRIGHT AND LICENSE</a>
<li class='indexItem indexItem1'><a href='#SEE_ALSO'>SEE ALSO</a>
</ul>
</div>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="NAME"
>NAME</a></h1>
<p>Footprintless::App::Command::overlay::initialize - cleans,
then processes the overlay base and template files</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="VERSION"
>VERSION</a></h1>
<p>version 1.29</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="AUTHOR"
>AUTHOR</a></h1>
docs/Footprintless-App-Command-overlay-update.html view on Meta::CPAN
<html><head><title>Footprintless::App::Command::overlay::clean</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
BODY {
background: white;
color: black;
font-family: arial,sans-serif;
margin: 0;
padding: 1ex;
docs/Footprintless-App-Command-overlay-update.html view on Meta::CPAN
<li class='indexItem indexItem1'><a href='#AUTHOR'>AUTHOR</a>
<li class='indexItem indexItem1'><a href='#COPYRIGHT_AND_LICENSE'>COPYRIGHT AND LICENSE</a>
<li class='indexItem indexItem1'><a href='#SEE_ALSO'>SEE ALSO</a>
</ul>
</div>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="NAME"
>NAME</a></h1>
<p>Footprintless::App::Command::overlay::clean - processes the overlay template files only</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="VERSION"
>VERSION</a></h1>
<p>version 1.29</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="AUTHOR"
>AUTHOR</a></h1>
docs/Footprintless-App-Command-overlay.html view on Meta::CPAN
<html><head><title>Footprintless::App::Command::overlay</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
BODY {
background: white;
color: black;
font-family: arial,sans-serif;
margin: 0;
padding: 1ex;
docs/Footprintless-App-Command-overlay.html view on Meta::CPAN
<li class='indexItem indexItem1'><a href='#AUTHOR'>AUTHOR</a>
<li class='indexItem indexItem1'><a href='#COPYRIGHT_AND_LICENSE'>COPYRIGHT AND LICENSE</a>
<li class='indexItem indexItem1'><a href='#SEE_ALSO'>SEE ALSO</a>
</ul>
</div>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="NAME"
>NAME</a></h1>
<p>Footprintless::App::Command::overlay - Performs an action on an overlay.</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="VERSION"
>VERSION</a></h1>
<p>version 1.29</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="SYNOPSIS"
>SYNOPSIS</a></h1>
<pre> fpl overlay OVERLAY_COORD clean
fpl overlay OVERLAY_COORD initialize
fpl overlay OVERLAY_COORD update
fpl overlay OVERLAY_COORD # same as update</pre>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="DESCRIPTION"
>DESCRIPTION</a></h1>
<p>Performs actions on an overlay.</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="AUTHOR"
>AUTHOR</a></h1>
<p>Lucas Theisen <lucastheisen@pastdev.com></p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="COPYRIGHT_AND_LICENSE"
>COPYRIGHT AND LICENSE</a></h1>
docs/Footprintless-App-Command-overlay.html view on Meta::CPAN
<p>Please see those modules/websites for more information related to this module.</p>
<ul>
<li><a href="http://search.cpan.org/perldoc?Footprintless" class="podlinkpod"
>Footprintless</a></li>
<li><a href="http://search.cpan.org/perldoc?Footprintless%3A%3AOverlay" class="podlinkpod"
>Footprintless::Overlay</a></li>
<li><a href="http://search.cpan.org/perldoc?Footprintless%3A%3AApp%3A%3ACommand%3A%3Aoverlay%3A%3Aclean" class="podlinkpod"
>Footprintless::App::Command::overlay::clean</a></li>
<li><a href="http://search.cpan.org/perldoc?Footprintless%3A%3AApp%3A%3ACommand%3A%3Aoverlay%3A%3Ainitialize" class="podlinkpod"
>Footprintless::App::Command::overlay::initialize</a></li>
<li><a href="http://search.cpan.org/perldoc?Footprintless%3A%3AApp%3A%3ACommand%3A%3Aoverlay%3A%3Aupdate" class="podlinkpod"
>Footprintless::App::Command::overlay::update</a></li>
</ul>
<!-- end doc -->
</body></html>
docs/Footprintless-Factory.html view on Meta::CPAN
<li class='indexItem indexItem1'><a href='#METHODS'>METHODS</a>
<ul class='indexList indexList2'>
<li class='indexItem indexItem2'><a href='#agent(%25options)'>agent(%options)</a>
<li class='indexItem indexItem2'><a href='#command_options(%25spec)'>command_options(%spec)</a>
<li class='indexItem indexItem2'><a href='#command_options_factory()'>command_options_factory()</a>
<li class='indexItem indexItem2'><a href='#command_runner()'>command_runner()</a>
<li class='indexItem indexItem2'><a href='#deployment(%24coordinate%2C_%25options)'>deployment($coordinate, %options)</a>
<li class='indexItem indexItem2'><a href='#entities()'>entities()</a>
<li class='indexItem indexItem2'><a href='#localhost()'>localhost()</a>
<li class='indexItem indexItem2'><a href='#log(%24coordinate%2C_%25options)'>log($coordinate, %options)</a>
<li class='indexItem indexItem2'><a href='#overlay(%24coordinate%2C_%25options)'>overlay($coordinate, %options)</a>
<li class='indexItem indexItem2'><a href='#plugins()'>plugins()</a>
<li class='indexItem indexItem2'><a href='#register_plugin(%24plugin)'>register_plugin($plugin)</a>
<li class='indexItem indexItem2'><a href='#resource_manager()'>resource_manager()</a>
<li class='indexItem indexItem2'><a href='#service(%24coordinate%2C_%25options)'>service($coordinate, %options)</a>
<li class='indexItem indexItem2'><a href='#tunnel(%24coordinate%2C_%25options)'>tunnel($coordinate, %options)</a>
</ul>
<li class='indexItem indexItem1'><a href='#AUTHOR'>AUTHOR</a>
<li class='indexItem indexItem1'><a href='#COPYRIGHT_AND_LICENSE'>COPYRIGHT AND LICENSE</a>
<li class='indexItem indexItem1'><a href='#SEE_ALSO'>SEE ALSO</a>
</ul>
docs/Footprintless-Factory.html view on Meta::CPAN
<dt><a name="localhost"
>localhost</a></dt>
<dd>
<p>A <code>localhost</code> to use instead of that which is supplied by this footprintless instance.</p>
</dd>
</dl>
<h2><a class='u' href='#___top' title='click to go to top of document'
name="overlay($coordinate,_%options)"
>overlay($coordinate,
%options)</a></h2>
<p>Returns a new instance of <a href="http://search.cpan.org/perldoc?Footprintless%3A%3AOverlay" class="podlinkpod"
>Footprintless::Overlay</a> preconfigured to operate on the overlay at <code>$coordinate</code>.
Supported options are</p>
<dl>
<dt><a name="command_options_factory"
>command_options_factory</a></dt>
<dd>
<p>A <code>command_options_factory</code> to use instead of that which is supplied by this footprintless instance.</p>
<dt><a name="command_runner"
docs/Footprintless-Mixins.html view on Meta::CPAN
<li class='indexItem indexItem1'><a href='#VERSION'>VERSION</a>
<li class='indexItem indexItem1'><a href='#DESCRIPTION'>DESCRIPTION</a>
<li class='indexItem indexItem1'><a href='#EXPORT_OK'>EXPORT_OK</a>
<ul class='indexList indexList2'>
<li class='indexItem indexItem2'><a href='#_command_options(%5B%24sub_coordinate%5D)'>_command_options([$sub_coordinate])</a>
<li class='indexItem indexItem2'><a href='#_deployment(%24sub_coordinate%2C_%5B%24name%5D)'>_deployment($sub_coordinate, [$name])</a>
<li class='indexItem indexItem2'><a href='#_download(%24resource%2C_%5B%24to%5D)'>_download($resource, [$to])</a>
<li class='indexItem indexItem2'><a href='#_entity(%24coordinate%2C_%5B%24required%5D)'>_entity($coordinate, [$required])</a>
<li class='indexItem indexItem2'><a href='#_is_local(%24hostname_sub_coordinate)'>_is_local($hostname_sub_coordinate)</a>
<li class='indexItem indexItem2'><a href='#_local_template(%5C%26local_work%2C_%5B%25options%5D)'>_local_template(\&local_work, [%options])</a>
<li class='indexItem indexItem2'><a href='#_overlay(%24sub_coordinate%2C_%5B%24name%5D)'>_overlay($sub_coordinate, [$name])</a>
<li class='indexItem indexItem2'><a href='#_push_resource_to_destination(%24source%2C_%24destination%2C_%5B%25options%5D)'>_push_resource_to_destination($source, $destination, [%options])</a>
<li class='indexItem indexItem2'><a href='#_push_to_destination(%24source%2C_%24destination%2C_%5B%25options%5D)'>_push_to_destination($source, $destination, [%options])</a>
<li class='indexItem indexItem2'><a href='#_resolve(%24resource)'>_resolve($resource)</a>
<li class='indexItem indexItem2'><a href='#_service(%24sub_coordinate%2C_%5B%24name%5D)'>_service($sub_coordinate, [$name])</a>
<li class='indexItem indexItem2'><a href='#_sub_coordinate(%24sub_coordinate)'>_sub_coordinate($sub_coordinate)</a>
<li class='indexItem indexItem2'><a href='#_sub_entity(%24sub_coordinate%2C_%5B%24required%5D)'>_sub_entity($sub_coordinate, [$required])</a>
<li class='indexItem indexItem2'><a href='#_verify_required_entities(%40sub_coordinates)'>_verify_required_entities(@sub_coordinates)</a>
</ul>
<li class='indexItem indexItem1'><a href='#AUTHOR'>AUTHOR</a>
<li class='indexItem indexItem1'><a href='#COPYRIGHT_AND_LICENSE'>COPYRIGHT AND LICENSE</a>
docs/Footprintless-Mixins.html view on Meta::CPAN
<p>Returns a truthy value if the value at <code>$hostname_sub_coordinate</code> is an alias for the local system.</p>
<h2><a class='u' href='#___top' title='click to go to top of document'
name="_local_template(\&local_work,_[%options])"
>_local_template(\&local_work, [%options])</a></h2>
<p>Will check if the entity at <code>$self->{coordinate}</code> has a <code>hostname</code> that is local, and if not, it will create a temp directory, call <code>&local_work</code> with that directory, and call <a href="http://search.cpan.or...
>"_push_to_destination($source, $destination, [%options])" in _push_to_destination</a> with the temp directory as the source, and <code>to_dir</code> as the destination when complete. If <code>hostname</code> is <i>not</i> local, then <code>&...
<h2><a class='u' href='#___top' title='click to go to top of document'
name="_overlay($sub_coordinate,_[$name])"
>_overlay($sub_coordinate, [$name])</a></h2>
<p>Returns a <code>overlay</code> from the factory. If <code>$name</code> is supplied, the <code>overlay</code> will be a singleton stored at <code>$self-</code>{$name}>.</p>
<h2><a class='u' href='#___top' title='click to go to top of document'
name="_push_resource_to_destination($source,_$destination,_[%options])"
>_push_resource_to_destination($source, $destination, [%options])</a></h2>
<p>Pushes <code>$source</code> to <code>$destination</code>. Supported options are:</p>
<dl>
<dt><a name="extract"
>extract</a></dt>
docs/Footprintless-Overlay.html view on Meta::CPAN
<li class='indexItem indexItem1'><a href='#COPYRIGHT_AND_LICENSE'>COPYRIGHT AND LICENSE</a>
<li class='indexItem indexItem1'><a href='#SEE_ALSO'>SEE ALSO</a>
<li class='indexItem indexItem1'><a href='#CONFIGURATION'>CONFIGURATION</a>
</ul>
</div>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="NAME"
>NAME</a></h1>
<p>Footprintless::Overlay - An overlay manager</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="VERSION"
>VERSION</a></h1>
<p>version 1.29</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="SYNOPSIS"
>SYNOPSIS</a></h1>
<pre> # Standard way of getting an overlay
use Footprintless;
my $overlay = Footprintless->new()->overlay('overlay');
$overlay->clean();
$overlay->initialize();
$overlay->update();</pre>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="DESCRIPTION"
>DESCRIPTION</a></h1>
<p>Overlays are a combination of a directory of static files and a directory of templated files that will be merged to an output directory. This is implemented in <a href="http://search.cpan.org/perldoc?Template%3A%3AOverlay" class="podlinkpod"
>Template::Overlay</a>.</p>
<p>Additionally, any folder under the <code>template_dir</code> can contain a <code>.footprintless</code> file containing a <code>clean</code> and/or <code>resources</code> entities:</p>
docs/Footprintless-Overlay.html view on Meta::CPAN
bar => 'com.pastdev:bar:1.0.0'
}
};</pre>
<p>The <code>clean</code> entity is an arrayref containing a list of paths to clean out. These paths will be added to the path of the directory containing the <code>.footprintless</code> file. The <code>resources</code> entity is a list of resources ...
<h1><a class='u' href='#___top' title='click to go to top of document'
name="ENTITIES"
>ENTITIES</a></h1>
<p>A simple overlay:</p>
<pre> overlay => {
base_dir => "/home/me/foo/base",
clean => [
"/opt/tomcat/"
],
hostname => 'localhost',
key => 'T',
os => 'linux',
template_dir => "/home/me/foo/template",
to_dir => '/opt/foo/tomcat'
}</pre>
<p>A more complex example:</p>
<pre> foo => {
hostname => 'test.pastdev.com',
overlay => {
'Config::Entities::inherit' => ['hostname', 'sudo_username'],
base_dir => '/home/me/foo/base',
clean => [
'/opt/foo/tomcat/'
],
key => 'T',
os => 'linux',
resolver_coordinate => 'foo',
template_dir => '/home/me/foo/template',
to_dir => '/opt/foo/tomcat'
docs/Footprintless-Overlay.html view on Meta::CPAN
},
trust_store => {
'Config::Entities::inherit' => ['hostname', 'sudo_username'],
file => '/opt/foo/tomcat/certs/truststore.jks',
include_java_home_cacerts => 1,
password => $properties->{'foo.tomcat.trust_store.password'},
}
}
}</pre>
<p>An overlay can obtain base/template content from a resource. When initialize or update are called, the resource will be downloaded (if not already local) and extracted to a temp folder. The <code>base_dir</code> and <code>template_dir</code> paths...
<pre> overlay => {
base_dir => 'base',
clean => [
'/opt/tomcat/'
],
hostname => 'localhost',
key => 'T',
os => 'linux',
resource => 'com.pastdev:app-overlay:zip:package:1.0.0',
template_dir => 'template',
to_dir => '/opt/foo/tomcat'
}</pre>
<p>An overlay can have multiple template folders. If it does, they will be processed in the order they are listed:</p>
<pre> overlay => {
base_dir => 'base',
clean => [
'/opt/tomcat/'
],
hostname => 'localhost',
key => 'T',
os => 'linux',
template_dir => [
'first/template_dir',
'second/template_dir',
docs/Footprintless-Overlay.html view on Meta::CPAN
}</pre>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="CONSTRUCTORS"
>CONSTRUCTORS</a></h1>
<h2><a class='u' href='#___top' title='click to go to top of document'
name="new($entity,_$coordinate)"
>new($entity, $coordinate)</a></h2>
<p>Constructs a new overlay configured by <code>$entities</code> at <code>$coordinate</code>.</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="METHODS"
>METHODS</a></h1>
<h2><a class='u' href='#___top' title='click to go to top of document'
name="clean()"
>clean()</a></h2>
<p>Cleans the overlay. Each path in the <code>clean</code> entity, will be removed from the destination. If the path ends in a <code>/</code>, then after being removed, the directory will be recreated.</p>
<h2><a class='u' href='#___top' title='click to go to top of document'
name="initialize()"
>initialize()</a></h2>
<p>Will call <code>clean</code>, then <code>overlay</code> on an instance of <a href="http://search.cpan.org/perldoc?Template%3A%3AOverlay" class="podlinkpod"
>Template::Overlay</a> configured to this entity.</p>
<h2><a class='u' href='#___top' title='click to go to top of document'
name="update()"
>update()</a></h2>
<p>Will overlay <i>ONLY</i> the templated files. It will not <code>clean</code>, nor copy any files from <code>base_dir</code> like <code>initialize</code> does.</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="AUTHOR"
>AUTHOR</a></h1>
<p>Lucas Theisen <lucastheisen@pastdev.com></p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="COPYRIGHT_AND_LICENSE"
>COPYRIGHT AND LICENSE</a></h1>
docs/Footprintless-Overlay.html view on Meta::CPAN
>Template::Resolver</a></li>
</ul>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="CONFIGURATION"
>CONFIGURATION</a></h1>
<p>This module can optionally be configured to use a customized resolver. To do so, configure a resolver factory in your entities:</p>
<pre> footprintless => {
overlay => {
resolver_factory => 'My::ResolverFactory'
}
}</pre>
<p>The resolver factory must have a <code>new_resolver</code> method that takes a spec and a list of options and returns a <code>Template::Resolver</code>, for example:</p>
<pre> sub new_resolver {
my ($self, $resolver_spec, %resolver_opts) = @_;
return Template::Resolver->new(
$resolver_spec,
docs/Footprintless.html view on Meta::CPAN
</ul>
<li class='indexItem indexItem1'><a href='#METHODS'>METHODS</a>
<ul class='indexList indexList2'>
<li class='indexItem indexItem2'><a href='#agent(%25options)'>agent(%options)</a>
<li class='indexItem indexItem2'><a href='#command_options_factory()'>command_options_factory()</a>
<li class='indexItem indexItem2'><a href='#command_runner()'>command_runner()</a>
<li class='indexItem indexItem2'><a href='#deployment(%24coordinate%2C_%25options)'>deployment($coordinate, %options)</a>
<li class='indexItem indexItem2'><a href='#entities()'>entities()</a>
<li class='indexItem indexItem2'><a href='#localhost()'>localhost()</a>
<li class='indexItem indexItem2'><a href='#log(%24coordinate%2C_%25options)'>log($coordinate, %options)</a>
<li class='indexItem indexItem2'><a href='#overlay(%24coordinate%2C_%25options)'>overlay($coordinate, %options)</a>
<li class='indexItem indexItem2'><a href='#plugins()'>plugins()</a>
<li class='indexItem indexItem2'><a href='#resource_manager()'>resource_manager()</a>
<li class='indexItem indexItem2'><a href='#service(%24coordinate%2C_%25options)'>service($coordinate, %options)</a>
<li class='indexItem indexItem2'><a href='#tunnel(%24coordinate%2C_%25options)'>tunnel($coordinate, %options)</a>
</ul>
<li class='indexItem indexItem1'><a href='#AUTHOR'>AUTHOR</a>
<li class='indexItem indexItem1'><a href='#COPYRIGHT_AND_LICENSE'>COPYRIGHT AND LICENSE</a>
<li class='indexItem indexItem1'><a href='#SEE_ALSO'>SEE ALSO</a>
</ul>
</div>
docs/Footprintless.html view on Meta::CPAN
<h1><a class='u' href='#___top' title='click to go to top of document'
name="SYNOPSIS"
>SYNOPSIS</a></h1>
<pre> use Footprintless;
my $footprintless = Footprintless->new();
# Deploy initialize, start, and follow the log of the foo
$footprintless->overlay('dev.foo.overlay')->initialize();
$footprintless->service('dev.foo.service')->start();
$footprintless->log('dev.foo.logs.app')->follow();</pre>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="DESCRIPTION"
>DESCRIPTION</a></h1>
<p>Footprintless is an automation framework with an application frontend for managing diverse software stacks in a consistent fashion. It provides a minimally invasive approach to configuration management. At its core, <a href="http://search.cpan.org...
>Config::Entities</a> are used to define the whole <a href="https://en.wikipedia.org/wiki/System" class="podlinkurl"
>system</a>. Once defined, the entities are used by all of the Footprintless modules to decouple the environment from the action. The environment is defined by the entities used to create <a href="http://search.cpan.org/perldoc?Footprintless%3A%3ACom...
docs/Footprintless.html view on Meta::CPAN
resources => {
bar => 'com.pastdev:bar:war:1.0',
baz => 'com.pastdev:baz:war:1.0'
},
to_dir => '/opt/foo/tomcat/webapps'
},
hostname => 'app.pastdev.com',
logs => {
catalina => '/opt/foo/tomcat/logs/catalina.out'
},
overlay => {
'Config::Entities::inherit' => ['hostname', 'sudo_username'],
base_dir => '/home/me/git/foo/base',
clean => [
'/opt/foo/tomcat/'
],
deployment_coordinate => 'foo.dev.app.deployment',
key => 'T',
os => 'linux',
resolver_coordinate => 'foo.dev',
template_dir => '/home/me/git/foo/template',
docs/Footprintless.html view on Meta::CPAN
<dt><a name="localhost"
>localhost</a></dt>
<dd>
<p>A <code>localhost</code> to use instead of that which is supplied by this footprintless instance.</p>
</dd>
</dl>
<h2><a class='u' href='#___top' title='click to go to top of document'
name="overlay($coordinate,_%options)"
>overlay($coordinate, %options)</a></h2>
<p>Returns a new instance of <a href="http://search.cpan.org/perldoc?Footprintless%3A%3AOverlay" class="podlinkpod"
>Footprintless::Overlay</a> preconfigured to operate on the overlay at <code>$coordinate</code>. Supported options are</p>
<dl>
<dt><a name="command_options_factory"
>command_options_factory</a></dt>
<dd>
<p>A <code>command_options_factory</code> to use instead of that which is supplied by this footprintless instance.</p>
<dt><a name="command_runner"
>command_runner</a></dt>
lib/Footprintless.pm view on Meta::CPAN
sub log {
my ( $self, @args ) = @_;
$self->{factory}->log(@args);
}
sub plugins {
my ($self) = @_;
$self->{factory}->plugins();
}
sub overlay {
my ( $self, @args ) = @_;
$self->{factory}->overlay(@args);
}
sub resource_manager {
my ( $self, @args ) = @_;
$self->{factory}->resource_manager(@args);
}
sub service {
my ( $self, @args ) = @_;
$self->{factory}->service(@args);
lib/Footprintless.pm view on Meta::CPAN
version 1.29
=head1 SYNOPSIS
use Footprintless;
my $footprintless = Footprintless->new();
# Deploy initialize, start, and follow the log of the foo
$footprintless->overlay('dev.foo.overlay')->initialize();
$footprintless->service('dev.foo.service')->start();
$footprintless->log('dev.foo.logs.app')->follow();
=head1 DESCRIPTION
Footprintless is an automation framework with an application frontend for
managing diverse software stacks in a consistent fashion. It provides a
minimally invasive approach to configuration management. At its core,
L<Config::Entities> are used to define the whole
L<system|https://en.wikipedia.org/wiki/System>. Once defined, the
lib/Footprintless.pm view on Meta::CPAN
resources => {
bar => 'com.pastdev:bar:war:1.0',
baz => 'com.pastdev:baz:war:1.0'
},
to_dir => '/opt/foo/tomcat/webapps'
},
hostname => 'app.pastdev.com',
logs => {
catalina => '/opt/foo/tomcat/logs/catalina.out'
},
overlay => {
'Config::Entities::inherit' => ['hostname', 'sudo_username'],
base_dir => '/home/me/git/foo/base',
clean => [
'/opt/foo/tomcat/'
],
deployment_coordinate => 'foo.dev.app.deployment',
key => 'T',
os => 'linux',
resolver_coordinate => 'foo.dev',
template_dir => '/home/me/git/foo/template',
lib/Footprintless.pm view on Meta::CPAN
A C<command_runner> to use instead of that which is supplied by
this footprintless instance.
=item localhost
A C<localhost> to use instead of that which is supplied by
this footprintless instance.
=back
=head2 overlay($coordinate, %options)
Returns a new instance of L<Footprintless::Overlay> preconfigured to
operate on the overlay at C<$coordinate>. Supported options are
=over 4
=item command_options_factory
A C<command_options_factory> to use instead of that which is supplied by
this footprintless instance.
=item command_runner
lib/Footprintless/App/Command/overlay.pm view on Meta::CPAN
use strict;
use warnings;
package Footprintless::App::Command::overlay;
$Footprintless::App::Command::overlay::VERSION = '1.29';
# ABSTRACT: Performs an action on an overlay.
# PODNAME: Footprintless::App::Command::overlay
use parent qw(Footprintless::App::ActionCommand);
sub _actions {
return (
'clean' => 'Footprintless::App::Command::overlay::clean',
'initialize' => 'Footprintless::App::Command::overlay::initialize',
'update' => 'Footprintless::App::Command::overlay::update'
);
}
sub _default_action {
return 'update';
}
sub usage_desc {
return "fpl overlay OVERLAY_COORD ACTION %o";
}
1;
__END__
=pod
=head1 NAME
Footprintless::App::Command::overlay - Performs an action on an overlay.
=head1 VERSION
version 1.29
=head1 SYNOPSIS
fpl overlay OVERLAY_COORD clean
fpl overlay OVERLAY_COORD initialize
fpl overlay OVERLAY_COORD update
fpl overlay OVERLAY_COORD # same as update
=head1 DESCRIPTION
Performs actions on an overlay.
=head1 AUTHOR
Lucas Theisen <lucastheisen@pastdev.com>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2016 by Lucas Theisen.
This is free software; you can redistribute it and/or modify it under
lib/Footprintless/App/Command/overlay.pm view on Meta::CPAN
=item *
L<Footprintless|Footprintless>
=item *
L<Footprintless::Overlay|Footprintless::Overlay>
=item *
L<Footprintless::App::Command::overlay::clean|Footprintless::App::Command::overlay::clean>
=item *
L<Footprintless::App::Command::overlay::initialize|Footprintless::App::Command::overlay::initialize>
=item *
L<Footprintless::App::Command::overlay::update|Footprintless::App::Command::overlay::update>
=back
=cut
lib/Footprintless/App/Command/overlay/clean.pm view on Meta::CPAN
use strict;
use warnings;
package Footprintless::App::Command::overlay::clean;
$Footprintless::App::Command::overlay::clean::VERSION = '1.29';
# ABSTRACT: removes all files managed by the overlay
# PODNAME: Footprintless::App::Command::overlay::clean
use parent qw(Footprintless::App::Action);
use Footprintless::App -ignore;
use Log::Any;
my $logger = Log::Any->get_logger();
sub execute {
my ( $self, $opts, $args ) = @_;
$logger->info('Performing clean...');
$self->{overlay}->clean();
$logger->info('Done...');
}
sub usage_desc {
return "fpl overlay OVERLAY_COORD clean";
}
sub validate_args {
my ( $self, $opts, $args ) = @_;
eval { $self->{overlay} = $self->{footprintless}->overlay( $self->{coordinate} ); };
$self->usage_error("invalid coordinate [$self->{coordinate}]: $@") if ($@);
}
1;
__END__
=pod
=head1 NAME
Footprintless::App::Command::overlay::clean - removes all files managed by the overlay
=head1 VERSION
version 1.29
=head1 AUTHOR
Lucas Theisen <lucastheisen@pastdev.com>
=head1 COPYRIGHT AND LICENSE
lib/Footprintless/App/Command/overlay/initialize.pm view on Meta::CPAN
use strict;
use warnings;
package Footprintless::App::Command::overlay::initialize;
$Footprintless::App::Command::overlay::initialize::VERSION = '1.29';
# ABSTRACT: cleans, then processes the overlay base and template files
# PODNAME: Footprintless::App::Command::overlay::initialize
use parent qw(Footprintless::App::Action);
use Footprintless::App -ignore;
use Log::Any;
my $logger = Log::Any->get_logger();
sub execute {
my ( $self, $opts, $args ) = @_;
$logger->info('Performing initialize...');
$self->{overlay}->initialize();
$logger->info('Done...');
}
sub usage_desc {
return "fpl overlay OVERLAY_COORD initialize %o";
}
sub validate_args {
my ( $self, $opts, $args ) = @_;
eval { $self->{overlay} = $self->{footprintless}->overlay( $self->{coordinate} ); };
$self->usage_error("invalid coordinate [$self->{coordinate}]: $@") if ($@);
}
1;
__END__
=pod
=head1 NAME
Footprintless::App::Command::overlay::initialize - cleans, then processes the overlay base and template files
=head1 VERSION
version 1.29
=head1 AUTHOR
Lucas Theisen <lucastheisen@pastdev.com>
=head1 COPYRIGHT AND LICENSE
lib/Footprintless/App/Command/overlay/update.pm view on Meta::CPAN
use strict;
use warnings;
package Footprintless::App::Command::overlay::update;
$Footprintless::App::Command::overlay::update::VERSION = '1.29';
# ABSTRACT: processes the overlay template files only
# PODNAME: Footprintless::App::Command::overlay::clean
use parent qw(Footprintless::App::Action);
use Footprintless::App -ignore;
use Log::Any;
my $logger = Log::Any->get_logger();
sub execute {
my ( $self, $opts, $args ) = @_;
$logger->info('Performing update...');
$self->{overlay}->update();
$logger->info('Done...');
}
sub usage_desc {
return "fpl overlay OVERLAY_COORD update %o";
}
sub validate_args {
my ( $self, $opts, $args ) = @_;
eval { $self->{overlay} = $self->{footprintless}->overlay( $self->{coordinate} ); };
$self->usage_error("invalid coordinate [$self->{coordinate}]: $@") if ($@);
}
1;
__END__
=pod
=head1 NAME
Footprintless::App::Command::overlay::clean - processes the overlay template files only
=head1 VERSION
version 1.29
=head1 AUTHOR
Lucas Theisen <lucastheisen@pastdev.com>
=head1 COPYRIGHT AND LICENSE
lib/Footprintless/Factory.pm view on Meta::CPAN
return $self->{localhost};
}
sub log {
my ( $self, $coordinate, %options ) = @_;
require Footprintless::Log;
return Footprintless::Log->new( $self, $coordinate, %options );
}
sub overlay {
my ( $self, $coordinate, %options ) = @_;
require Footprintless::Overlay;
return Footprintless::Overlay->new( $self, $coordinate, %options );
}
sub plugins {
return @{ $_[0]->{plugins} };
}
lib/Footprintless/Factory.pm view on Meta::CPAN
A C<command_runner> to use instead of that which is supplied by
this footprintless instance.
=item localhost
A C<localhost> to use instead of that which is supplied by
this footprintless instance.
=back
=head2 overlay($coordinate, %options)
Returns a new instance of L<Footprintless::Overlay> preconfigured to
operate on the overlay at C<$coordinate>. Supported options are
=over 4
=item command_options_factory
A C<command_options_factory> to use instead of that which is supplied by
this footprintless instance.
=item command_runner
lib/Footprintless/Mixins.pm view on Meta::CPAN
our @EXPORT_OK = qw(
_clean
_command_options
_deployment
_download
_entity
_extract_resource
_is_local
_local_template
_overlay
_push_resource_to_destination
_push_to_destination
_resource
_run
_run_or_die
_service
_sub_coordinate
_sub_entity
_verify_required_entities
);
lib/Footprintless/Mixins.pm view on Meta::CPAN
else {
$is_local = _is_local( $self, 'hostname' );
$to_dir = $is_local ? $destination_dir : temp_dir();
}
&$local_work($to_dir);
_push_to_destination( $self, $to_dir, $destination_dir ) unless ($is_local);
}
sub _overlay {
my ( $self, $sub_coordinate, $name ) = @_;
my $overlay = $name ? $self->{$name} : undef;
unless ($overlay) {
$overlay = $self->{factory}->overlay( _sub_coordinate( $self, $sub_coordinate ) );
$self->{$name} = $overlay if ($name);
}
return $overlay;
}
sub _push_resource_to_destination {
my ( $self, $resource, $destination_dir, %options ) = @_;
my $temp_dir = temp_dir();
if ( $options{extract} ) {
_extract_resource( $self, $resource, $temp_dir );
}
else {
lib/Footprintless/Mixins.pm view on Meta::CPAN
=head2 _local_template(\&local_work, [%options])
Will check if the entity at C<$self-E<gt>{coordinate}> has a C<hostname> that
is local, and if not, it will create a temp directory, call C<&local_work>
with that directory, and call
L<_push_to_destination/_push_to_destination($source, $destination, [%options])>
with the temp directory as the source, and C<to_dir> as the destination when
complete. If C<hostname> is I<not> local, then C<&local_work> is called
with C<to_dir>.
=head2 _overlay($sub_coordinate, [$name])
Returns a C<overlay> from the factory. If C<$name> is supplied, the
C<overlay> will be a singleton stored at C<$self->{$name}>.
=head2 _push_resource_to_destination($source, $destination, [%options])
Pushes C<$source> to C<$destination>. Supported options are:
=over 4
=item extract
If truthy, then the resource will be extracted using
lib/Footprintless/Overlay.pm view on Meta::CPAN
use strict;
use warnings;
package Footprintless::Overlay;
$Footprintless::Overlay::VERSION = '1.29';
# ABSTRACT: An overlay manager
# PODNAME: Footprintless::Overlay
use parent qw(Footprintless::MixableBase);
use Carp;
use Footprintless::Mixins qw (
_clean
_command_options
_entity
_extract_resource
lib/Footprintless/Overlay.pm view on Meta::CPAN
$self->_local_with_dirs_template(
sub {
$self->_initialize(@_);
}
);
}
}
sub _initialize {
my ( $self, $base_dir, $template_dir, $to_dir ) = @_;
$self->_overlay($base_dir)->overlay(
$template_dir,
resolver => $self->_dot_footprintless_resolver(),
to => $to_dir
);
}
sub _local_with_dirs_template {
my ( $self, $local_work ) = @_;
$self->_local_template(
sub {
$self->_dirs_template( $_[0], $local_work );
}
);
}
sub _overlay {
my ( $self, $base_dir ) = @_;
my @overlay_opts = ();
my $key = $self->_sub_entity('key');
push( @overlay_opts, key => $key ) if ($key);
return Template::Overlay->new( $base_dir, $self->_resolver(), @overlay_opts );
}
sub _resolver {
my ($self) = @_;
my @resolver_opts = ();
my $os = $self->_sub_entity('os');
push( @resolver_opts, os => $os ) if ($os);
my $resolver_coordinate = $self->_sub_entity('resolver_coordinate');
my $resolver_spec =
$resolver_coordinate
? $self->_entity($resolver_coordinate)
: $self->_entity();
my $resolver;
my $resolver_factory = $self->_entity('footprintless.overlay.resolver_factory');
if ($resolver_factory) {
$logger->tracef( "using resolver_factory: %s", $resolver_factory );
$resolver =
dynamic_module_new($resolver_factory)->new_resolver( $resolver_spec, @resolver_opts );
}
else {
$resolver = Template::Resolver->new( $resolver_spec, @resolver_opts );
}
return $resolver;
}
lib/Footprintless/Overlay.pm view on Meta::CPAN
sub {
$self->_update(@_);
}
);
}
}
sub _update {
my ( $self, $base_dir, $template_dir, $to_dir ) = @_;
$logger->tracef( "update to=[%s], template=[%s]", $to_dir, $template_dir );
$self->_overlay($to_dir)
->overlay( $template_dir, resolver => $self->_dot_footprintless_resolver() );
}
1;
__END__
=pod
=head1 NAME
Footprintless::Overlay - An overlay manager
=head1 VERSION
version 1.29
=head1 SYNOPSIS
# Standard way of getting an overlay
use Footprintless;
my $overlay = Footprintless->new()->overlay('overlay');
$overlay->clean();
$overlay->initialize();
$overlay->update();
=head1 DESCRIPTION
Overlays are a combination of a directory of static files and a directory
of templated files that will be merged to an output directory. This
is implemented in L<Template::Overlay>.
Additionally, any folder under the C<template_dir> can contain a
C<.footprintless> file containing a C<clean> and/or C<resources> entities:
lib/Footprintless/Overlay.pm view on Meta::CPAN
}
};
The C<clean> entity is an arrayref containing a list of paths to clean out.
These paths will be added to the path of the directory containing the
C<.footprintless> file. The C<resources> entity is a list of resources to
download into the same directory as the C<.footprintless> file.
=head1 ENTITIES
A simple overlay:
overlay => {
base_dir => "/home/me/foo/base",
clean => [
"/opt/tomcat/"
],
hostname => 'localhost',
key => 'T',
os => 'linux',
template_dir => "/home/me/foo/template",
to_dir => '/opt/foo/tomcat'
}
A more complex example:
foo => {
hostname => 'test.pastdev.com',
overlay => {
'Config::Entities::inherit' => ['hostname', 'sudo_username'],
base_dir => '/home/me/foo/base',
clean => [
'/opt/foo/tomcat/'
],
key => 'T',
os => 'linux',
resolver_coordinate => 'foo',
template_dir => '/home/me/foo/template',
to_dir => '/opt/foo/tomcat'
lib/Footprintless/Overlay.pm view on Meta::CPAN
},
trust_store => {
'Config::Entities::inherit' => ['hostname', 'sudo_username'],
file => '/opt/foo/tomcat/certs/truststore.jks',
include_java_home_cacerts => 1,
password => $properties->{'foo.tomcat.trust_store.password'},
}
}
}
An overlay can obtain base/template content from a resource. When
initialize or update are called, the resource will be downloaded (if not
already local) and extracted to a temp folder. The C<base_dir> and
C<template_dir> paths will be appended to the extract temp folder:
overlay => {
base_dir => 'base',
clean => [
'/opt/tomcat/'
],
hostname => 'localhost',
key => 'T',
os => 'linux',
resource => 'com.pastdev:app-overlay:zip:package:1.0.0',
template_dir => 'template',
to_dir => '/opt/foo/tomcat'
}
An overlay can have multiple template folders. If it does, they will
be processed in the order they are listed:
overlay => {
base_dir => 'base',
clean => [
'/opt/tomcat/'
],
hostname => 'localhost',
key => 'T',
os => 'linux',
template_dir => [
'first/template_dir',
'second/template_dir',
],
to_dir => '/opt/foo/tomcat'
}
=head1 CONSTRUCTORS
=head2 new($entity, $coordinate)
Constructs a new overlay configured by C<$entities> at C<$coordinate>.
=head1 METHODS
=head2 clean()
Cleans the overlay. Each path in the C<clean> entity, will be removed
from the destination. If the path ends in a C</>, then after being
removed, the directory will be recreated.
=head2 initialize()
Will call C<clean>, then C<overlay> on an instance of L<Template::Overlay>
configured to this entity.
=head2 update()
Will overlay I<ONLY> the templated files. It will not C<clean>, nor copy
any files from C<base_dir> like C<initialize> does.
=head1 AUTHOR
Lucas Theisen <lucastheisen@pastdev.com>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2016 by Lucas Theisen.
lib/Footprintless/Overlay.pm view on Meta::CPAN
L<Template::Resolver|Template::Resolver>
=back
=head1 CONFIGURATION
This module can optionally be configured to use a customized resolver. To
do so, configure a resolver factory in your entities:
footprintless => {
overlay => {
resolver_factory => 'My::ResolverFactory'
}
}
The resolver factory must have a C<new_resolver> method that takes a spec and
a list of options and returns a C<Template::Resolver>, for example:
sub new_resolver {
my ($self, $resolver_spec, %resolver_opts) = @_;
return Template::Resolver->new(
t/Footprintless_App_Command_config.t view on Meta::CPAN
$ENV{FPL_CONFIG_PROPS} =
File::Spec->catfile( $test_dir, 'config', 'properties.pl' )
. ( ( $^O eq 'MSWin32' ) ? ';' : ':' )
. File::Spec->catfile( $test_dir, 'config', 'environment.pl' );
is( test_app( 'Footprintless::App' => [ 'config', 'dev.foo.site', '--format', 'dumper0' ] )
->stdout(),
"\$VAR1 = '';",
'dev.foo.site empty string'
);
is( test_app( 'Footprintless::App' => [ 'config', 'dev.foo.overlay.os', '--format', 'dumper0' ] )
->stdout(),
"\$VAR1 = 'linux';",
'dev.foo.overlay.os = linux'
);
is( test_app( 'Footprintless::App' => [ 'config', 'dev.foo.logs', '--format', 'json2' ] )
->stdout(),
'{"catalina":"/opt/pastdev/foo-tomcat/logs/catalina.out"}',
'json dev.piab = {...}'
);
t/Footprintless_App_Command_deploy.t view on Meta::CPAN
sub footprintless {
my ( $temp_dir, $root_dir ) = @_;
my $temp_config_dir = File::Spec->catdir( $temp_dir, 'config' );
make_path($temp_config_dir);
my $environment_dot_pl = File::Spec->catdir( $temp_config_dir, 'environment.pl' );
spurt( <<" EPL", $environment_dot_pl );
return {
'dev.foo.deployment.resources.dir' => '$test_dir/data/resources',
'dev.foo.hostname' => 'localhost',
'dev.foo.overlay.dir' => '$test_dir/data',
'dev.foo.sudo_username' => undef,
'dev.os' => '$^O',
'dev.root.dir' => '$root_dir',
}
EPL
# Get the current entities
$ENV{FPL_CONFIG_DIRS} = File::Spec->catdir( $test_dir, 'config', 'entities' );
$ENV{FPL_CONFIG_PROPS} =
File::Spec->catfile( $test_dir, 'config', 'properties.pl' )
t/Footprintless_App_Command_overlay.t view on Meta::CPAN
sub footprintless {
my ( $temp_dir, $root_dir ) = @_;
my $temp_config_dir = File::Spec->catdir( $temp_dir, 'config' );
make_path($temp_config_dir);
my $environment_dot_pl = File::Spec->catdir( $temp_config_dir, 'environment.pl' );
spurt( <<" EPL", $environment_dot_pl );
return {
'dev.foo.deployment.resources.dir' => '$test_dir/data/resources',
'dev.foo.hostname' => 'localhost',
'dev.foo.overlay.dir' => '$test_dir/data',
'dev.foo.sudo_username' => undef,
'dev.os' => '$^O',
'dev.root.dir' => '$root_dir',
}
EPL
# Get the current entities
$ENV{FPL_CONFIG_DIRS} = File::Spec->catdir( $test_dir, 'config', 'entities' );
$ENV{FPL_CONFIG_PROPS} =
File::Spec->catfile( $test_dir, 'config', 'properties.pl' )
. ( ( $^O eq 'MSWin32' ) ? ';' : ':' )
. $environment_dot_pl;
return Footprintless->new();
}
sub match {
my ( $file, $footprintless, $coordinate, $action ) = @_;
my $overlay = $footprintless->entities()->get_entity($coordinate);
my $got_file = File::Spec->catdir( File::Spec->catdir( $overlay->{to_dir}, $file ) );
ok( -f $got_file, "$action: $file is file" );
my $original_content;
my $original_file =
File::Spec->catdir( File::Spec->catdir( $overlay->{template_dir}, $file ) );
if ( -f $original_file ) {
my @resolver_opts = ();
if ( $overlay->{os} ) {
push( @resolver_opts, os => $overlay->{os} );
}
my $resolver_spec =
$overlay->{resolver_coordinate}
? $footprintless->entities()->get_entity( $overlay->{resolver_coordinate} )
: $overlay;
$original_content = Template::Resolver->new( $resolver_spec, @resolver_opts )->resolve(
content => slurp($original_file),
key => $overlay->{key}
);
}
else {
$original_content = slurp( File::Spec->catdir( $overlay->{base_dir}, $file ) );
}
$logger->debugf( 'checking %s', $got_file );
is( slurp($got_file), $original_content, "$action: $file matches expected" );
}
sub test_overlay {
my ( $coordinate, $action, %options ) = @_;
my $temp_dir = File::Temp->newdir();
my $overlay_dir = File::Spec->catdir( $temp_dir, 'overlay' );
make_path($overlay_dir);
my $footprintless = footprintless( $temp_dir, $overlay_dir );
my $overlay = $footprintless->entities()->get_entity($coordinate);
unless ( $overlay->{base_dir} eq File::Spec->catfile( $test_dir, 'data', 'base' )
&& $overlay->{template_dir} eq File::Spec->catfile( $test_dir, 'data', 'template' )
&& $overlay->{to_dir} =~ /^$overlay_dir/ )
{
;
$logger->errorf(
"%s=[%s]\n%s=[%s]\n%s starts with [%s]", $overlay->{base_dir},
File::Spec->catfile( $test_dir, 'data', 'base' ), $overlay->{template_dir},
File::Spec->catfile( $test_dir, 'data', 'template' ), $overlay->{to_dir},
$overlay_dir
);
BAIL_OUT('environment configuration broken, could be dangerous to proceed...');
}
$logger->debug('environment looks good, proceed...');
if ( $logger->is_trace ) {
$logger->tracef( 'overlay: %s', Data::Dumper->new( [$overlay] )->Indent(1)->Dump() );
}
Footprintless::App::clear_pretend_self();
my $result = test_app(
'Footprintless::App' => [
'overlay', $coordinate,
$action, ( $options{command_args} ? @{ $options{command_args} } : () )
]
);
is( $result->exit_code(), 0, "overlay completed succesfully" );
if ( $logger->is_debug() ) {
$logger->debugf(
"exit_code=[%s],error=[%s]\n----- STDOUT ----\n%s\n---- STDERR ----\n%s\n---- END ----",
$result->exit_code(), $result->error(), $result->stdout(), $result->stderr()
);
}
&{ $options{validator} }($footprintless) if ( $options{validator} );
}
my $coordinate = 'dev.foo.overlay';
test_overlay(
$coordinate,
'update',
validator => sub {
my ($footprintless) = @_;
match( 'bin/catalina.sh', $footprintless, $coordinate, 'update' );
match( 'bin/setenv.sh', $footprintless, $coordinate, 'update' );
match( 'conf/jndi-resources.xml', $footprintless, $coordinate, 'update' );
match( 'conf/server.xml', $footprintless, $coordinate, 'update' );
}
);
test_overlay(
$coordinate,
'initialize',
validator => sub {
my ($footprintless) = @_;
match( 'bin/catalina.sh', $footprintless, $coordinate, 'initialize' );
match( 'bin/setenv.sh', $footprintless, $coordinate, 'initialize' );
match( 'conf/jndi-resources.xml', $footprintless, $coordinate, 'initialize' );
match( 'conf/server.xml', $footprintless, $coordinate, 'initialize' );
match( 'conf/catalina.properties', $footprintless, $coordinate, 'initialize' );
t/Footprintless_Overlay.t view on Meta::CPAN
my $template_dir = File::Spec->catdir( $temp_dir, 'template' );
make_path( $base_dir, $to_dir, $template_dir );
return $temp_dir, $base_dir, $to_dir, $template_dir;
}
{
$logger->info('Verify initialize');
my ( $temp_dir, $base_dir, $to_dir, $template_dir ) = temp_dirs();
my $hostname = 'localhost';
my $overlay = Footprintless::Overlay->new(
factory(
{ system => {
hostname => $hostname,
app => {
'Config::Entities::inherit' => ['hostname'],
overlay => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
base_dir => $base_dir,
clean => ["$to_dir/"],
key => 'T',
os => $^O,
resolver_coordinate => 'system',
template_dir => $template_dir,
to_dir => $to_dir
}
}
}
}
),
'system.app.overlay'
);
ok( $overlay, 'overlay constructed' );
my $name = 'foo';
my $template_file = File::Spec->catfile( $template_dir, $name );
my $to_file = File::Spec->catfile( $to_dir, $name );
spurt( 'hostname=[${T{app.hostname}}]', $template_file );
my $base_template_file = File::Spec->catfile( $base_dir, $name );
spurt( 'i should be overlayed', $base_template_file );
my $base_name = 'bar';
my $base_file = File::Spec->catfile( $base_dir, $base_name );
spurt( 'bar', $base_file );
$overlay->initialize();
is( slurp($to_file), "hostname=[$hostname]", 'initialize template' );
is( slurp($base_file), "bar", 'initialize base' );
}
{
$logger->info('Verify update');
my ( $temp_dir, $base_dir, $to_dir, $template_dir ) = temp_dirs();
my $hostname = 'localhost';
my $overlay = Footprintless::Overlay->new(
factory(
{ system => {
hostname => $hostname,
app => {
'Config::Entities::inherit' => ['hostname'],
overlay => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
base_dir => $base_dir,
clean => ["$to_dir/"],
key => 'T',
os => $^O,
resolver_coordinate => 'system',
template_dir => $template_dir,
to_dir => $to_dir
}
}
}
}
),
'system.app.overlay'
);
ok( $overlay, 'overlay constructed' );
my $name = 'foo';
my $template_file = File::Spec->catfile( $template_dir, $name );
my $to_file = File::Spec->catfile( $to_dir, $name );
spurt( 'hostname=[${T{app.hostname}}]', $template_file );
$overlay->update();
is( slurp($to_file), "hostname=[$hostname]", 'update' );
}
{
$logger->info('Verify clean');
my ( $temp_dir, $base_dir, $to_dir, $template_dir ) = temp_dirs();
my $overlay = Footprintless::Overlay->new(
factory(
{ overlay => {
hostname => 'localhost',
base_dir => $base_dir,
clean => ["$to_dir/"],
key => 'T',
os => $^O,
resolver_coordinate => 'system',
template_dir => $template_dir,
to_dir => $to_dir
}
}
),
'overlay'
);
my $to_file = File::Spec->catfile( $to_dir, 'bar' );
spurt( 'foo', $to_file );
ok( -f $to_file, 'clean test to_file created' );
$overlay->clean();
ok( !-e $to_file, 'clean test' );
}
{
$logger->info('Verify resolver factory');
my ( $temp_dir, $base_dir, $to_dir, $template_dir ) = temp_dirs();
my $hostname = 'localhost';
my $overlay = Footprintless::Overlay->new(
factory(
{ system => {
hostname => $hostname,
app => {
'Config::Entities::inherit' => ['hostname'],
overlay => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
base_dir => $base_dir,
clean => ["$to_dir/"],
key => 'T',
os => $^O,
resolver_coordinate => 'system',
template_dir => $template_dir,
to_dir => $to_dir
},
web => {
'Config::Entities::inherit' => ['hostname'],
https => 1,
port => 8443,
context_path => '/foo'
},
},
},
footprintless =>
{ overlay => { resolver_factory => 'Footprintless::WebUrlResolverFactory' } }
}
),
'system.app.overlay'
);
ok( $overlay, 'overlay constructed with resolver factory' );
my $name = 'foo';
my $template_file = File::Spec->catfile( $template_dir, $name );
my $to_file = File::Spec->catfile( $to_dir, $name );
spurt( 'url=[${T_web_url{app.web}}]', $template_file );
$overlay->update();
is( slurp($to_file), "url=[https://$hostname:8443/foo]", 'update with resolver factory' );
}
{
$logger->info('Verify resolve .footprintless placeholders');
my ( $temp_dir, $base_dir, $to_dir, $template_dir ) = temp_dirs();
my $hostname = 'localhost';
my @downloads = ();
{
package Mock::ResourceManager;
sub download {
my ( $self, @args ) = @_;
push( @downloads, \@args );
}
}
my $overlay = Footprintless::Overlay->new(
factory(
{ system => {
hostname => $hostname,
app => {
'Config::Entities::inherit' => ['hostname'],
overlay => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
base_dir => $base_dir,
clean => ["$to_dir/"],
key => 'T',
os => $^O,
resolver_coordinate => 'system',
template_dir => $template_dir,
to_dir => $to_dir
},
web => {
'Config::Entities::inherit' => ['hostname'],
https => 1,
port => 8443,
context_path => '/foo'
},
},
}
},
resource_manager => bless( {}, 'Mock::ResourceManager' )
),
'system.app.overlay'
);
ok( $overlay, 'overlay constructed with mock resource manager' );
my $dot_footprintless = File::Spec->catfile( $template_dir, '.footprintless' );
spurt( 'return {clean => ["./"], resources => {foo => "bar"}};', $dot_footprintless );
$overlay->initialize();
is( @downloads == 1 && $downloads[0][0], 'bar', 'bar was downloaded by initialize' );
my $baz = File::Spec->catfile( $to_dir, 'baz' );
spurt( 'testing...', $baz );
ok( -f $baz, 'baz is ready to be cleaned' );
$overlay->update();
ok( !-e $baz, 'clean worked' );
is( @downloads == 2 && $downloads[1][0], 'bar', 'bar was downloaded by update' );
}
{
$logger->info('Verify alternate to_dir');
my ( $temp_dir, $base_dir, $to_dir, $template_dir ) = temp_dirs();
my $alternate_to_dir = File::Spec->catdir( $temp_dir, 'alternate' );
make_path($alternate_to_dir);
my $hostname = 'localhost';
my $overlay = Footprintless::Overlay->new(
factory(
{ system => {
hostname => $hostname,
app => {
'Config::Entities::inherit' => ['hostname'],
overlay => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
base_dir => $base_dir,
clean => ["$to_dir/"],
key => 'T',
os => $^O,
resolver_coordinate => 'system',
template_dir => $template_dir,
to_dir => $to_dir
}
}
}
}
),
'system.app.overlay'
);
ok( $overlay, 'overlay constructed' );
my $name = 'foo';
my $template_file = File::Spec->catfile( $template_dir, $name );
my $to_file = File::Spec->catfile( $to_dir, $name );
my $alternate_to_file = File::Spec->catfile( $alternate_to_dir, $name );
spurt( 'hostname=[${T{app.hostname}}]', $template_file );
my $base_template_file = File::Spec->catfile( $base_dir, $name );
spurt( 'i should be overlayed', $base_template_file );
my $base_name = 'bar';
my $base_file = File::Spec->catfile( $base_dir, $base_name );
spurt( 'bar', $base_file );
$overlay->initialize( to_dir => $alternate_to_dir );
ok( !-e $to_file, 'configured initialize template does not exist' );
is( slurp($alternate_to_file), "hostname=[$hostname]", 'alternate initialize template' );
is( slurp($base_file), "bar", 'configured initialize base' );
unlink($alternate_to_file);
ok( !-e $alternate_to_file, 'alternate_to_file deleted' );
$overlay->update( to_dir => $alternate_to_dir );
ok( !-e $to_file, 'configured update template does not exist' );
is( slurp($alternate_to_file), "hostname=[$hostname]", 'alternate update' );
}
SKIP: {
$logger->info('Verify non-local');
my $command_runner = default_command_runner();
eval {
$command_runner->run_or_die( 'ssh -q -o "StrictHostKeyChecking=yes" localhost echo hello',
{ timeout => 2 } );
};
if ($@) {
skip( "cannot ssh to localhost: $@", 3 );
}
my ( $temp_dir, $base_dir, $to_dir, $template_dir ) = temp_dirs();
my $hostname = 'localhost';
my $overlay = Footprintless::Overlay->new(
factory(
{ system => {
hostname => $hostname,
app => {
'Config::Entities::inherit' => ['hostname'],
overlay => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
base_dir => $base_dir,
clean => ["$to_dir/"],
key => 'T',
os => $^O,
resolver_coordinate => 'system',
template_dir => $template_dir,
to_dir => $to_dir
}
}
}
}
),
'system.app.overlay',
localhost => Footprintless::Localhost->new( none => 1 )
);
ok( $overlay, 'overlay constructed' );
my $name = 'foo';
my $template_file = File::Spec->catfile( $template_dir, $name );
my $to_file = File::Spec->catfile( $to_dir, $name );
spurt( 'hostname=[${T{app.hostname}}]', $template_file );
my $base_template_file = File::Spec->catfile( $base_dir, $name );
spurt( 'i should be overlayed', $base_template_file );
my $base_name = 'bar';
my $base_file = File::Spec->catfile( $base_dir, $base_name );
spurt( 'bar', $base_file );
$overlay->initialize();
is( slurp($to_file), "hostname=[$hostname]", 'non-local initialize template' );
is( slurp($base_file), "bar", 'non-local initialize base' );
}
SKIP: {
$logger->info('Verify resource overlay');
my ( $temp_dir, $base_dir, $to_dir, $template_dir ) = temp_dirs();
my $hostname = 'localhost';
my $overlay = Footprintless::Overlay->new(
factory(
{ system => {
hostname => $hostname,
app => {
'Config::Entities::inherit' => ['hostname'],
overlay => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
base_dir => 'base',
clean => ["$to_dir/"],
key => 'T',
os => $^O,
resource => File::Spec->catfile(
$test_dir, 'data', 'resources', 'overlay.zip'
),
resolver_coordinate => 'system',
template_dir => 'template/first',
to_dir => $to_dir
},
},
}
}
),
'system.app.overlay'
);
ok( $overlay, 'resource overlay constructed' );
$overlay->initialize();
my $foo_file = File::Spec->catfile( $to_dir, 'foo.txt' );
my $bar_file = File::Spec->catfile( $to_dir, 'bar.txt' );
my $baz_file = File::Spec->catfile( $to_dir, 'baz.txt' );
ok( -f $foo_file, 'resource overlay initialize foo exists' );
is( slurp($foo_file), "hostname=[foo]\n", 'resource overlay initialize foo matches' );
ok( -f $bar_file, 'resource overlay initialize bar exists' );
is( slurp($bar_file),
"first.bar.hostname=[$hostname]\n",
'resource overlay initialize bar matches'
);
ok( -f $baz_file, 'resource overlay initialize baz exists' );
is( slurp($baz_file),
"first.baz.hostname=[$hostname]\n",
'resource overlay initialize baz matches'
);
$overlay->clean();
ok( !( -e $foo_file ), 'resource overlay clean foo' );
ok( !( -e $bar_file ), 'resource overlay clean bar' );
ok( !( -e $baz_file ), 'resource overlay clean baz' );
$overlay->update();
ok( !( -e $foo_file ), 'resource overlay update foo missing' );
ok( -f $bar_file, 'resource overlay update bar exists' );
is( slurp($bar_file),
"first.bar.hostname=[$hostname]\n",
'resource overlay update bar matches'
);
ok( -f $baz_file, 'resource overlay update baz exists' );
is( slurp($baz_file),
"first.baz.hostname=[$hostname]\n",
'resource overlay update baz matches'
);
}
SKIP: {
$logger->info('Verify multi-template resource overlay');
my ( $temp_dir, $base_dir, $to_dir, $template_dir ) = temp_dirs();
my $hostname = 'localhost';
my $overlay = Footprintless::Overlay->new(
factory(
{ system => {
hostname => $hostname,
app => {
'Config::Entities::inherit' => ['hostname'],
overlay => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
base_dir => 'base',
clean => ["$to_dir/"],
key => 'T',
os => $^O,
resource => File::Spec->catfile(
$test_dir, 'data', 'resources', 'overlay.zip'
),
resolver_coordinate => 'system',
template_dir => [ 'template/first', 'template/second', ],
to_dir => $to_dir
},
},
}
}
),
'system.app.overlay'
);
ok( $overlay, 'multi-template resource overlay constructed' );
$overlay->initialize();
my $foo_file = File::Spec->catfile( $to_dir, 'foo.txt' );
my $bar_file = File::Spec->catfile( $to_dir, 'bar.txt' );
my $baz_file = File::Spec->catfile( $to_dir, 'baz.txt' );
ok( -f $foo_file, 'multi-template resource overlay initialize foo exists' );
is( slurp($foo_file), "hostname=[foo]\n",
'multi-template resource overlay initialize foo matches' );
ok( -f $bar_file, 'multi-template resource overlay initialize bar exists' );
is( slurp($bar_file),
"second.bar.hostname=[$hostname]\n",
'multi-template resource overlay initialize bar matches'
);
ok( -f $baz_file, 'multi-template resource overlay initialize baz exists' );
is( slurp($baz_file),
"first.baz.hostname=[$hostname]\n",
'multi-template resource overlay initialize baz matches'
);
$overlay->clean();
ok( !( -e $foo_file ), 'multi-template resource overlay clean foo' );
ok( !( -e $bar_file ), 'multi-template resource overlay clean bar' );
ok( !( -e $baz_file ), 'multi-template resource overlay clean baz' );
$overlay->update();
ok( !( -e $foo_file ), 'multi-template resource overlay update foo missing' );
ok( -f $bar_file, 'multi-template resource overlay update bar exists' );
is( slurp($bar_file),
"second.bar.hostname=[$hostname]\n",
'multi-template resource overlay update bar matches'
);
ok( -f $baz_file, 'multi-template resource overlay update baz exists' );
is( slurp($baz_file),
"first.baz.hostname=[$hostname]\n",
'multi-template resource overlay update baz matches'
);
}
t/config/entities/dev.pm view on Meta::CPAN
"$foo_tomcat_directory/webapps/", "$foo_tomcat_directory/work/",
],
resources => {
bar => "$properties{'dev.foo.deployment.resources.dir'}/bar.war",
baz => "$properties{'dev.foo.deployment.resources.dir'}/baz.war"
},
to_dir => "$foo_tomcat_directory/webapps",
},
hostname => $properties->{'dev.foo.hostname'},
logs => { catalina => "$foo_tomcat_directory/logs/catalina.out", },
overlay => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
base_dir => "$properties{'dev.foo.overlay.dir'}/base",
clean => [ "$foo_tomcat_directory/" ],
key => 'T',
os => $properties{'dev.os'},
resolver_coordinate => $coord,
template_dir => "$properties{'dev.foo.overlay.dir'}/template",
to_dir => $foo_tomcat_directory
},
site => '',
sudo_username => $properties->{'dev.foo.sudo_username'},
tomcat => {
'Config::Entities::inherit' => [ 'hostname', 'sudo_username' ],
ajp => { port => 8509 },
catalina_base => $foo_tomcat_directory,
http => { port => 8580 },
jmx_port => 8587,
t/config/environment.pl view on Meta::CPAN
use File::Spec;
my $data_dir = File::Spec->catdir( substr( __FILE__, 0, rindex( __FILE__, "config" ) ), 'data' );
return {
'dev.foo.deployment.resources.dir' => "$data_dir/resources",
'dev.foo.hostname' => 'app.pastdev.local',
'dev.foo.overlay.dir' => $data_dir,
'dev.foo.sudo_username' => 'foo',
'dev.os' => 'linux',
'dev.root.dir' => '/opt/pastdev',
}
xt/author/00-compile.t view on Meta::CPAN
'Footprintless/App/Command/config.pm',
'Footprintless/App/Command/deployment.pm',
'Footprintless/App/Command/deployment/clean.pm',
'Footprintless/App/Command/deployment/deploy.pm',
'Footprintless/App/Command/log.pm',
'Footprintless/App/Command/log/cat.pm',
'Footprintless/App/Command/log/follow.pm',
'Footprintless/App/Command/log/grep.pm',
'Footprintless/App/Command/log/head.pm',
'Footprintless/App/Command/log/tail.pm',
'Footprintless/App/Command/overlay.pm',
'Footprintless/App/Command/overlay/clean.pm',
'Footprintless/App/Command/overlay/initialize.pm',
'Footprintless/App/Command/overlay/update.pm',
'Footprintless/App/Command/service.pm',
'Footprintless/App/DocumentationUtil.pm',
'Footprintless/App/UsageException.pm',
'Footprintless/Command.pm',
'Footprintless/CommandOptionsFactory.pm',
'Footprintless/CommandRunner.pm',
'Footprintless/CommandRunner/ExecutionException.pm',
'Footprintless/CommandRunner/IPCRun.pm',
'Footprintless/CommandRunner/IPCRun3.pm',
'Footprintless/Deployment.pm',