File Coverage

blib/lib/Rex/Apache/Deploy/Symlink.pm
Criterion Covered Total %
statement 48 132 36.3
branch 0 48 0.0
condition 0 3 0.0
subroutine 16 29 55.1
pod 7 8 87.5
total 71 220 32.2


line stmt bran cond sub pod time code
1             #
2             # (c) Jan Gehring
3             #
4             # vim: set ts=2 sw=2 tw=0:
5             # vim: set expandtab:
6              
7             =head1 NAME
8              
9             Rex::Apache::Deploy::Symlink - Deploy application and symlink to live
10              
11             =head1 DESCRIPTION
12              
13             With this module you can deploy an application to a special folder and after that you can symlink it to the document root.
14              
15             =head1 SYNOPSIS
16              
17             generate_deploy_directory {
18             my ($file) = @_;
19             $file =~ m/(\d+\.\d+)/;
20             return $1;
21             };
22              
23             deploy_to "/data/myapp";
24             document_root "/var/www/html";
25              
26             task "dodeploy", "server1", sub {
27             deploy "myapp-1.2.tar.gz";
28             };
29              
30             task "dodeploy", "server1", sub {
31             deploy "myapp",
32             version => "1.2";
33             };
34              
35             =head1 FUNCTIONS
36              
37             =over 4
38              
39             =cut
40              
41             package Rex::Apache::Deploy::Symlink;
42              
43 1     1   1868 use strict;
  1         3  
  1         27  
44 1     1   6 use warnings;
  1         1  
  1         29  
45              
46 1     1   6 use Rex::Commands::Run;
  1         1  
  1         10  
47 1     1   93 use Rex::Commands::Fs;
  1         2  
  1         8  
48 1     1   427 use Rex::Commands::Upload;
  1         2  
  1         6  
49 1     1   55 use Rex::Commands;
  1         3  
  1         7  
50 1     1   896 use File::Basename qw(dirname basename);
  1         1  
  1         62  
51              
52 1     1   6 use Rex::Apache::Build;
  1         2  
  1         94  
53              
54 1     1   5 use File::Basename qw(basename);
  1         3  
  1         41  
55 1     1   6 use Cwd qw(getcwd);
  1         2  
  1         48  
56              
57             #require Exporter;
58             #use base qw(Exporter);
59              
60 1     1   5 use vars qw(@EXPORT $deploy_to $document_root $generate_deploy_directory);
  1         2  
  1         305  
61             @EXPORT = qw(deploy get_live_version get_deploy_directory_for
62             deploy_to generate_deploy_directory document_root
63             list_versions switch_to_version);
64              
65             ############ deploy functions ################
66              
67             =item deploy($file, %option)
68              
69             This function will do the deployment. It uploads the file to the target server and extract it to the directory given by I concatenated with the return value of I.
70              
71             task "dodeploy", "server1", sub {
72             deploy "myapp-1.2.tar.gz";
73             };
74              
75             task "dodeploy", "server1", sub {
76             deploy "myapp",
77             version => "1.2";
78             };
79              
80              
81             =cut
82              
83             sub deploy {
84 0     0 1   my ( $file, %option ) = @_;
85              
86 0 0         if ( !%option ) {
87 0 0         if ( Rex::Config->get("package_option") ) {
88 0           %option = %{ Rex::Config->get("package_option") };
  0            
89             }
90             }
91              
92 0           my $options = \%option;
93              
94 0 0         unless ($file) {
95              
96             # if no file is given, use directory name
97 0           $file = basename( getcwd() );
98             }
99              
100 0 0         unless ( -f $file ) {
101 0           my $version = get_version();
102              
103 0 0         if ( exists $options->{version} ) {
104 0           $version = $options->{version};
105             }
106              
107             # if file doesn't exists, try to find it
108 0 0         if ( -f "$file.tar.gz" ) {
    0          
109 0           $file = "$file.tar.gz";
110             }
111             elsif ( -f "$file-$version.tar.gz" ) {
112 0           $file = "$file-$version.tar.gz";
113             }
114             else {
115 0           Rex::Logger::debug("No file found to deploy ($file)");
116 0           die("File $file not found.");
117             }
118             }
119              
120 1     1   6 no strict;
  1         2  
  1         29  
121 1     1   7 no warnings;
  1         3  
  1         118  
122 0           my $rnd_file = get_random( 8, a .. z, 0 .. 9 );
123 1     1   6 use strict;
  1         3  
  1         30  
124 1     1   5 use warnings;
  1         2  
  1         1040  
125              
126 0 0         unless ( is_dir($deploy_to) ) {
127 0           mkdir $deploy_to;
128             }
129              
130 0 0         unless ( is_writeable($deploy_to) ) {
131 0           Rex::Logger::info("No write permission to $deploy_to");
132 0           exit 1;
133             }
134              
135 0 0         unless ( is_writeable( dirname($document_root) ) ) {
136 0           Rex::Logger::info("No write permission to $document_root");
137 0           exit 1;
138             }
139              
140 0           my $deploy_dir = get_deploy_directory_for($file);
141 0           Rex::Logger::debug("deploy_dir: $deploy_dir");
142              
143 0 0 0       if ( get_live_version() && get_live_version() eq basename($deploy_dir) ) {
144 0           Rex::Logger::info(
145             "Sorry, you try to deploy to a version that is currently live.");
146 0           exit 1;
147             }
148              
149 0           Rex::Logger::debug( "Uploadling $file to /tmp/$rnd_file" . _get_ext($file) );
150 0           upload( $file, "/tmp/$rnd_file" . _get_ext($file) );
151              
152 0           mkdir $deploy_dir;
153              
154 0           run "cd $deploy_dir; "
155             . sprintf( _get_extract_command($file),
156             "/tmp/$rnd_file" . _get_ext($file) );
157              
158 0           Rex::Logger::debug( "Unlinking /tmp/$rnd_file" . _get_ext($file) );
159 0           unlink "/tmp/$rnd_file" . _get_ext($file);
160             }
161              
162             =item list_versions
163              
164             This function returns all available versions from the directory defined by I as an array.
165              
166             =cut
167              
168             sub list_versions {
169 0     0 1   return grep { !/^\./ } list_files($deploy_to);
  0            
170             }
171              
172             =item switch_to_version($new_version)
173              
174             This function switches to the given version.
175              
176             task "switch", "server1", sub {
177             my $param = shift;
178              
179             switch_to_version $param->{version};
180             };
181              
182             =cut
183              
184             sub switch_to_version {
185 0     0 1   my ($new_version) = @_;
186              
187 0           my @versions = list_versions;
188 0 0         if ( !grep { /$new_version/ } @versions ) {
  0            
189 0           Rex::Logger::info("no version found!");
190 0           return;
191             }
192              
193 0           run "ln -snf $deploy_to/$new_version $document_root";
194             }
195              
196             =item get_live_version
197              
198             This function returns the current live version.
199              
200             =cut
201              
202             sub get_live_version {
203 0     0 1   my $link = eval { return readlink $document_root; };
  0            
204              
205 0 0         return basename($link) if ($link);
206             }
207              
208             ############ configuration functions #############
209              
210             sub get_deploy_directory_for {
211 0     0 0   my ($file) = @_;
212              
213 0 0         unless ($generate_deploy_directory) {
214             $generate_deploy_directory = sub {
215 0     0     my ($file) = @_;
216 0 0         if ( $file =~ m/-([0-9\._~\-]+)\.(zip|tar\.gz|war|tar\.bz2|jar)$/ ) {
217 0           return $1;
218             }
219             else {
220 0           return "" . time;
221             }
222 0           };
223             }
224 0           my $gen_dir_name = &$generate_deploy_directory($file);
225 0           my $deploy_dir = "$deploy_to/$gen_dir_name";
226              
227 0           return $deploy_dir;
228             }
229              
230             =item deploy_to($directory)
231              
232             This function sets the directory where the uploaded archives should be extracted. This is not the document root of your webserver.
233              
234             deploy_to "/data/myapp";
235              
236             =cut
237              
238             sub deploy_to {
239 0     0 1   $deploy_to = shift;
240             }
241              
242             =item document_root($doc_root)
243              
244             This function sets the document root of your webserver. This will be a symlink to the deployed application.
245              
246             =cut
247              
248             sub document_root {
249 0     0 1   $document_root = shift;
250             }
251              
252             =item generate_deploy_directory(sub{})
253              
254             If you need a special directory naming of your uploaded version you can define it with this function.
255              
256             The default function is:
257              
258             sub {
259             my ($file) = @_;
260             if($file =~ m/-([0-9\._~\-]+)\.(zip|tar\.gz|war|tar\.bz2|jar)$/) {
261             return $1;
262             }
263             else {
264             return "" . time;
265             }
266             };
267              
268              
269             =cut
270              
271             sub generate_deploy_directory(&) {
272 0     0 1   $generate_deploy_directory = shift;
273             }
274              
275             ############ helper functions #############
276              
277             sub _get_extract_command {
278 0     0     my ($file) = @_;
279              
280 0 0         if ( $file =~ m/\.tar\.gz$/ ) {
    0          
    0          
281 0           return "tar xzf %s";
282             }
283             elsif ( $file =~ m/\.zip$/ ) {
284 0           return "unzip -o %s";
285             }
286             elsif ( $file =~ m/\.tar\.bz2$/ ) {
287 0           return "tar xjf %s";
288             }
289              
290 0           die("Unknown Archive Format.");
291             }
292              
293             sub _get_pack_command {
294 0     0     my ($file) = @_;
295              
296 0 0         if ( $file =~ m/\.tar\.gz$/ ) {
    0          
    0          
297 0           return "tar czf %s %s";
298             }
299             elsif ( $file =~ m/\.zip$/ ) {
300 0           return "zip -r %s %s";
301             }
302             elsif ( $file =~ m/\.tar\.bz2$/ ) {
303 0           return "tar cjf %s %s";
304             }
305              
306 0           die("Unknown Archive Format.");
307             }
308              
309             sub _get_ext {
310 0     0     my ($file) = @_;
311              
312 0 0         if ( $file =~ m/\.tar\.gz$/ ) {
    0          
    0          
313 0           return ".tar.gz";
314             }
315             elsif ( $file =~ m/\.zip$/ ) {
316 0           return ".zip";
317             }
318             elsif ( $file =~ m/\.tar\.bz2$/ ) {
319 0           return ".tar.bz2";
320             }
321              
322 0           die("Unknown Archive Format.");
323              
324             }
325              
326             ####### import function #######
327              
328             sub import {
329              
330 1     1   7 no strict 'refs';
  1         2  
  1         138  
331 0     0     for my $func (@EXPORT) {
332 0           Rex::Logger::debug("Registering main::$func");
333 0           *{"$_[1]::$func"} = \&$func;
  0            
334             }
335              
336             }
337              
338             =back
339              
340             =cut
341              
342             1;