Update version according to OSCI-856
[packages/precise/mcollective.git] / plugins / mcollective / pluginpackager / rpmpackage_packager.rb
1 module MCollective
2   module PluginPackager
3     class RpmpackagePackager
4       require 'erb'
5
6       def initialize(plugin, pluginpath = nil, signature = nil, verbose = false, keep_artifacts = nil)
7         if @buildtool = select_command
8           @plugin = plugin
9           @package_name = "#{@plugin.mcname}-#{@plugin.metadata[:name]}"
10           @package_name_and_version = "#{@package_name}-#{@plugin.metadata[:version]}"
11           @verbose = verbose
12           @libdir = pluginpath || '/usr/libexec/mcollective/mcollective/'
13           @signature = signature
14           @rpmdir = rpmdir
15           @srpmdir = srpmdir
16           @keep_artifacts = keep_artifacts
17         else
18           raise("Cannot build package. 'rpmbuild' or 'rpmbuild-md5' is not present on the system")
19         end
20       end
21
22       # Determine the build tool present on the system
23       def select_command
24         if PluginPackager.command_available?('rpmbuild-md5')
25           return 'rpmbuild-md5'
26         elsif PluginPackager.command_available?('rpmbuild')
27           return 'rpmbuild'
28         else
29           return nil
30         end
31       end
32
33       def rpmdir
34         `rpm --eval '%_rpmdir'`.chomp
35       end
36
37       def srpmdir
38         `rpm --eval '%_srcrpmdir'`.chomp
39       end
40
41       # Build Process :
42       # - create temporary buildroot
43       # - create the spec file
44       # - create the tarball
45       # - run the build script
46       # - move pacakges to cwd
47       # - clean up
48       def create_packages
49         begin
50           puts "Building packages for #{@package_name} plugin."
51
52           @tmpdir = Dir.mktmpdir('mcollective_packager')
53           prepare_tmpdirs
54
55           make_spec_file
56           run_build
57           move_packages
58
59           puts "Completed building all packages for #{@package_name} plugin."
60         ensure
61           if @keep_artifacts
62             puts 'Keeping build artifacts'
63             puts "Build artifacts saved - #{@tmpdir}"
64           else
65             cleanup_tmpdirs
66           end
67         end
68       end
69
70       private
71
72       def run_build
73         begin
74           tarfile = create_tar
75           PluginPackager.execute_verbosely(@verbose) do
76             PluginPackager.safe_system("#{@buildtool} -ta#{" --quiet" unless @verbose}#{" --sign" if @signature} #{tarfile}")
77           end
78         rescue => e
79           puts 'Build process has failed'
80           raise e
81         end
82       end
83
84       # Tar up source
85       # Expects directory $mcollective-$agent-$version
86       # Creates file : $tmpbuildroot/$mcollective-$agent-$version
87       def create_tar
88         tarfile = File.join(@tmpdir, "#{@package_name_and_version}.tgz")
89         begin
90          PluginPackager.execute_verbosely(@verbose) do
91             Dir.chdir(@tmpdir) do
92               PluginPackager.safe_system("tar -cvzf #{tarfile} #{@package_name_and_version}")
93             end
94           end
95         rescue => e
96           puts "Could not create tarball - '#{tarfile}'"
97           raise e
98         end
99         tarfile
100       end
101
102       # Move rpm's and srpm's to cwd
103       def move_packages
104         begin
105           files_to_copy = Dir.glob(File.join(@rpmdir, 'noarch', "#{@package_name}-*-#{@plugin.metadata[:version]}-#{@plugin.revision}.noarch.rpm"))
106           files_to_copy << File.join(@srpmdir, "#{@package_name}-#{@plugin.metadata[:version]}-#{@plugin.revision}.src.rpm")
107           FileUtils.cp(files_to_copy, '.')
108         rescue => e
109           puts 'Could not copy packages to working directory'
110           raise e
111         end
112       end
113
114       # Create the specfile and place as $tmpbuildroot/$mcollective-$agent-$version/$mcollective-$agent-$version.spec
115       def make_spec_file
116         spec_file = File.join(@tmpdir, @package_name_and_version, "#{@package_name_and_version}.spec")
117         begin
118           spec_template = ERB.new(File.read(File.join(File.dirname(__FILE__), 'templates', 'redhat', 'rpm_spec.erb')), nil, '-')
119           File.open(spec_file, 'w') do |f|
120             f.puts spec_template.result(binding)
121           end
122         rescue => e
123           puts "Could not create specfile - '#{spec_file}'"
124           raise e
125         end
126       end
127
128       # Move files contained in the plugin to the correct directory
129       # relative to the build root.
130       def prepare_tmpdirs
131         plugin_files.each do |file|
132           begin
133             targetdir = File.join(@tmpdir, @package_name_and_version, @libdir, File.dirname(File.expand_path(file)).gsub(@plugin.target_path, ""))
134             FileUtils.mkdir_p(targetdir) unless File.directory?(targetdir)
135             FileUtils.cp_r(file, targetdir)
136           rescue Errno::EACCES => e
137             puts "Could not create directory '#{targetdir}'. Permission denied"
138             raise e
139           rescue Errno::ENOENT => e
140             puts "Could not copy file '#{file}' to '#{targetdir}'. File does not exist"
141             raise e
142           rescue => e
143             puts 'Could not prepare temporary build directory'
144             raise e
145           end
146         end
147       end
148
149       # Extract all the package files from the plugin's package data hash
150       def plugin_files
151         files = []
152         @plugin.packagedata.each do |name, data|
153           files += data[:files].reject{ |f| File.directory?(f) }
154         end
155         files
156       end
157
158       # Extract the package specific files from the file list and omits directories
159       def package_files(files)
160         package_files = []
161         files.each do |f|
162           if !File.directory?(f)
163             package_files << File.join(@libdir, File.expand_path(f).gsub(/#{@plugin.target_path}|\.\//, ''))
164           end
165         end
166         package_files
167       end
168
169       def cleanup_tmpdirs
170         begin
171           FileUtils.rm_r(@tmpdir) if File.directory?(@tmpdir)
172         rescue => e
173           puts "Could not remove temporary build directory - '#{@tmpdir}'"
174           raise e
175         end
176       end
177     end
178   end
179 end