Class: Omnibus::Packager::BFF

Inherits:
Base
  • Object
show all
Defined in:
lib/omnibus/packagers/bff.rb

Constant Summary collapse

SCRIPT_MAP =

Returns:

  • (Hash)
{
  # Default Omnibus naming
  preinst: "Pre-installation Script",
  postinst: "Post-installation Script",
  config: "Configuration Script",
  unconfig: "Unconfiguration Script",
  prerm: "Pre_rm Script",
  postrm: "Unconfiguration Script",
}.freeze

Constants included from Util

Util::SHELLOUT_OPTIONS

Constants included from NullArgumentable

NullArgumentable::NULL

Instance Attribute Summary

Attributes inherited from Base

#project

Instance Method Summary collapse

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

extended, included, #node

Methods included from NullArgumentable

included, #null?

Methods included from Logging

included

Methods included from Instrumentation

#measure

Methods included from Digestable

#digest, #digest_directory, included

Constructor Details

This class inherits a constructor from Omnibus::Packager::Base

Instance Method Details

#bff_versionString

TODO:

This is probably not the best way to extract the version and probably misses edge cases like when using git describe!

Return the BFF-specific version for this package. This is calculated using the first three digits of the version, concatenated by a dot, then suffixed with the build_iteration.

Returns:

  • (String)


289
290
291
292
# File 'lib/omnibus/packagers/bff.rb', line 289

def bff_version
  version = project.build_version.split(/[^\d]/)[0..2].join(".")
  "#{version}.#{project.build_iteration}"
end

#create_bff_filevoid

This method returns an undefined value.

Create the bff file using mkinstallp.

Warning: This command runs as sudo! AIX requires the use of sudo to run the mkinstallp command.



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/omnibus/packagers/bff.rb', line 205

def create_bff_file
  # We are making the assumption that sudo exists.
  # Unforunately, the owner of the file in the staging directory is what
  # will be on the target machine, and mkinstallp can't tell you if that
  # is a bad thing (it usually is).
  # The match is so we only pick the lowest level of the project dir.
  # This implies that if we are in /tmp/staging/project/dir/things,
  # we will chown from 'project' on, rather than 'project/dir', which leaves
  # project owned by the build user (which is incorrect)
  # First - let's find out who we are.
  shellout!("sudo chown -Rh 0:0 #{File.join(staging_dir, project.install_dir.match(%r{^/?(\w+)}).to_s)}")
  log.info(log_key) { "Creating .bff file" }

  # Since we want the owner to be root, we need to sudo the mkinstallp
  # command, otherwise it will not have access to the previously chowned
  # directory.
  shellout!("sudo /usr/sbin/mkinstallp -d #{staging_dir} -T #{File.join(staging_dir, "gen.template")}")

  # Print the full contents of the inventory file generated by mkinstallp
  # from within the staging_dir's .info folder (where control files for the
  # packaging process are kept.)
  log.debug(log_key) do
    "With .inventory file of:\n" + File.read("#{File.join( staging_dir, ".info", "#{safe_base_package_name}.inventory" )}")
  end

  # Copy the resulting package up to the package_dir
  FileSyncer.glob(File.join(staging_dir, "tmp/*.bff")).each do |bff|
    copy_file(bff, File.join(Config.package_dir, create_bff_file_name))
  end

ensure
  # chown back to original user's uid/gid so cleanup works correctly
  original_uid = shellout!("id -u").stdout.chomp
  original_gid = shellout!("id -g").stdout.chomp

  shellout!("sudo chown -Rh #{original_uid}:#{original_gid} #{staging_dir}")
end

#create_bff_file_nameString

Create bff file name

mkinstallp names the bff file according to the version specified in the template. We want to differentiate the build specific version correctly.

Returns:

  • (String)


252
253
254
# File 'lib/omnibus/packagers/bff.rb', line 252

def create_bff_file_name
  "#{safe_base_package_name}-#{project.build_version}-#{project.build_iteration}.#{safe_architecture}.bff"
end

#package_nameObject



56
57
58
# File 'lib/omnibus/packagers/bff.rb', line 56

def package_name
  "#{safe_base_package_name}-#{project.build_version}-#{project.build_iteration}.#{safe_architecture}.bff"
end

#safe_architectureString

The architecture for this RPM package.

Returns:

  • (String)


299
300
301
# File 'lib/omnibus/packagers/bff.rb', line 299

def safe_architecture
  Ohai["kernel"]["machine"]
end

#safe_base_package_nameString

Return the BFF-ready base package name, converting any invalid characters to dashes (-).

Returns:

  • (String)


262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/omnibus/packagers/bff.rb', line 262

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 BFF 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

#scripts_install_dirString

The path where the package scripts in the install directory.

Returns:

  • (String)


65
66
67
# File 'lib/omnibus/packagers/bff.rb', line 65

def scripts_install_dir
  File.expand_path(File.join(project.install_dir, "embedded/share/installp"))
end

#scripts_staging_dirString

The path where the package scripts will staged.

Returns:

  • (String)


74
75
76
# File 'lib/omnibus/packagers/bff.rb', line 74

def scripts_staging_dir
  File.expand_path(File.join(staging_dir, scripts_install_dir))
end

#write_gen_templatevoid

This method returns an undefined value.

Create the gen template for mkinstallp.

Some details on the various lifecycle scripts:

The order of the installp scripts is:

  • install

    • pre-install

    • post-install

    • config

  • upgrade

    • pre-remove (of previous version)

    • pre-install (previous version of software not present anymore)

    • post-install

    • config

  • remove

    • unconfig

    • unpre-install

To run the new version of scc, the post-install will do. To run the previous version with an upgrade, use the pre-remove script. To run a source install of scc upon installation of installp package, use the pre-install. Upon upgrade, both the pre-remove and the pre-install scripts will run. As scc has been removed between the runs of these scripts, it will only run once during upgrade.

Keywords for scripts:

Pre-installation Script: /path/script
Unpre-installation Script: /path/script
Post-installation Script: /path/script
Pre_rm Script: /path/script
Configuration Script: /path/script
Unconfiguration Script: /path/script


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/omnibus/packagers/bff.rb', line 131

def write_gen_template
  # Get a list of all files
  files = FileSyncer.glob("#{staging_dir}/**/*").reject do |path|
    # remove any files with spaces or braces.
    if path =~ /[[:space:]{}]/
      log.warn(log_key) { "Skipping packaging '#{path}' file due to whitespace or braces in filename" }
      true
    end
  end
  files.map! do |path|
    # If paths have colons or commas, rename them and add them to a post-install,
    # post-sysck renaming script ('config') which is created if needed
    if path =~ /:|,/
      alt = path.gsub(/(:|,)/, "__")
      log.debug(log_key) { "Renaming #{path} to #{alt}" }

      File.rename(path, alt) if File.exist?(path)

      # Create a config script if needed based on resources/bff/config.erb
      config_script_path = File.join(scripts_staging_dir, "config")
      unless File.exist? config_script_path
        render_template(resource_path("config.erb"),
          destination: "#{scripts_staging_dir}/config",
          variables: {
            name: project.name,
          })
      end

      File.open(File.join(scripts_staging_dir, "config"), "a") do |file|
        file.puts "mv '#{alt.gsub(/^#{staging_dir}/, "")}' '#{path.gsub(/^#{staging_dir}/, "")}'"
      end

      path = alt
    end

    path.gsub(/^#{staging_dir}/, "")
  end

  # Create a map of scripts that exist to inject into the template
  scripts = SCRIPT_MAP.inject({}) do |hash, (script, installp_key)|
    staging_path = File.join(scripts_staging_dir, script.to_s)

    if File.file?(staging_path)
      hash[installp_key] = staging_path
      log.debug(log_key) { installp_key + ":\n" + File.read(staging_path) }
    end

    hash
  end

  render_template(resource_path("gen.template.erb"),
    destination: File.join(staging_dir, "gen.template"),
    variables: {
      name: safe_base_package_name,
      install_dir: project.install_dir,
      friendly_name: project.friendly_name,
      version: bff_version,
      description: project.description,
      files: files,
      scripts: scripts,
    })

  # Print the full contents of the rendered template file for mkinstallp's use
  log.debug(log_key) { "Rendered Template:\n" + File.read(File.join(staging_dir, "gen.template")) }
end

#write_scriptsvoid

This method returns an undefined value.

Copy all scripts in Omnibus::Project#package_scripts_path to the package directory.



84
85
86
87
88
89
90
91
92
93
# File 'lib/omnibus/packagers/bff.rb', line 84

def write_scripts
  SCRIPT_MAP.each do |script, _installp_name|
    source_path = File.join(project.package_scripts_path, script.to_s)

    if File.file?(source_path)
      log.debug(log_key) { "Adding script `#{script}' to `#{scripts_staging_dir}'" }
      copy_file(source_path, scripts_staging_dir)
    end
  end
end