Mojo-Command-Generate-InitScript

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for Mojo-Command-Generate-InitScript

0.03    05.02
        Fixed deploying for Debian, added some :) documentation

0.02    26.01
        Added Debian initscript generation

0.01    26.01
        First version, released on an unsuspecting world.

MANIFEST  view on Meta::CPAN

Changes
ignore.txt
lib/Mojo/Command/Generate/InitScript.pm
lib/Mojo/Command/Generate/InitScript/Freebsd.pm
lib/Mojo/Command/Generate/InitScript/Debian.pm
Makefile.PL
MANIFEST			This list of files
README
t/00-load.t
t/boilerplate.t
t/manifest.t
t/pod-coverage.t
t/pod.t
META.yml                                 Module meta-data (added by MakeMaker)

META.yml  view on Meta::CPAN

--- #YAML:1.0
name:               Mojo-Command-Generate-InitScript
version:            0.03
abstract:           Initscript generator command
author:
    - Anatoliy Lapitskiy <nuclon@cpan.org>
license:            perl
distribution_type:  module
configure_requires:
    ExtUtils::MakeMaker:  0
build_requires:
    ExtUtils::MakeMaker:  0
requires:
    Test::More:  0
no_index:
    directory:
        - t
        - inc
generated_by:       ExtUtils::MakeMaker version 6.56
meta-spec:
    url:      http://module-build.sourceforge.net/META-spec-v1.4.html
    version:  1.4

Makefile.PL  view on Meta::CPAN

use strict;
use warnings;
use ExtUtils::MakeMaker;

WriteMakefile(
    NAME                => 'Mojo::Command::Generate::InitScript',
    AUTHOR              => q{Anatoliy Lapitskiy <nuclon@cpan.org>},
    VERSION_FROM        => 'lib/Mojo/Command/Generate/InitScript.pm',
    ABSTRACT_FROM       => 'lib/Mojo/Command/Generate/InitScript.pm',
    ($ExtUtils::MakeMaker::VERSION >= 6.3002
      ? ('LICENSE'=> 'perl')
      : ()),
    PL_FILES            => {},
    PREREQ_PM => {
        'Test::More' => 0,
    },
    dist                => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
    clean               => { FILES => 'Mojo-Command-Generate-InitScript-*' },
);

README  view on Meta::CPAN

Mojo-Command-Generate-InitScript

The README is used to introduce the module and provide instructions on
how to install the module, any machine dependencies it may have (for
example C compilers and installed libraries) and any other information
that should be provided before the module is installed.

A README file is required for CPAN modules since CPAN extracts the README
file from a module distribution so that people browsing the archive
can use it to get an idea of the module's uses. It is usually a good idea
to provide version information here so that people can decide whether
fixes for the module are worth downloading.


INSTALLATION

To install this module, run the following commands:

	perl Makefile.PL
	make
	make test
	make install

SUPPORT AND DOCUMENTATION

After installing, you can find documentation for this module with the
perldoc command.

    perldoc Mojo::Command::Generate::InitScript

You can also look for information at:

    RT, CPAN's request tracker
        http://rt.cpan.org/NoAuth/Bugs.html?Dist=Mojo-Command-Generate-InitScript

    AnnoCPAN, Annotated CPAN documentation
        http://annocpan.org/dist/Mojo-Command-Generate-InitScript

    CPAN Ratings
        http://cpanratings.perl.org/d/Mojo-Command-Generate-InitScript

    Search CPAN
        http://search.cpan.org/dist/Mojo-Command-Generate-InitScript/


LICENSE AND COPYRIGHT

Copyright (C) 2010 Anatoliy

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.

ignore.txt  view on Meta::CPAN

blib*
Makefile
Makefile.old
Build
Build.bat
_build*
pm_to_blib*
*.tar.gz
.lwpcookies
cover_db
pod2htm*.tmp
Mojo-Command-Generate-InitScript-*
.hg*
*.swp

lib/Mojo/Command/Generate/InitScript.pm  view on Meta::CPAN

package Mojo::Command::Generate::InitScript;

use warnings;
use strict;

use base 'Mojo::Commands';
use File::Spec;
use Getopt::Long 'GetOptions';
use Mojo::ByteStream 'b';



__PACKAGE__->attr(description => <<'EOF');
Generate application initscript (also known as rc.d script)
EOF
__PACKAGE__->attr(usage => <<"EOF");
usage: $0 generate init_script target_os [OPTIONS]

These options are available:
    --output <folder>   Set folder to output initscripts
    --deploy            Deploy initscripts into OS
                        Either --deploy or --output=dist should be specified

    --name <name>       Ovewrite name which is used for initscript filename(s)
EOF

__PACKAGE__->attr(namespaces => sub { ['Mojo::Command::Generate::InitScript'] });


=head1 NAME

Mojo::Command::Generate::InitScript - Initscript generator command

=head1 SYNOPSYS

	$ ./mojo_app.pl generate help init_script
	usage: ./mojo_app.pl generate init_script target_os [OPTIONS]

	These options are available:
		--output <folder>   Set folder to output initscripts
		--deploy            Deploy initscripts into OS
							Either --deploy or --output=dist should be specified

		--name <name>       Ovewrite name which is used for initscript filename(s)


=cut

our $VERSION = '0.03';



sub run
{
	my ( $self, $target ) = @_;

	my $opt = {};

	Getopt::Long::Configure('pass_through');
	GetOptions( $opt,
		'output=s', 'name=s', 'deploy',
	);

	if ( !( $opt->{'deploy'} || $opt->{'output'} ) )
	{
		die qq{Either --deploy or --output <folder> should be specified\n};
	}
	if ( $opt->{'deploy'} && $opt->{'output'} )
	{
		die qq{Either --deploy or --output <folder> should be specified but not both\n};
	}

	if ( $opt->{'deploy'} && !$self->user_is_root )
	{
		die qq{You must be root to deploy init script\n};
	}

	if ( !$opt->{'name'} )
	{
		my ( $vol, $folder, $filename ) = File::Spec->splitpath( $0 );
		($opt->{'name'}) = $filename =~ m/^(.*?)(?:\.pl)?$/;
	}

	$opt->{'app_script'} = File::Spec->rel2abs( $0 );

	$self->SUPER::run( $target, $opt, @_ );

}

sub user_is_root
{
	my $self = shift;
	return $> == 0 || $< == 0
}

sub help
{
	my $self = shift;
	my $name = pop @ARGV;
	if ( $name eq 'init_script' )
	{
		print $self->usage;
		return;
	}
	my $module;
	for my $namespace (@{$self->namespaces})
	{

		# Generate module
		my $try = $namespace . '::' . b($name)->camelize;

		# Load
		if (my $e = Mojo::Loader->load($try)) {

			# Module missing
			next unless ref $e;

			# Real error
			die $e;
		}

		# Module is a command?
		next unless $try->can('new') && $try->can('run');

		# Found
		$module = $try;
		last;
	}

	die qq/Command "$name" missing, maybe you need to install it?\n/
	  unless $module;

	my $command = $module->new;
	print $self->usage, "\n", $command->usage;
}

=head1 AUTHOR

Anatoliy Lapitskiy, C<< <nuclon at cpan.org> >>


=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Mojo::Command::Generate::InitScript


You can also look for information at:

=over 4

=item * bitbucket repository

L<http://bitbucket.org/nuclon/mojo-command-generate-initscript/>

=item * Search CPAN

L<http://search.cpan.org/dist/Mojo-Command-Generate-InitScript/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

Copyright 2010 Anatoliy Lapitskiy.

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.


=cut

1; # End of Mojo::Command::Generate::InitScript

lib/Mojo/Command/Generate/InitScript/Debian.pm  view on Meta::CPAN

package Mojo::Command::Generate::InitScript::Debian;

use warnings;
use strict;
use File::Spec;

#use base 'Mojo::Command::Generate::InitScript::Base';
use base 'Mojo::Command';
use Getopt::Long 'GetOptions';
use File::Spec;
use IO::File;
use List::Util qw(first);

__PACKAGE__->attr(usage => <<"EOF");
Debian initscript related options:
    --should-start <applist>    defines facilities which, if present, 
                                should be available during startup of this service    
    --should-stop <applist>     facilities which should be available 
                                during shutdown of this service.
    --runlevels  <runlevels>    which run levels should by default run the init script
                                with a start (stop) argument to start (stop)
                                (Default: 2 3 4 5)
EOF

sub run
{
	my ( $self, $opt ) = @_;

	$opt->{'should-start'} = [];
	$opt->{'should-stop'}  = [];
	$opt->{'runlevels'}    = [2, 3, 4, 5];
	$opt->{'stoplevels'}   = [];

	GetOptions($opt,
		'should-start=s{,}', 'should-stop=s{,}', 'runlevels=i{,}',
	);

	for my $i (0..6)
	{
		if ( !first { $i == $_ } @{ $opt->{'runlevels'} } )
		{
			push @{ $opt->{'stoplevels'} }, $i;
		}
	}

	# init script
	my $file = $opt->{'deploy'}
				? '/etc/init.d/'. $opt->{'name'}
				: File::Spec->join($opt->{'output'}, $opt->{'name'});
	$self->render_to_file( 'initscript', $file, $opt );
	$self->chmod_file( $file, 0755 );

	# config file
	$file = $opt->{'deploy'}
				? '/etc/default/'. $opt->{'name'}
				: File::Spec->join($opt->{'output'}, 'etc_default_'.$opt->{'name'});
	$self->render_to_file( 'config', $file, $opt );
	$self->chmod_file( $file, 0644 );

	if ( $opt->{'deploy'} )
	{
		system('/usr/sbin/update-rc.d', $opt->{'name'},
			'start', '20', (@{ $opt->{'runlevels'} }), '.',
			'stop', '20', (@{ $opt->{'stoplevels'} }), '.'
		);
	}
}
1;
__DATA__
@@ initscript
% my $opt = shift;
% my $name = $opt->{'name'};
#! /bin/sh

### BEGIN INIT INFO
# Provides:          <%= $name %>
# Required-Start:    $remote_fs $local_fs $network $syslog $time
# Required-Stop:     $remote_fs $local_fs $network $syslog $time
% if ( @{ $opt->{'should-start'} } )
% {
# Should-Start:      <%= join(' ', @{ $opt->{'should-start'} } ) %>
% }
% if ( @{ $opt->{'should-stop'} } )
% {
# Should-Stop:       <%= join(' ', @{ $opt->{'should-stop'} } ) %>
% }
# Default-Start:     <%= join(' ', @{ $opt->{'runlevels'} } ) %>
# Default-Stop:      <%= join(' ', @{ $opt->{'stoplevels'} } ) %>
# Short-Description: starts <%= $name %> application
# Description:       starts <%= $name %> application
### END INIT INFO

set -e

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=<%= $opt->{'app_script'} %>
NAME=<%= $name %>
DESC=<%= $name %>

MODE="daemon_prefork"
PIDFILE="/var/run/<%= $name %>.pid"
EXTRA_ARGS=""
USER="nobody"

# Include nginx defaults if available
if [ -f /etc/default/<%= $name %> ] ; then
        . /etc/default/<%= $name %>
fi

DAEMON_ARGS="$MODE --daemonize --pid $PIDFILE --user $USER $EXTRA_ARGS"

. /lib/lsb/init-functions

do_start() {
		start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_ARGS
}

do_stop() {
		start-stop-daemon --stop --quiet --pidfile $PIDFILE
}

case "$1" in
	start)
		log_daemon_msg "Starting $DESC" "$NAME"
		do_start
		log_end_msg $?
		;;
	stop)
		log_daemon_msg "Stopping $DESC" "$NAME"
		do_stop
		log_end_msg $?
		;;
	restart|force-reload)
		log_daemon_msg "Restarting $DESC" "$NAME"
		do_stop
		do_start
		log_end_msg $?
		;;
	status)
		status_of_proc -p $PIDFILE $DAEMON $NAME && exit 0 || exit $?
		;;
	*)
		echo "Usage: $NAME {start|stop|restart|force-reload|status}" >&2
		exit 1
		;;

esac

exit 0

@@ config
% my $opt = shift;
% my $name = $opt->{'name'};

MODE="daemon_prefork"
PIDFILE="/var/run/<%= $name %>.pid"
EXTRA_ARGS=""
USER="nobody"

__END__

=head1 NAME

Mojo::Command::Generate::InitScript::Debian - Initscript generator for Linux Debian

=head1 SYNOPSYS

	$ ./mojo_app.pl generate help init_script debian
	usage: ./mojo_app.pl generate init_script target_os [OPTIONS]

	These options are available:
		--output <folder>   Set folder to output initscripts
		--deploy            Deploy initscripts into OS
							Either --deploy or --output=dist should be specified

		--name <name>       Ovewrite name which is used for initscript filename(s)

	Debian initscript related options:
		--should-start <applist>    defines facilities which, if present,
									should be available during startup of this service
		--should-stop <applist>     facilities which should be available
									during shutdown of this service.
		--runlevels  <runlevels>    which run levels should by default run the init script
									with a start (stop) argument to start (stop)
									(Default: 2 3 4 5)

=cut

lib/Mojo/Command/Generate/InitScript/Freebsd.pm  view on Meta::CPAN

package Mojo::Command::Generate::InitScript::Freebsd;

use warnings;
use strict;
use File::Spec;

#use base 'Mojo::Command::Generate::InitScript::Base';
use base 'Mojo::Command';
use Getopt::Long 'GetOptions';
use File::Spec;
use IO::File;

__PACKAGE__->attr(usage => <<"EOF");
FreeBSD related initscript options:
    --before <applist>         Defines services which 
                               should start after this initscript
                               for example: --before nginx
    --requre <applist>         Defines services which
                               should be started before this initscript
                               for example: --requre postgresql
EOF

sub run
{
	my ( $self, $opt ) = @_;

	$opt->{'before'}  = [];
	$opt->{'require'} = [];

	GetOptions($opt,
		'before=s{,}', 'require=s{,}',
	);

	my $rc_file = $opt->{'deploy'}
				? '/usr/local/etc/rc.d/'. $opt->{'name'}
				: File::Spec->join($opt->{'output'}, $opt->{'name'});
	$self->render_to_file( 'initscript', $rc_file, $opt );
	$self->chmod_file( $rc_file, 0755 );

	# update /etc/rc.conf
	$self->update_rc_conf( $opt->{'name'} ) if $opt->{'deploy'};
}

sub update_rc_conf
{
	my ( $self, $name ) = @_;

	my $fh = IO::File->new();
	$fh->open('/etc/rc.conf', '+<') or die qq{Can't open /etc/rc.conf\n};
	my $current_pos = 0;
	my @lines = ();
	my $read_lines = 0;
	my $update_from_pos = undef;
	my $already_done = 0;
	while ( my $line = $fh->getline )
	{
		chomp $line;
		if ( $read_lines )
		{
			push @lines, $line;
			next;
		}
		if ( $line =~ m/^\Q$name\E_enable="(.*?)"$/i )
		{
			if ( $1 =~ /^yes$/i )
			{
				$already_done = 1;
				last;
			}
			$update_from_pos = $current_pos;
			$read_lines = 1;
		}
		$current_pos = $fh->tell;
	}

	if ( ! $already_done )
	{
		if ( defined $update_from_pos )
		{
			$fh->seek( $update_from_pos, 0 );
		}
		$fh->print("\n") if $fh->eof;
		$fh->print($name, '_enable="YES"', "\n");
		if ( @lines )
		{
			$fh->print( join("\n", @lines) );
		}
		$fh->truncate( $fh->tell );
	}
	close $fh;
}

1;
__DATA__
@@ initscript
% my $opt = shift;
% my $name = $opt->{'name'};
#!/bin/sh
# PROVIDE: <%= $name %>
% if ( @{ $opt->{'before'} } )
% {
# BEFORE: <%= join(' ', @{ $opt->{'before'} }) %>
% }
# REQUIRE: NETWORKING<%= @{ $opt->{'require'} } ? ' '.join(' ', @{ $opt->{'require'} }) : '' %>
# KEYWORD: shutdown

. /etc/rc.subr

name="<%= $name %>"

rcvar=`set_rcvar`

load_rc_config $name

: ${<%= $name %>_enable="NO"}
: ${<%= $name %>_pidfile="/var/tmp/<%= $name %>.pid"}
: ${<%= $name %>_mode="daemon_prefork"}
: ${<%= $name %>_args=""}
: ${<%= $name %>_user="nobody"}

command="<%= $opt->{'app_script'} %>"
extra_commands="reload"
pidfile="${<%= $name %>_pidfile}"
sig_reload="USR1"
command_args="${<%= $name %>_mode} --daemonize --pid ${<%= $name %>_pidfile} --user ${<%= $name %>_user} ${<%= $name %>_args}"
procname="perl"

run_rc_command "$1"

__END__

=head1 NAME

Mojo::Command::Generate::InitScript::Freebsd - Initscript generator for FreeBSD

=head1 SYNOPSYS

	$ ./mojo_app.pl generate help init_script freebsd
	usage: ./mojo_app.pl generate init_script target_os [OPTIONS]

	These options are available:
		--output <folder>   Set folder to output initscripts
		--deploy            Deploy initscripts into OS
							Either --deploy or --output=dist should be specified

		--name <name>       Ovewrite name which is used for initscript filename(s)

	FreeBSD related initscript options:
		--before <applist>         Defines services which
								   should start after this initscript
								   for example: --before nginx
		--requre <applist>         Defines services which
								   should be started before this initscript
								   for example: --requre postgresql

=cut

t/00-load.t  view on Meta::CPAN

#!perl

use Test::More tests => 1;

BEGIN {
    use_ok( 'Mojo::Command::Generate::InitScript' ) || print "Bail out!
";
}

diag( "Testing Mojo::Command::Generate::InitScript $Mojo::Command::Generate::InitScript::VERSION, Perl $], $^X" );

t/boilerplate.t  view on Meta::CPAN

#!perl -T

use strict;
use warnings;
use Test::More tests => 3;

sub not_in_file_ok {
    my ($filename, %regex) = @_;
    open( my $fh, '<', $filename )
        or die "couldn't open $filename for reading: $!";

    my %violated;

    while (my $line = <$fh>) {
        while (my ($desc, $regex) = each %regex) {
            if ($line =~ $regex) {
                push @{$violated{$desc}||=[]}, $.;
            }
        }
    }

    if (%violated) {
        fail("$filename contains boilerplate text");
        diag "$_ appears on lines @{$violated{$_}}" for keys %violated;
    } else {
        pass("$filename contains no boilerplate text");
    }
}

sub module_boilerplate_ok {
    my ($module) = @_;
    not_in_file_ok($module =>
        'the great new $MODULENAME'   => qr/ - The great new /,
        'boilerplate description'     => qr/Quick summary of what the module/,
        'stub function definition'    => qr/function[12]/,
    );
}

TODO: {
  local $TODO = "Need to replace the boilerplate text";

  not_in_file_ok(README =>
    "The README is used..."       => qr/The README is used/,
    "'version information here'"  => qr/to provide version information/,
  );

  not_in_file_ok(Changes =>
    "placeholder date/time"       => qr(Date/time)
  );

  module_boilerplate_ok('lib/Mojo/Command/Generate/InitScript.pm');


}

t/manifest.t  view on Meta::CPAN

#!perl -T

use strict;
use warnings;
use Test::More;

unless ( $ENV{RELEASE_TESTING} ) {
    plan( skip_all => "Author tests not required for installation" );
}

eval "use Test::CheckManifest 0.9";
plan skip_all => "Test::CheckManifest 0.9 required" if $@;
ok_manifest();

t/pod-coverage.t  view on Meta::CPAN

use strict;
use warnings;
use Test::More;

# Ensure a recent version of Test::Pod::Coverage
my $min_tpc = 1.08;
eval "use Test::Pod::Coverage $min_tpc";
plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage"
    if $@;
plan skip_all => 'set TEST_POD to enable this test (developer only!)'
  unless $ENV{TEST_POD};


all_pod_coverage_ok();

t/pod.t  view on Meta::CPAN

#!perl -T

use strict;
use warnings;
use Test::More;

# Ensure a recent version of Test::Pod
my $min_tp = 1.22;
eval "use Test::Pod $min_tp";
plan skip_all => "Test::Pod $min_tp required for testing POD" if $@;
plan skip_all => 'set TEST_POD to enable this test (developer only!)'
  unless $ENV{TEST_POD};


all_pod_files_ok();



( run in 0.313 second using v1.01-cache-2.11-cpan-7add2cbd662 )