File Coverage

blib/lib/Rex/Repositorio/Repository/Yum.pm
Criterion Covered Total %
statement 30 145 20.6
branch 0 16 0.0
condition 0 12 0.0
subroutine 10 23 43.4
pod n/a
total 40 196 20.4


line stmt bran cond sub pod time code
1             #
2             # (c) Jan Gehring <jan.gehring@gmail.com>
3             #
4             # vim: set ts=2 sw=2 tw=0:
5             # vim: set expandtab:
6              
7             package Rex::Repositorio::Repository::Yum;
8              
9 1     1   1494 use Moose;
  1         2  
  1         6  
10 1     1   4192 use Try::Tiny;
  1         2  
  1         54  
11 1     1   5 use File::Basename qw'basename';
  1         1  
  1         50  
12 1     1   591 use Data::Dumper;
  1         3986  
  1         77  
13 1     1   9 use Carp;
  1         1  
  1         43  
14 1     1   4 use Params::Validate qw(:all);
  1         1  
  1         175  
15 1     1   5 use File::Spec;
  1         1  
  1         17  
16 1     1   3 use File::Path;
  1         1  
  1         36  
17 1     1   494 use IO::All;
  1         7875  
  1         8  
18 1     1   650 use JSON::XS;
  1         2938  
  1         1022  
19              
20             our $VERSION = '0.7.0'; # VERSION
21              
22             extends "Rex::Repositorio::Repository::Base";
23              
24             sub mirror {
25 0     0     my ( $self, %option ) = @_;
26              
27 0           $self->repo->{url} =~ s/\/$//;
28 0           $self->repo->{local} =~ s/\/$//;
29 0           my $name = $self->repo->{name};
30              
31 0           my $pr = $self->app->progress_bar(
32             title => "Downloading metadata...",
33             length => 3,
34             );
35              
36 0           my ( $packages_ref, $repomd_ref );
37 0           ( $packages_ref, $repomd_ref ) = $self->_get_repomd_xml( $self->repo->{url} );
38 0           my @packages = @{$packages_ref};
  0            
39              
40             try {
41 0     0     $self->download_metadata(
42             url => $self->repo->{url} . "/repodata/repomd.xml",
43             dest => $self->repo->{local} . "/repodata/repomd.xml",
44             force => $option{update_metadata},
45             );
46              
47 0           $pr->update(2);
48              
49 0           $self->download_metadata(
50             url => $self->repo->{url} . "/repodata/repomd.xml.asc",
51             dest => $self->repo->{local} . "/repodata/repomd.xml.asc",
52             force => $option{update_metadata},
53             );
54              
55 0           $pr->update(3);
56             }
57             catch {
58 0     0     $pr->update(3);
59 0           $self->app->logger->error($_);
60 0           };
61              
62 0           $self->_download_packages( \%option, @packages );
63              
64 0           print "\n";
65 0           print "\n";
66 0           $pr = $self->app->progress_bar(
67             title => "Downloading rest of metadata...",
68 0           length => scalar( @{ $repomd_ref->{data} } ),
69             );
70              
71 0           my $mi = 0;
72 0           for my $file_data ( @{ $repomd_ref->{data} } ) {
  0            
73 0           $mi++;
74 0           $pr->update($mi);
75              
76 0           my $file_url =
77             $self->{repo}->{url} . "/" . $file_data->{location}->[0]->{href};
78 0           my $file = basename $file_data->{location}->[0]->{href};
79              
80             $self->download_metadata(
81             url => $file_url,
82             dest => $self->repo->{local} . "/repodata/$file",
83             cb => sub {
84 0     0     $self->_checksum(
85             @_,
86             $file_data->{checksum}->[0]->{type},
87             $file_data->{checksum}->[0]->{content}
88             );
89             },
90 0           force => $option{update_metadata},
91             );
92             }
93              
94 0 0 0       if ( exists $self->repo->{images} && $self->repo->{images} eq "true" ) {
95              
96 0           print "\n";
97 0           print "\n";
98 0           $pr = $self->app->progress_bar(
99             title => "Downloading images...",
100             length => 7,
101             );
102              
103 0           my $ii = 0;
104 0           for my $file (
105             (
106             "images/boot.iso", "images/efiboot.img",
107             "images/efidisk.img", "images/install.img",
108             "images/pxeboot/initrd.img", "images/pxeboot/vmlinuz",
109             "images/upgrade.img",
110             )
111             )
112             {
113 0           $ii++;
114 0           $pr->update($ii);
115              
116 0           my $file_url = $self->repo->{url} . "/" . $file;
117 0           my $local_file = $self->repo->{local} . "/" . $file;
118             try {
119 0     0     $self->download_package(
120             url => $file_url,
121             name => $file,
122             dest => $local_file,
123             );
124 0           1;
125             }
126             catch {
127 0     0     $self->app->logger->error("Error downloading $file_url.");
128 0           };
129             }
130             }
131             }
132              
133             sub _download_packages {
134 0     0     my ( $self, $_option, @packages ) = @_;
135              
136 0 0 0       if ( !$_option->{update_files} && !$_option->{force} ) {
137 0           return;
138             }
139              
140 0           my %option = %{$_option};
  0            
141              
142 0           my $i = 0;
143 0           print "\n";
144 0           print "\n";
145 0           my $pr = $self->app->progress_bar(
146             title => "Downloading packages...",
147             length => scalar(@packages),
148             );
149              
150 0           for my $package (@packages) {
151 0           $i++;
152 0           $pr->update($i);
153              
154 0           my $package_url = $self->repo->{url} . "/" . $package->{location};
155 0           my $package_name = $package->{name};
156              
157 0           my $local_file = $self->repo->{local} . "/" . $package->{location};
158             $self->download_package(
159             url => $package_url,
160             name => $package_name,
161             dest => $local_file,
162             cb => sub {
163 0     0     $self->_checksum(
164             @_,
165             $package->{checksum}->{type},
166             $package->{checksum}->{data}
167             );
168             },
169 0           update_file => $option{update_files},
170             force => $option{force},
171             );
172             }
173             }
174              
175             sub _get_repomd_xml {
176 0     0     my ( $self, $url ) = @_;
177              
178 0           my $repomd_ref =
179             $self->decode_xml( $self->download("$url/repodata/repomd.xml") );
180              
181 0           my ($primary_file) =
182 0           grep { $_->{type} eq "primary" } @{ $repomd_ref->{data} };
  0            
183 0           $primary_file = $primary_file->{location}->[0]->{href};
184              
185 0           $url = $url . "/" . $primary_file;
186 0           $self->app->logger->debug("Downloading $url.");
187 0           my $xml = $self->get_xml( $self->download_gzip($url) );
188              
189 0           my @packages;
190 0           my @xml_packages = $xml->getElementsByTagName('package');
191 0           for my $xml_package (@xml_packages) {
192 0           my ($name_node) = $xml_package->getChildrenByTagName("name");
193 0           my ($checksum_node) = $xml_package->getChildrenByTagName("checksum");
194 0           my ($size_node) = $xml_package->getChildrenByTagName("size");
195 0           my ($location_node) = $xml_package->getChildrenByTagName("location");
196 0           push @packages,
197             {
198             location => $location_node->getAttribute("href"),
199             name => $name_node->textContent,
200             checksum => {
201             type => $checksum_node->getAttribute("type"),
202             data => $checksum_node->textContent,
203             },
204             size => $size_node->getAttribute("archive"),
205             };
206             }
207              
208 0           return ( \@packages, $repomd_ref );
209             }
210              
211             sub init {
212 0     0     my $self = shift;
213              
214 0           my $repo_dir = $self->app->get_repo_dir( repo => $self->repo->{name} );
215 0           mkpath "$repo_dir/repodata";
216              
217 0           $self->_run_createrepo();
218             }
219              
220             sub add_file {
221 0     0     my $self = shift;
222 0           my %option = validate(
223             @_,
224             {
225             file => {
226             type => SCALAR
227             },
228             }
229             );
230              
231 0           my $dest = $self->app->get_repo_dir( repo => $self->repo->{name} ) . "/"
232             . basename( $option{file} );
233              
234 0           $self->add_file_to_repo( source => $option{file}, dest => $dest );
235              
236 0           $self->_run_createrepo();
237             }
238              
239             sub remove_file {
240 0     0     my $self = shift;
241              
242 0           my %option = validate(
243             @_,
244             {
245             file => {
246             type => SCALAR
247             },
248             }
249             );
250              
251 0           my $file = $self->app->get_repo_dir( repo => $self->repo->{name} ) . "/"
252             . basename( $option{file} );
253              
254 0           $self->remove_file_from_repo( file => $file );
255              
256 0           $self->_run_createrepo();
257             }
258              
259             sub _run_createrepo {
260 0     0     my $self = shift;
261              
262 0           my $repo_dir = $self->app->get_repo_dir( repo => $self->repo->{name} );
263              
264 0 0 0       if ( exists $self->repo->{gpg} && $self->repo->{gpg}->{key} ) {
265 0           unlink "$repo_dir/repodata/repomd.xml.asc";
266             }
267              
268 0           system "cd $repo_dir ; createrepo .";
269 0 0         if ( $? != 0 ) {
270 0           confess "Error running createrepo.";
271             }
272              
273 0 0 0       if ( exists $self->repo->{gpg} && $self->repo->{gpg}->{key} ) {
274 0           my $key = $self->repo->{gpg}->{key};
275 0           my $pass = $self->repo->{gpg}->{password};
276 0 0         if ( !$pass ) {
277 0           $pass = $self->read_password("GPG key passphrase: ");
278             }
279              
280 0           my $cmd =
281             "cd $repo_dir ; gpg --default-key $key -a --batch --passphrase '"
282             . $pass
283             . "' --detach-sign repodata/repomd.xml";
284 0           system $cmd;
285              
286 0 0         if ( $? != 0 ) {
287 0           $cmd =~ s/\Q$pass\E/\*\*\*\*\*\*\*/;
288 0           confess "Error running: $cmd";
289             }
290              
291             # export pub key as asc file
292 0           my $pub_file = $self->repo->{name} . ".asc";
293 0           $cmd = "cd $repo_dir ; gpg -a --output $pub_file --export $key";
294 0           system $cmd;
295              
296 0 0         if ( $? != 0 ) {
297 0           confess "Error running gpg export: $cmd";
298             }
299             }
300             }
301              
302             # test if all necessary parameters are available
303             override verify_options => sub {
304             my $self = shift;
305             super();
306              
307             if ( !exists $self->repo->{local} ) {
308             confess "No local path (local) given for: " . $self->repo->{name};
309             }
310             };
311              
312             1;