Add puppet/archive module, required for newer puppet/rabbitmq
[mirror/dsa-puppet.git] / 3rdparty / modules / archive / lib / puppet_x / bodeco / archive.rb
1 require 'digest'
2 require 'puppet/util/execution'
3 require 'shellwords'
4
5 module PuppetX
6   module Bodeco
7     class Archive
8       def initialize(file)
9         @file = file
10         @file_path = Shellwords.shellescape file
11       end
12
13       def checksum(type)
14         return nil if type == :none
15
16         digest = Digest.const_get(type.to_s.upcase)
17         digest.file(@file).hexdigest
18       rescue LoadError
19         raise $ERROR_INFO, "invalid checksum type #{type}. #{$ERROR_INFO}", $ERROR_INFO.backtrace
20       end
21
22       def root_dir
23         if Facter.value(:osfamily) == 'windows'
24           'C:\\'
25         else
26           '/'
27         end
28       end
29
30       def extract(path = root_dir, opts = {})
31         opts = {
32           custom_command: nil,
33           options: '',
34           uid: nil,
35           gid: nil
36         }.merge(opts)
37
38         custom_command = opts.fetch(:custom_command, nil)
39         options = opts.fetch(:options)
40         Dir.chdir(path) do
41           cmd = if custom_command && custom_command =~ %r{%s}
42                   custom_command % @file_path
43                 elsif custom_command
44                   "#{custom_command} #{options} #{@file_path}"
45                 else
46                   command(options)
47                 end
48
49           Puppet.debug("Archive extracting #{@file} in #{path}: #{cmd}")
50           File.chmod(0o644, @file) if opts[:uid] || opts[:gid]
51           Puppet::Util::Execution.execute(cmd, uid: opts[:uid], gid: opts[:gid], failonfail: true, squelch: false, combine: true)
52         end
53       end
54
55       private
56
57       def win_7zip
58         if ENV['path'].include?('7-Zip')
59           '7z.exe'
60         elsif File.directory?('C:\\Program Files\\7-Zip')
61           'C:\\Program Files\\7-Zip\\7z.exe'
62         elsif File.directory?('C:\\Program Files (x86)\\7-zip')
63           'C:\\Program Files (x86)\\7-Zip\\7z.exe'
64         else
65           raise Exception, '7z.exe not available'
66         end
67       end
68
69       def command(options)
70         if Facter.value(:osfamily) == 'windows'
71           opt = parse_flags('x -aoa', options, '7z')
72           "#{win_7zip} #{opt} #{@file_path}"
73         else
74           case @file
75           when %r{\.tar$}
76             opt = parse_flags('xf', options, 'tar')
77             "tar #{opt} #{@file_path}"
78           when %r{(\.tgz|\.tar\.gz)$}
79             case Facter.value(:osfamily)
80             when 'Solaris', 'AIX'
81               gunzip_opt = parse_flags('-dc', options, 'gunzip')
82               tar_opt = parse_flags('xf', options, 'tar')
83               "gunzip #{gunzip_opt} #{@file_path} | tar #{tar_opt} -"
84             else
85               opt = parse_flags('xzf', options, 'tar')
86               "tar #{opt} #{@file_path}"
87             end
88           when %r{(\.tbz|\.tar\.bz2)$}
89             case Facter.value(:osfamily)
90             when 'Solaris', 'AIX'
91               bunzip_opt = parse_flags('-dc', options, 'bunzip')
92               tar_opt = parse_flags('xf', options, 'tar')
93               "bunzip2 #{bunzip_opt} #{@file_path} | tar #{tar_opt} -"
94             else
95               opt = parse_flags('xjf', options, 'tar')
96               "tar #{opt} #{@file_path}"
97             end
98           when %r{(\.txz|\.tar\.xz)$}
99             unxz_opt = parse_flags('-dc', options, 'unxz')
100             tar_opt = parse_flags('xf', options, 'tar')
101             "unxz #{unxz_opt} #{@file_path} | tar #{tar_opt} -"
102           when %r{\.gz$}
103             opt = parse_flags('-d', options, 'gunzip')
104             "gunzip #{opt} #{@file_path}"
105           when %r{(\.zip|\.war|\.jar)$}
106             opt = parse_flags('-o', options, 'zip')
107             "unzip #{opt} #{@file_path}"
108           else
109             raise NotImplementedError, "Unknown filetype: #{@file}"
110           end
111         end
112       end
113
114       def parse_flags(default, options, command = nil)
115         case options
116         when :undef
117           default
118         when ::String
119           options
120         when ::Hash
121           options[command]
122         else
123           raise ArgumentError, "Invalid options for command #{command}: #{options.inspect}"
124         end
125       end
126     end
127   end
128 end