class Vanagon::Component::DSL
Public Class Methods
Constructor for the DSL
object
@param name [String] name of the component @param settings [Hash] settings to use in building the component @param platform [Vanagon::Platform] platform to build the component for @return [Vanagon::Component::DSL] A DSL
object to describe the {Vanagon::Component}
# File lib/vanagon/component/dsl.rb, line 16 def initialize(name, settings, platform) @name = name @component = Vanagon::Component.new(@name, settings, platform) end
Public Instance Methods
Accessor for the component.
@return [Vanagon::Component] the component the DSL
methods will be acting against
# File lib/vanagon/component/dsl.rb, line 32 def _component @component end
Adds activate trigger name to be watched
@param activate_name [String] the activate trigger name
# File lib/vanagon/component/dsl.rb, line 502 def add_debian_activate_triggers(activate_name) @component.activate_triggers << OpenStruct.new(:activate_name => activate_name) end
Adds interest trigger based on the specified packaging state and interest name.
@param pkg_state [String, Array] the package state during which the scripts should execute.
Accepts either a single string ("install" or "upgrade"), or an Array of Strings (["install", "upgrade"]).
@param scripts [Array] the scripts to run for the interest trigger @param interest_name [String] the name of the interest trigger
# File lib/vanagon/component/dsl.rb, line 492 def add_debian_interest_triggers(pkg_state, scripts, interest_name) pkg_state = Array(pkg_state) scripts = Array(scripts) check_pkg_state_array(pkg_state) @component.interest_triggers << OpenStruct.new(:pkg_state => pkg_state, :scripts => scripts, :interest_name => interest_name) end
Adds action to run during the postinstall phase of packaging
@param pkg_state [Array] the state in which the scripts should execute. Can be
one or multiple of 'install' and 'upgrade'.
@param scripts [Array] the Bourne shell compatible scriptlet(s) to execute
# File lib/vanagon/component/dsl.rb, line 521 def add_postinstall_action(pkg_state, scripts) pkg_state = Array(pkg_state) scripts = Array(scripts) check_pkg_state_array(pkg_state) @component.postinstall_actions << OpenStruct.new(:pkg_state => pkg_state, :scripts => scripts) end
Add post installation action that must exit successfully before restarting the service
@param pkg_state [Array] the state in which the scripts should execute. Can be
one or multiple of 'install' and 'upgrade'.
@param scripts [Array] the Bourne shell compatible scriptlet(s) to execute
# File lib/vanagon/component/dsl.rb, line 511 def add_postinstall_required_action(pkg_state, scripts) check_pkg_state_array(pkg_state) @component.postinstall_required_actions << OpenStruct.new(:pkg_state => Array(pkg_state), :scripts => Array(scripts)) end
Adds action to run during the postremoval phase of packaging
@param pkg_state [Array] the state in which the scripts should execute. Can be
one or multiple of 'removal' and 'upgrade'.
@param scripts [Array] the Bourne shell compatible scriptlet(s) to execute
# File lib/vanagon/component/dsl.rb, line 559 def add_postremove_action(pkg_state, scripts) pkg_state = Array(pkg_state) scripts = Array(scripts) if pkg_state.empty? || !(pkg_state - ["upgrade", "removal"]).empty? raise Vanagon::Error, "#{pkg_state} should be an array containing one or more of ['removal', 'upgrade']" end @component.postremove_actions << OpenStruct.new(:pkg_state => pkg_state, :scripts => scripts) end
Adds action to run during the preinstall phase of packaging
@param pkg_state [String, Array] the package state during which the scripts should execute.
Accepts either a single string ("install" or "upgrade"), or an Array of Strings (["install", "upgrade"]).
@param scripts [Array] the Bourne shell compatible scriptlet(s) to execute
# File lib/vanagon/component/dsl.rb, line 466 def add_preinstall_action(pkg_state, scripts) pkg_state = Array(pkg_state) scripts = Array(scripts) check_pkg_state_array(pkg_state) @component.preinstall_actions << OpenStruct.new(:pkg_state => pkg_state, :scripts => scripts) end
Adds action to run during the preremoval phase of packaging
@param pkg_state [Array] the state in which the scripts should execute. Can be
one or multiple of 'removal' and 'upgrade'.
@param scripts [Array] the Bourne shell compatible scriptlet(s) to execute
# File lib/vanagon/component/dsl.rb, line 533 def add_preremove_action(pkg_state, scripts) pkg_state = Array(pkg_state) scripts = Array(scripts) if pkg_state.empty? || !(pkg_state - ["upgrade", "removal"]).empty? raise Vanagon::Error, "#{pkg_state} should be an array containing one or more of ['removal', 'upgrade']" end @component.preremove_actions << OpenStruct.new(:pkg_state => pkg_state, :scripts => scripts) end
Add a %ghost entry to the rpm %files section. This indicates a file that is tracked in the rpm database (the package manages it), but not installed. Used, for example, when setting up alternative packages for use with update-alternatives.
@param path [String] installed path of the file.
# File lib/vanagon/component/dsl.rb, line 299 def add_rpm_ghost_file(path) @component.add_rpm_ghost_file(Vanagon::Common::Pathname.file(path)) end
Adds trigger for scripts to be run on specified pkg_state.
@param pkg_state [String, Array] the package state during which the scripts should execute.
Accepts either a single string ("install" or "upgrade"), or an Array of Strings (["install", "upgrade"]).
@param scripts [Array] the rpm pkg scriptlet(s) to execute @param pkg [String] the package the trigger will be set in
# File lib/vanagon/component/dsl.rb, line 479 def add_rpm_install_triggers(pkg_state, scripts, pkg) pkg_state = Array(pkg_state) scripts = Array(scripts) check_pkg_state_array(pkg_state) @component.install_triggers << OpenStruct.new(:pkg_state => pkg_state, :scripts => scripts, :pkg => pkg) end
This will add a source to the project and put it in the workdir alongside the other sources
@param uri [String] uri of the source @param [Hash] options optional keyword arguments used to instatiate a new source
@option opts [String] :sum @option opts [String] :ref @option opts [Bool] :erb set to 'true' to specify that the source file should be translated by erb
# File lib/vanagon/component/dsl.rb, line 403 def add_source(uri, options = {}) @component.sources << OpenStruct.new(options.merge({ url: uri })) end
Add a patch to the list of patches to apply to the component’s source after unpacking
@param patch [String] Path to the patch that should be applied @param options [Hash] options controlling the patch @option namespace [String] Namespace for package patches @option destination [String] Path to the location where the patch should be applied @option strip [String, Integer] directory levels to skip in applying patch @option fuzz [String, Integer] levels of context miss to ignore in applying patch @option after [String] the location in the makefile where the patch command should be run
# File lib/vanagon/component/dsl.rb, line 95 def apply_patch(patch, options = {}) @component.patches << Vanagon::Patch.new(patch, @component, options) end
Set
or add to the build call for the component. The commands required to build the component before testing/installing it.
@param block [Proc] the command(s) required to build the component
# File lib/vanagon/component/dsl.rb, line 68 def build(&block) @component.build << yield end
Set
a build dir relative to the source directory.
The build dir will be created before the configure block runs and configure/build/install commands will be run in the build dir.
@example
pkg.build_dir "build" pkg.source "my-cmake-project" # Will create the path "my-cmake-project/build" pkg.configure { ["cmake .."] } pkg.build { ["make -j 3"] } pkg.install { ["make install"] }
@param path [String] The build directory to use for building the project
# File lib/vanagon/component/dsl.rb, line 365 def build_dir(path) if Pathname.new(path).relative? @component.build_dir = path else raise Vanagon::Error, "build_dir should be a relative path, but '#{path}' looks to be absolute." end end
build_requires
adds a requirements to the list of build time dependencies that will need to be fetched from an external source before this component can be built. build_requires
can also be satisfied by other components in the same project.
@param build_requirement [String] a library or other component that is required to build the current component
# File lib/vanagon/component/dsl.rb, line 127 def build_requires(build_requirement) @component.build_requires << build_requirement end
Set
or add to the check call for the component. The commands required to test the component before installing it.
@param block [Proc] the command(s) required to test the component
# File lib/vanagon/component/dsl.rb, line 75 def check(&block) @component.check << yield end
Checks that the array of pkg_state is valid (install AND/OR upgrade). Returns vanagon error if invalid
@param pkg_state [Array] array of pkg_state input to test
# File lib/vanagon/component/dsl.rb, line 455 def check_pkg_state_array(pkg_state) if pkg_state.empty? || (pkg_state - ["install", "upgrade"]).any? raise Vanagon::Error, "#{pkg_state} should be an array containing one or more of ['install', 'upgrade']" end end
Sets clone option for git repository
@param option for cloning and value
# File lib/vanagon/component/dsl.rb, line 346 def clone_option(option, value) option_sym = option.to_sym @component.options[:clone_options] ||= {} @component.options[:clone_options][option_sym] = value end
Marks a file as a configfile to ensure that it is not overwritten on upgrade if it has been modified
@param file [String] name of the configfile
# File lib/vanagon/component/dsl.rb, line 260 def configfile(file, mode: nil, owner: nil, group: nil) # I AM SO SORRY @component.delete_file file if @component.platform.name =~ /solaris-10|osx/ @component.install << "mv '#{file}' '#{file}.pristine'" @component.add_file Vanagon::Common::Pathname.configfile("#{file}.pristine", mode: mode, owner: owner, group: group) else @component.add_file Vanagon::Common::Pathname.configfile(file, mode: mode, owner: owner, group: group) end end
Set
or add to the configure call for the component. The commands required to configure the component before building it.
@param block [Proc] the command(s) required to configure the component
# File lib/vanagon/component/dsl.rb, line 61 def configure(&block) @component.configure << yield end
Indicates that this component conflicts with another package, so both cannot be installed at the same time. Conflicts can be collected and used by the project and package.
@param pkgname [String] name of the package which conflicts with this component @param version [String] the version of the package that conflicts with this component
# File lib/vanagon/component/dsl.rb, line 161 def conflicts(pkgname, version = nil) @component.conflicts << OpenStruct.new(:pkgname => pkgname, :version => version) end
Adds a directory to the list of directories provided by the project, to be included in any packages of the project
@param dir [String] directory to add to the project @param mode [String] octal mode to apply to the directory @param owner [String] owner of the directory @param group [String] group of the directory
# File lib/vanagon/component/dsl.rb, line 413 def directory(dir, mode: nil, owner: nil, group: nil) # rubocop:disable Metrics/AbcSize install_flags = ['-d'] if @component.platform.is_windows? unless mode.nil? && owner.nil? && group.nil? VanagonLogger.info "You're trying to set the mode, owner, or group for windows. I don't know how to do that, ignoring!" end else install_flags << "-m '#{mode}'" unless mode.nil? end @component.install << "#{@component.platform.install} #{install_flags.join(' ')} '#{dir}'" @component.directories << Vanagon::Common::Pathname.new(dir, mode: mode, owner: owner, group: group) end
Set
a source dir
The build dir will be created when the source archive is unpacked. This should be used when the unpacked directory name does not match the source archive name.
@example
pkg.url "http://the-internet.com/a-silly-name-that-unpacks-into-not-this.tar.gz" pkg.dirname "really-cool-directory" pkg.configure { ["cmake .."] } pkg.build { ["make -j 3"] } pkg.install { ["make install"] }
@param path [String] The build directory to use for building the project
# File lib/vanagon/component/dsl.rb, line 387 def dirname(path) if Pathname.new(path).relative? @component.dirname = path else raise Vanagon::Error, "dirname should be a relative path, but '#{path}' looks to be absolute." end end
Adds a set of environment overrides to the environment for a component. This environment is included in the configure, build and install steps.
@param env [Hash] mapping of keys to values to add to the environment for the component
# File lib/vanagon/component/dsl.rb, line 430 def environment(*env) if env.size == 1 && env.first.is_a?(Hash) VanagonLogger.info <<-WARNING.undent the component DSL method signature #environment({Key => Value}) is deprecated and will be removed by Vanagon 1.0.0. Please update your project configurations to use the form: #environment(key, value) WARNING return @component.environment.merge!(env.first) elsif env.size == 2 return @component.environment[env.first] = env.last end raise ArgumentError, <<-WARNING.undent component DSL method #environment only accepts a single Hash (deprecated) or a key-value pair (preferred): environment({"KEY" => "value"}) environment("KEY", "value") WARNING end
Force version determination for components
If the component doesn’t already have a version set (which normally happens for git sources), the source will be fetched into a temporary directory to attempt to figure out the version if the source type supports :version. This directory will be cleaned once the get_sources method returns
@raise Vanagon::Error
raises a vanagon error if we’re unable to determine the version
# File lib/vanagon/component/dsl.rb, line 550 def get_version_forced @component.force_version end
Set
the homepage for the component
@param homepage
# File lib/vanagon/component/dsl.rb, line 580 def homepage(homepage) @component.homepage = homepage end
Set
or add to the install call for the component. The commands required to install the component.
@param block [Proc] the command(s) required to install the component
# File lib/vanagon/component/dsl.rb, line 82 def install(&block) @component.install << yield end
Shorthand to install a file and mark it as a configfile
@param source [String] path to the configfile to copy @param target [String] path to the desired target of the configfile
# File lib/vanagon/component/dsl.rb, line 275 def install_configfile(source, target, mode: '0644', owner: nil, group: nil) install_file(source, target, mode: mode, owner: owner, group: group) configfile(target, mode: mode, owner: owner, group: group) end
Copies a file from source to target during the install phase of the component
@param source [String] path to the file to copy @param target [String] path to the desired target of the file @param owner [String] owner of the file @param group [String] group owner of the file
# File lib/vanagon/component/dsl.rb, line 241 def install_file(source, target, mode: nil, owner: nil, group: nil) # rubocop:disable Metrics/AbcSize @component.install << "#{@component.platform.install} -d '#{File.dirname(target)}'" @component.install << "#{@component.platform.copy} -p '#{source}' '#{target}'" if @component.platform.is_windows? unless mode.nil? && owner.nil? && group.nil? VanagonLogger.info "You're trying to set the mode, owner, or group for windows. I don't know how to do that, ignoring!" end else mode ||= '0644' @component.install << "chmod #{mode} '#{target}'" end @component.add_file Vanagon::Common::Pathname.file(target, mode: mode, owner: owner, group: group) end
# File lib/vanagon/component/dsl.rb, line 573 def install_only(install_only) @component.install_only = install_only end
install_service
adds the commands to install the various files on disk during the package build and registers the service with the project
@param service_file [String] path to the service file relative to the source @param default_file [String] path to the default file relative to the source @param service_name [String] name of the service @param options optional extra parameters
service_type [String] type of the service (network, application, system, etc) init_system [String] the init system on which to install service (sysv, systemd) link_target [String] executable service file should be linked to
# File lib/vanagon/component/dsl.rb, line 175 def install_service(service_file, default_file = nil, service_name = @component.name, **options) # rubocop:disable Metrics/AbcSize init_system = options[:init_system] || @component.platform.servicetype servicedir = @component.platform.get_service_dir(init_system) case init_system when "sysv" target_service_file = File.join(servicedir, service_name) target_default_file = File.join(@component.platform.defaultdir, service_name) target_mode = '0755' default_mode = '0644' when "systemd" target_service_file = File.join(servicedir, "#{service_name}.service") target_default_file = File.join(@component.platform.defaultdir, service_name) target_mode = '0644' default_mode = '0644' when "launchd" target_service_file = File.join(servicedir, "#{service_name}.plist") target_mode = '0644' default_mode = '0644' when "smf" # modify version in smf manifest so service gets restarted after package upgrade @component.install << %{#{@component.platform.sed} -ri 's/(<service.*version=)(".*")/\\1"#{Time.now.to_i}"/' #{service_file}} target_service_file = File.join(servicedir, options[:service_type].to_s, "#{service_name}.xml") target_default_file = File.join(@component.platform.defaultdir, service_name) target_mode = '0644' default_mode = '0755' when "aix" @component.service << OpenStruct.new(:name => service_name, :service_command => File.read(service_file).chomp) # Return here because there is no file to install, just a string read in return when "windows" @component.service << OpenStruct.new( \ :bindir_id => "#{service_name.gsub(/[^A-Za-z0-9]/, '').upcase}BINDIR", \ :service_file => service_file, \ :component_group_id => "#{service_name.gsub(/[^A-Za-z0-9]/, '')}Component" \ ) # return here as we are just collecting the name of the service file to put into the harvest filter list. return else fail "Don't know how to install the #{init_system}. Please teach #install_service how to do this." end # Install the service and default files if options[:link_target] install_file(service_file, options[:link_target], mode: target_mode) link options[:link_target], target_service_file else install_file(service_file, target_service_file, mode: target_mode) end if default_file install_file(default_file, target_default_file, mode: default_mode) configfile target_default_file end # Register the service for use in packaging @component.service << OpenStruct.new(:name => service_name, :service_file => target_service_file, :type => options[:service_type], :init_system => init_system) end
# File lib/vanagon/component/dsl.rb, line 569 def license(license) @component.license = license end
link will add a command to the install to create a symlink from source to target
@param source [String] path to the file to symlink @param target [String] path to the desired symlink
# File lib/vanagon/component/dsl.rb, line 284 def link(source, target) @component.install << "#{@component.platform.install} -d '#{File.dirname(target)}'" # Use a bash conditional to only create the link if it doesn't already point to the correct source. # This allows rerunning the install step to be idempotent, rather than failing because the link # already exists. @component.install << "([[ '#{target}' -ef '#{source}' ]] || ln -s '#{source}' '#{target}')" @component.add_file Vanagon::Common::Pathname.file(target) end
Loads and parses json from a file. Will treat the keys in the json as methods to invoke on the component in question
@param file [String] Path to the json file @raise [RuntimeError] exceptions are raised if there is no file,
if it refers to methods that don't exist, or if it does not contain a Hash
# File lib/vanagon/component/dsl.rb, line 105 def load_from_json(file) if File.exist?(file) data = JSON.parse(File.read(file)) raise "Hash required. Got '#{data.class}' when parsing '#{file}'" unless data.is_a?(Hash) data.each do |key, value| if self.respond_to?(key) self.send(key, value) else fail "Component does not have a '#{key}' method to invoke. Maybe your bespoke json has a typo?" end end else fail "Cannot load component data from '#{file}'. It does not exist." end end
All purpose getter. This object, which is passed to the component block, won’t have easy access to the attributes of the @component, so we make a getter for each attribute.
We only magically handle get_ methods, any other methods just get the standard method_missing
treatment.
# File lib/vanagon/component/dsl.rb, line 43 def method_missing(method_name, *args) attribute_match = method_name.to_s.match(/get_(.*)/) if attribute_match attribute = attribute_match.captures.first else super end @component.send(attribute) end
Sets a mirror url for the source of this component
@param url [String] a mirror url to use as the source for this component.
Can be called more than once to add multiple mirror URLs.
# File lib/vanagon/component/dsl.rb, line 322 def mirror(url) @component.mirrors << url end
Indicates that this component provides a system level package. Provides can be collected and used by the project and package.
@param provide [String] a package that is provided with this component @param version [String] the version of the package that is provided with this component
# File lib/vanagon/component/dsl.rb, line 151 def provides(provide, version = nil) @component.provides << OpenStruct.new(:provide => provide, :version => version) end
Sets the ref of the source for use in a git source
@param the_ref [String] ref, sha, branch or tag to checkout for a git source
# File lib/vanagon/component/dsl.rb, line 339 def ref(the_ref) @component.options[:ref] = the_ref end
Indicates that this component replaces a system level package. Replaces can be collected and used by the project and package.
@param replacement [String] a package that is replaced with this component @param version [String] the version of the package that is replaced
# File lib/vanagon/component/dsl.rb, line 143 def replaces(replacement, version = nil) @component.replaces << OpenStruct.new(:replacement => replacement, :version => version) end
requires adds a requirement to the list of runtime requirements for the component
@param requirement [String] a package that is required at runtime for this component
# File lib/vanagon/component/dsl.rb, line 135 def requires(requirement, version = nil) @component.requires << OpenStruct.new(:requirement => requirement, :version => version) end
# File lib/vanagon/component/dsl.rb, line 54 def respond_to_missing?(method_name, include_private = false) method_name.to_s.start_with?('get_') || super end
# File lib/vanagon/component/dsl.rb, line 326 def sum(value) type = __callee__.to_s.gsub(/sum$/, '') @component.options[:sum] = value @component.options[:sum_type] = type end
Sets the canonical URL or URI for the upstream source of this component
@param uri [String, URI] a URL or URI describing a canonical location
for a component's source code or artifact
# File lib/vanagon/component/dsl.rb, line 314 def url(uri) @component.url = uri.to_s end
Sets the version for the component
@param ver [String] version of the component
# File lib/vanagon/component/dsl.rb, line 306 def version(ver) @component.version = ver end