Class: Omnibus::Packager::RPM
Constant Summary collapse
- SCRIPT_MAP =
{ # Default Omnibus naming preinst: "pre", postinst: "post", prerm: "preun", postrm: "postun", # Default RPM naming pre: "pre", post: "post", preun: "preun", postun: "postun", verifyscript: "verifyscript", pretrans: "pretrans", posttrans: "posttrans", }.freeze
Constants included from Util
Constants included from NullArgumentable
Instance Attribute Summary
Attributes inherited from Base
DSL methods collapse
-
#category(val = NULL) ⇒ String
Set or return the category for this package.
-
#compression_level(val = NULL) ⇒ Integer
Set or return the compression level (1-9) for this package.
-
#compression_type(val = NULL) ⇒ String
Set or return the compression type (:gzip, :bzip2, :xz) for this package.
-
#dist_tag(val = NULL) ⇒ String
Set or return the dist_tag for this package.
-
#license(val = NULL) ⇒ String
Set or return the license for this package.
-
#priority(val = NULL) ⇒ String
Set or return the priority for this package.
-
#signing_passphrase(val = NULL) ⇒ String
Set or return the signing passphrase.
-
#vendor(val = NULL) ⇒ String
Set or return the vendor who made this package.
Instance Method Summary collapse
-
#build_dir ⇒ String
The path to the
BUILD
directory inside the staging directory. -
#build_filepath(path) ⇒ String
Convert the path of a file in the staging directory to an entry for use in the spec file.
-
#compression ⇒ String
Returns the RPM spec “_binary_payload” line corresponding to the compression configuration.
-
#config_files ⇒ Array
Get a list of user-declared config files.
-
#create_rpm_file ⇒ void
Generate the RPM file using
rpmbuild
. -
#filesystem_directories ⇒ Array
Directories owned by the filesystem package: fedoraproject.org/wiki/Packaging:Guidelines#File_and_Directory_Ownership.
-
#mark_filesystem_directories(fsdir) ⇒ String
Mark filesystem directories with ownership and permissions specified in the filesystem package git.fedorahosted.org/cgit/filesystem.git/plain/filesystem.spec.
- #package_name ⇒ String
-
#rpm_file ⇒ String
The full path to the rpm file.
-
#rpm_safe(string) ⇒ Object
Generate an RPM-safe name from the given string, doing the following:.
-
#safe_architecture ⇒ String
The architecture for this RPM package.
-
#safe_base_package_name ⇒ String
Return the RPM-ready base package name, converting any invalid characters to dashes (
-
). -
#safe_build_iteration ⇒ String
This is actually just the regular build_iternation, but it felt lonely among all the other
safe_*
methods. -
#safe_version ⇒ String
RPM package versions cannot contain dashes, so we will convert them to underscores.
-
#spec_file ⇒ String
The full path to this spec file on disk.
-
#with_rpm_signing(&block) ⇒ String
Render the rpm signing script with secure permissions, call the given block with the path to the script, and ensure deletion of the script from disk since it contains sensitive information.
-
#write_rpm_spec ⇒ void
Render an rpm spec file in SPECS/#{name}.spec using the supplied ERB template.
Methods inherited from Base
build, #exclusions, id, #id, #initialize, #install_dir, #package_path, #resource_path, #resources_path, #run!, setup, #skip_packager, #staging_dir, #staging_dir_path
Methods included from Util
#compiler_safe_path, #copy_file, #create_directory, #create_file, #create_link, included, #path_key, #remove_directory, #remove_file, #retry_block, #shellout, #shellout!, #windows_safe_path
Methods included from Templating
included, #render_template, #render_template_content
Methods included from Sugarable
Methods included from NullArgumentable
Methods included from Logging
Methods included from Instrumentation
Methods included from Digestable
#digest, #digest_directory, included
Constructor Details
This class inherits a constructor from Omnibus::Packager::Base
Instance Method Details
#build_dir ⇒ String
The path to the BUILD
directory inside the staging directory.
300 301 302 |
# File 'lib/omnibus/packagers/rpm.rb', line 300 def build_dir @build_dir ||= File.join(staging_dir, "BUILD") end |
#build_filepath(path) ⇒ String
Convert the path of a file in the staging directory to an entry for use in the spec file.
469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/omnibus/packagers/rpm.rb', line 469 def build_filepath(path) filepath = rpm_safe("/" + path.gsub("#{build_dir}/", "")) return if config_files.include?(filepath) full_path = build_dir + filepath.gsub("[%]", "%") # FileSyncer.glob quotes pathnames that contain spaces, which is a problem on el7 full_path.delete!('"') # Mark directories with the %dir directive to prevent rpmbuild from counting their contents twice. return mark_filesystem_directories(filepath) if !File.symlink?(full_path) && File.directory?(full_path) filepath end |
#category(val = NULL) ⇒ String
Set or return the category for this package.
192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/omnibus/packagers/rpm.rb', line 192 def category(val = NULL) if null?(val) @category || "default" else unless val.is_a?(String) raise InvalidValue.new(:category, "be a String") end @category = val end end |
#compression ⇒ String
Returns the RPM spec “_binary_payload” line corresponding to the compression configuration.
395 396 397 398 399 400 401 402 403 404 405 |
# File 'lib/omnibus/packagers/rpm.rb', line 395 def compression compression_name = case compression_type when :bzip2 "bzdio" when :xz "xzdio" else # default to gzip "gzdio" end "w#{compression_level}.#{compression_name}" end |
#compression_level(val = NULL) ⇒ Integer
Set or return the compression level (1-9) for this package
267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/omnibus/packagers/rpm.rb', line 267 def compression_level(val = NULL) if null?(val) @compression_level || 9 else unless val.is_a?(Integer) && 1 <= val && 9 >= val raise InvalidValue.new(:compression_level, "be an Integer (between 1 and 9)") end @compression_level = val end end |
#compression_type(val = NULL) ⇒ String
Set or return the compression type (:gzip, :bzip2, :xz) for this package
242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/omnibus/packagers/rpm.rb', line 242 def compression_type(val = NULL) if null?(val) @compression_type || :gzip else unless val.is_a?(Symbol) && %i{gzip bzip2 xz}.member?(val) raise InvalidValue.new(:compression_type, "be a Symbol (:gzip, :bzip2, or :xz)") end @compression_type = val end end |
#config_files ⇒ Array
Get a list of user-declared config files
309 310 311 |
# File 'lib/omnibus/packagers/rpm.rb', line 309 def config_files @config_files ||= project.config_files.map { |file| rpm_safe(file) } end |
#create_rpm_file ⇒ void
This method returns an undefined value.
Generate the RPM file using rpmbuild
. Unlike debian,the fakeroot
command is not required for the package to be owned by root:root
. The rpmuser specified in the spec file dictates this.
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
# File 'lib/omnibus/packagers/rpm.rb', line 414 def create_rpm_file command = %{rpmbuild} command << %{ --target #{safe_architecture}} command << %{ -bb} command << %{ --buildroot #{staging_dir}/BUILD} command << %{ --define '_topdir #{staging_dir}'} command << " #{spec_file}" log.info(log_key) { "Creating .rpm file" } shellout!("#{command}") if signing_passphrase log.info(log_key) { "Signing enabled for .rpm file" } if File.exist?("#{ENV["HOME"]}/.rpmmacros") log.info(log_key) { "Detected .rpmmacros file at `#{ENV["HOME"]}'" } home = ENV["HOME"] else log.info(log_key) { "Using default .rpmmacros file from Omnibus" } # Generate a temporary home directory home = Dir.mktmpdir render_template(resource_path("rpmmacros.erb"), destination: "#{home}/.rpmmacros", variables: { gpg_name: "Opscode Packages", gpg_path: "#{ENV["HOME"]}/.gnupg", # TODO: Make this configurable }) end sign_cmd = "rpmsign --addsign #{rpm_file}" with_rpm_signing do |signing_script| log.info(log_key) { "Signing the built rpm file" } # RHEL 8 and Amazon-2023 has gpg-agent running so we can skip the expect script since the agent # takes care of the passphrase entering on the signing if dist_tag != ".el8" && dist_tag != ".el9" && dist_tag != ".amazon2023" sign_cmd.prepend("#{signing_script} \"").concat("\"") end shellout!("#{sign_cmd}", environment: { "HOME" => home }) end end FileSyncer.glob("#{staging_dir}/RPMS/**/*.rpm").each do |rpm| copy_file(rpm, Config.package_dir) end end |
#dist_tag(val = NULL) ⇒ String
Set or return the dist_tag for this package
The Dist Tag for this RPM package as per the Fedora packaging guidlines.
221 222 223 224 225 226 227 |
# File 'lib/omnibus/packagers/rpm.rb', line 221 def dist_tag(val = NULL) if null?(val) @dist_tag || ".#{Omnibus::Metadata.platform_shortname}#{Omnibus::Metadata.platform_version}" else @dist_tag = val end end |
#filesystem_directories ⇒ Array
Directories owned by the filesystem package: fedoraproject.org/wiki/Packaging:Guidelines#File_and_Directory_Ownership
319 320 321 |
# File 'lib/omnibus/packagers/rpm.rb', line 319 def filesystem_directories @filesystem_directories ||= IO.readlines(resource_path("filesystem_list")).map(&:chomp) end |
#license(val = NULL) ⇒ String
Set or return the license for this package.
142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/omnibus/packagers/rpm.rb', line 142 def license(val = NULL) if null?(val) @license || project.license else unless val.is_a?(String) raise InvalidValue.new(:license, "be a String") end @license = val end end |
#mark_filesystem_directories(fsdir) ⇒ String
Mark filesystem directories with ownership and permissions specified in the filesystem package git.fedorahosted.org/cgit/filesystem.git/plain/filesystem.spec
329 330 331 332 333 334 335 336 337 |
# File 'lib/omnibus/packagers/rpm.rb', line 329 def mark_filesystem_directories(fsdir) if fsdir.eql?("/") || fsdir.eql?("/usr/lib") || fsdir.eql?("/usr/share/empty") "%dir %attr(0555,root,root) #{fsdir}" elsif filesystem_directories.include?(fsdir) "%dir %attr(0755,root,root) #{fsdir}" else "%dir #{fsdir}" end end |
#package_name ⇒ String
287 288 289 290 291 292 293 |
# File 'lib/omnibus/packagers/rpm.rb', line 287 def package_name if dist_tag "#{safe_base_package_name}-#{safe_version}-#{safe_build_iteration}#{dist_tag}.#{safe_architecture}.rpm" else "#{safe_base_package_name}-#{safe_version}-#{safe_build_iteration}.#{safe_architecture}.rpm" end end |
#priority(val = NULL) ⇒ String
Set or return the priority for this package.
167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/omnibus/packagers/rpm.rb', line 167 def priority(val = NULL) if null?(val) @priority || "extra" else unless val.is_a?(String) raise InvalidValue.new(:priority, "be a String") end @priority = val end end |
#rpm_file ⇒ String
The full path to the rpm file.
496 497 498 |
# File 'lib/omnibus/packagers/rpm.rb', line 496 def rpm_file "#{staging_dir}/RPMS/#{safe_architecture}/#{package_name}" end |
#rpm_safe(string) ⇒ Object
Generate an RPM-safe name from the given string, doing the following:
-
Replace [ with [[] to make rpm not use globs
-
Replace * with [*] to make rpm not use globs
-
Replace ? with [?] to make rpm not use globs
-
Replace % with [%] to make rpm not expand macros
539 540 541 542 543 544 545 546 547 |
# File 'lib/omnibus/packagers/rpm.rb', line 539 def rpm_safe(string) string = "\"#{string}\"" if string[/\s/] string.dup .gsub("[", "[\\[]") .gsub("*", "[*]") .gsub("?", "[?]") .gsub("%", "[%]") end |
#safe_architecture ⇒ String
The architecture for this RPM package.
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 |
# File 'lib/omnibus/packagers/rpm.rb', line 642 def safe_architecture case Ohai["kernel"]["machine"] when "i686" "i386" when "armv7l" # raspberry pi 3 CentOS "armv7hl" when "armv6l" if Ohai["platform"] == "pidora" "armv6hl" else "armv6l" end else Ohai["kernel"]["machine"] end end |
#safe_base_package_name ⇒ String
Return the RPM-ready base package name, converting any invalid characters to dashes (-
).
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 |
# File 'lib/omnibus/packagers/rpm.rb', line 555 def safe_base_package_name if project.package_name =~ /\A[a-z0-9\.\+\-]+\z/ project.package_name.dup else converted = project.package_name.downcase.gsub(/[^a-z0-9\.\+\-]+/, "-") log.warn(log_key) do "The `name' component of RPM package names can only include " \ "lowercase alphabetical characters (a-z), numbers (0-9), dots (.), " \ "plus signs (+), and dashes (-). Converting `#{project.package_name}' to " \ "`#{converted}'." end converted end end |
#safe_build_iteration ⇒ String
This is actually just the regular build_iternation, but it felt lonely among all the other safe_*
methods.
578 579 580 |
# File 'lib/omnibus/packagers/rpm.rb', line 578 def safe_build_iteration project.build_iteration end |
#safe_version ⇒ String
RPM package versions cannot contain dashes, so we will convert them to underscores.
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 |
# File 'lib/omnibus/packagers/rpm.rb', line 588 def safe_version version = project.build_version.dup # RPM 4.10+ added support for using the tilde (~) as a way to mark # versions as lower priority in comparisons. More details on this # feature can be found here: # # http://rpm.org/ticket/56 # if version =~ /\-/ if Ohai["platform_family"] == "wrlinux" converted = version.tr("-", "_") # WRL has an elderly RPM version log.warn(log_key) do "Omnibus replaces dashes (-) with tildes (~) so pre-release " \ "versions get sorted earlier than final versions. However, the " \ "version of rpmbuild on Wind River Linux does not support this. " \ "All dashes will be replaced with underscores (_). Converting " \ "`#{project.build_version}' to `#{converted}'." end else converted = version.tr("-", "~") log.warn(log_key) do "Tildes hold special significance in the RPM package versions. " \ "They mark a version as lower priority in RPM's version compare " \ "logic. We'll replace all dashes (-) with tildes (~) so pre-release" \ "versions get sorted earlier then final versions. Converting" \ "`#{project.build_version}' to `#{converted}'." end end version = converted end if version =~ /\A[a-zA-Z0-9\.\+\~]+\z/ version else converted = version.gsub(/[^a-zA-Z0-9\.\+\~]+/, "_") log.warn(log_key) do "The `version' component of RPM package names can only include " \ "alphabetical characters (a-z, A-Z), numbers (0-9), dots (.), " \ "plus signs (+), tildes (~) and underscores (_). Converting " \ "`#{project.build_version}' to `#{converted}'." end converted end end |
#signing_passphrase(val = NULL) ⇒ String
Set or return the signing passphrase. If this value is provided, Omnibus will attempt to sign the RPM.
96 97 98 99 100 101 102 |
# File 'lib/omnibus/packagers/rpm.rb', line 96 def signing_passphrase(val = NULL) if null?(val) @signing_passphrase else @signing_passphrase = val end end |
#spec_file ⇒ String
The full path to this spec file on disk.
487 488 489 |
# File 'lib/omnibus/packagers/rpm.rb', line 487 def spec_file "#{staging_dir}/SPECS/#{package_name}.spec" end |
#vendor(val = NULL) ⇒ String
Set or return the vendor who made this package.
117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/omnibus/packagers/rpm.rb', line 117 def vendor(val = NULL) if null?(val) @vendor || "Omnibus <[email protected]>" else unless val.is_a?(String) raise InvalidValue.new(:vendor, "be a String") end @vendor = val end end |
#with_rpm_signing(&block) ⇒ String
Render the rpm signing script with secure permissions, call the given block with the path to the script, and ensure deletion of the script from disk since it contains sensitive information.
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
# File 'lib/omnibus/packagers/rpm.rb', line 510 def with_rpm_signing(&block) directory = Dir.mktmpdir destination = "#{directory}/sign-rpm" render_template(resource_path("signing.erb"), destination: destination, mode: 0700, variables: { passphrase: signing_passphrase, }) # Yield the destination to the block yield(destination) ensure remove_file(destination) remove_directory(directory) end |
#write_rpm_spec ⇒ void
This method returns an undefined value.
Render an rpm spec file in SPECS/#{name}.spec using the supplied ERB template.
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
# File 'lib/omnibus/packagers/rpm.rb', line 345 def write_rpm_spec # Create a map of scripts that exist and their contents scripts = SCRIPT_MAP.inject({}) do |hash, (source, destination)| path = File.join(project.package_scripts_path, source.to_s) if File.file?(path) hash[destination] = File.read(path) end hash end # Get a list of all files files = FileSyncer.glob("#{build_dir}/**/*") .map { |path| build_filepath(path) } render_template(resource_path("spec.erb"), destination: spec_file, variables: { name: safe_base_package_name, version: safe_version, iteration: safe_build_iteration, vendor: vendor, license: license, dist_tag: dist_tag, maintainer: project.maintainer, homepage: project.homepage, description: project.description, priority: priority, category: category, conflicts: project.conflicts, replaces: project.replaces, dependencies: project.runtime_dependencies, user: project.package_user, group: project.package_group, scripts: scripts, config_files: config_files, files: files, build_dir: build_dir, platform_family: Ohai["platform_family"], compression: compression, }) end |