File Coverage

blib/lib/Rex/Repositorio/Repository/Yum.pm
Criterion Covered Total %
statement 30 143 20.9
branch 0 14 0.0
condition 0 9 0.0
subroutine 10 23 43.4
pod n/a
total 40 189 21.1


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   1765 use Moose;
  1         3  
  1         9  
10 1     1   6037 use Try::Tiny;
  1         3  
  1         64  
11 1     1   4 use File::Basename qw'basename';
  1         2  
  1         55  
12 1     1   761 use Data::Dumper;
  1         5964  
  1         79  
13 1     1   8 use Carp;
  1         2  
  1         50  
14 1     1   4 use Params::Validate qw(:all);
  1         2  
  1         182  
15 1     1   4 use File::Spec;
  1         3  
  1         20  
16 1     1   3 use File::Path;
  1         2  
  1         47  
17 1     1   563 use IO::All;
  1         9400  
  1         7  
18 1     1   683 use JSON::XS;
  1         3549  
  1         1327  
19              
20             our $VERSION = '0.6.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           my %option = %{ $_option };
  0            
137              
138 0           my $i = 0;
139 0           print "\n";
140 0           print "\n";
141 0           my $pr = $self->app->progress_bar(
142             title => "Downloading packages...",
143             length => scalar(@packages),
144             );
145              
146 0           for my $package (@packages) {
147 0           $i++;
148 0           $pr->update($i);
149              
150 0           my $package_url = $self->repo->{url} . "/" . $package->{location};
151 0           my $package_name = $package->{name};
152              
153 0           my $local_file = $self->repo->{local} . "/" . $package->{location};
154             $self->download_package(
155             url => $package_url,
156             name => $package_name,
157             dest => $local_file,
158             cb => sub {
159 0     0     $self->_checksum(
160             @_,
161             $package->{checksum}->{type},
162             $package->{checksum}->{data}
163             );
164             },
165 0           force => $option{update_files}
166             );
167             }
168             }
169              
170             sub _get_repomd_xml {
171 0     0     my ($self, $url) = @_;
172              
173 0           my $repomd_ref =
174             $self->decode_xml(
175             $self->download( "$url/repodata/repomd.xml" ) );
176              
177 0           my ($primary_file) =
178 0           grep { $_->{type} eq "primary" } @{ $repomd_ref->{data} };
  0            
179 0           $primary_file = $primary_file->{location}->[0]->{href};
180              
181 0           $url = $url . "/" . $primary_file;
182 0           $self->app->logger->debug("Downloading $url.");
183 0           my $xml = $self->get_xml( $self->download_gzip($url) );
184              
185 0           my @packages;
186 0           my @xml_packages = $xml->getElementsByTagName('package');
187 0           for my $xml_package (@xml_packages) {
188 0           my ($name_node) = $xml_package->getChildrenByTagName("name");
189 0           my ($checksum_node) = $xml_package->getChildrenByTagName("checksum");
190 0           my ($size_node) = $xml_package->getChildrenByTagName("size");
191 0           my ($location_node) = $xml_package->getChildrenByTagName("location");
192 0           push @packages,
193             {
194             location => $location_node->getAttribute("href"),
195             name => $name_node->textContent,
196             checksum => {
197             type => $checksum_node->getAttribute("type"),
198             data => $checksum_node->textContent,
199             },
200             size => $size_node->getAttribute("archive"),
201             };
202             }
203              
204 0           return (\@packages, $repomd_ref);
205             }
206              
207             sub init {
208 0     0     my $self = shift;
209              
210 0           my $repo_dir = $self->app->get_repo_dir( repo => $self->repo->{name} );
211 0           mkpath "$repo_dir/repodata";
212              
213 0           $self->_run_createrepo();
214             }
215              
216             sub add_file {
217 0     0     my $self = shift;
218 0           my %option = validate(
219             @_,
220             {
221             file => {
222             type => SCALAR
223             },
224             }
225             );
226              
227 0           my $dest = $self->app->get_repo_dir( repo => $self->repo->{name} ) . "/"
228             . basename( $option{file} );
229              
230 0           $self->add_file_to_repo( source => $option{file}, dest => $dest );
231              
232 0           $self->_run_createrepo();
233             }
234              
235             sub remove_file {
236 0     0     my $self = shift;
237              
238 0           my %option = validate(
239             @_,
240             {
241             file => {
242             type => SCALAR
243             },
244             }
245             );
246              
247 0           my $file = $self->app->get_repo_dir( repo => $self->repo->{name} ) . "/"
248             . basename( $option{file} );
249              
250 0           $self->remove_file_from_repo( file => $file );
251              
252 0           $self->_run_createrepo();
253             }
254              
255             sub _run_createrepo {
256 0     0     my $self = shift;
257              
258 0           my $repo_dir = $self->app->get_repo_dir( repo => $self->repo->{name} );
259              
260 0 0 0       if ( exists $self->repo->{gpg} && $self->repo->{gpg}->{key} ) {
261 0           unlink "$repo_dir/repodata/repomd.xml.asc";
262             }
263              
264 0           system "cd $repo_dir ; createrepo .";
265 0 0         if ( $? != 0 ) {
266 0           confess "Error running createrepo.";
267             }
268              
269 0 0 0       if ( exists $self->repo->{gpg} && $self->repo->{gpg}->{key} ) {
270 0           my $key = $self->repo->{gpg}->{key};
271 0           my $pass = $self->repo->{gpg}->{password};
272 0 0         if ( !$pass ) {
273 0           $pass = $self->read_password("GPG key passphrase: ");
274             }
275              
276 0           my $cmd =
277             "cd $repo_dir ; gpg --default-key $key -a --batch --passphrase '"
278             . $pass
279             . "' --detach-sign repodata/repomd.xml";
280 0           system $cmd;
281              
282 0 0         if ( $? != 0 ) {
283 0           $cmd =~ s/\Q$pass\E/\*\*\*\*\*\*\*/;
284 0           confess "Error running: $cmd";
285             }
286              
287             # export pub key as asc file
288 0           my $pub_file = $self->repo->{name} . ".asc";
289 0           $cmd = "cd $repo_dir ; gpg -a --output $pub_file --export $key";
290 0           system $cmd;
291              
292 0 0         if ( $? != 0 ) {
293 0           confess "Error running gpg export: $cmd";
294             }
295             }
296             }
297              
298             # test if all necessary parameters are available
299             override verify_options => sub {
300             my $self = shift;
301             super();
302              
303             if ( !exists $self->repo->{local} ) {
304             confess "No local path (local) given for: " . $self->repo->{name};
305             }
306             };
307              
308             1;