class Bosh::Cli::Resources::Package

Constants

BUILD_HOOK_FILES

Attributes

package_base[R]
release_base[R]

Public Class Methods

discover(release_base) click to toggle source

@param [String] directory base Release directory

# File lib/cli/resources/package.rb, line 13
def self.discover(release_base)
  Dir[File.join(release_base, 'packages', '*')].inject([]) do |packages, package_base|
    if File.directory?(package_base)
      packages << new(package_base, release_base)
    end
    packages
  end
end
new(package_base, release_base) click to toggle source
# File lib/cli/resources/package.rb, line 24
def initialize(package_base, release_base)
  @release_base = Pathname.new(release_base)
  @package_base = Pathname.new(package_base)
end

Public Instance Methods

additional_fingerprints() click to toggle source
# File lib/cli/resources/package.rb, line 94
def additional_fingerprints
  dependencies
end
dependencies() click to toggle source
# File lib/cli/resources/package.rb, line 39
def dependencies
  @dependencies ||= Array(spec['dependencies']).sort
end
files() click to toggle source
# File lib/cli/resources/package.rb, line 51
def files
  resolve_globs
  known_files = {}

  files = []
  files += resolved_globs.map do |match|
    known_files[match.path] = true
    [match.full_path, match.path]
  end

  BUILD_HOOK_FILES.each do |build_hook_file|
    source_file = package_base.join(build_hook_file)
    if source_file.exist?
      if known_files.has_key?(build_hook_file)
        raise Bosh::Cli::InvalidPackage, "Package '#{name}' has '#{build_hook_file}' file " +
            "which conflicts with BOSH packaging"
      end

      files << [source_file.to_s, build_hook_file]
    end
  end

  files
end
format_fingerprint(digest, filename, name, file_mode) click to toggle source
# File lib/cli/resources/package.rb, line 98
def format_fingerprint(digest, filename, name, file_mode)
  is_hook = BUILD_HOOK_FILES.include?(name)
  "%s%s%s" % [name, digest, is_hook ? '' : file_mode]
end
name() click to toggle source
# File lib/cli/resources/package.rb, line 35
def name
  spec['name']
end
plural_type() click to toggle source
# File lib/cli/resources/package.rb, line 47
def plural_type
  'packages'
end
run_script(script_name, *args) click to toggle source
# File lib/cli/resources/package.rb, line 103
def run_script(script_name, *args)
  if BUILD_HOOK_FILES.include?(script_name.to_s)
    send(:"run_script_#{script_name}", *args)
  end
end
singular_type() click to toggle source
# File lib/cli/resources/package.rb, line 43
def singular_type
  'package'
end
spec() click to toggle source
# File lib/cli/resources/package.rb, line 29
def spec
  @spec ||= load_yaml_file(package_base.join('spec'))
rescue
  raise Bosh::Cli::InvalidPackage, 'Package spec is missing'
end
validate!() click to toggle source
# File lib/cli/resources/package.rb, line 76
def validate!
  basename = File.basename(package_base.to_s)

  unless name == basename
    raise Bosh::Cli::InvalidPackage, "Found '#{name}' package in '#{basename}' directory, please fix it"
  end

  unless name.bosh_valid_id?
    raise Bosh::Cli::InvalidPackage, "Package name, '#{name}', should be a valid BOSH identifier"
  end

  unless spec['files'].is_a?(Array) && spec['files'].size > 0
    raise Bosh::Cli::InvalidPackage, "Package '#{name}' doesn't include any files"
  end

  resolve_globs
end

Private Instance Methods

excluded_files() click to toggle source

# File lib/cli/resources/package.rb, line 113
def excluded_files
  @excluded_files ||= Array(spec['excluded_files']).sort
end
release_alt() click to toggle source
# File lib/cli/resources/package.rb, line 167
def release_alt
  release_base.join('src_alt')
end
release_blobs() click to toggle source
# File lib/cli/resources/package.rb, line 171
def release_blobs
  release_base.join('blobs')
end
release_src() click to toggle source
# File lib/cli/resources/package.rb, line 163
def release_src
  release_base.join('src')
end
resolve_glob_in_dir(glob, dir) click to toggle source
# File lib/cli/resources/package.rb, line 151
def resolve_glob_in_dir(glob, dir)
  Dir.chdir(dir) do
    Dir.glob(glob, File::FNM_DOTMATCH).reject do |fn|
      %w(. ..).include?(File.basename(fn))
    end
  end
end
resolve_globs() click to toggle source

@return Array<Bosh::Cli::GlobMatch>

# File lib/cli/resources/package.rb, line 118
def resolve_globs
  @resolved_globs ||= begin
    all_matches = Set.new

    spec['files'].each do |glob|
      glob_matches = Set.new
      src_matches = resolve_glob_in_dir(glob, release_src)
      glob_matches += src_matches.map { |path| Bosh::Cli::GlobMatch.new(release_src, path) }

      # Blobs directory is a little bit different: whatever matches a blob
      # will complement already found matches, unless this particular path
      # has already been matched. The GlobMatch class defines <=> to compare
      # path, thereby rejecting blobs if the file exists in src.
      if File.directory?(File.join(release_blobs))
        blob_matches = resolve_glob_in_dir(glob, release_blobs)
        glob_matches += blob_matches.map { |path| Bosh::Cli::GlobMatch.new(release_blobs, path) }
      end

      if glob_matches.empty?
        raise Bosh::Cli::InvalidPackage, "Package '#{name}' has a glob that resolves to an empty file list: #{glob}"
      end

      all_matches += glob_matches
    end

    all_matches.reject! do |match|
      excluded_files.detect { |excluded_glob| File.fnmatch(excluded_glob, match.path) }
    end

    all_matches.sort
  end
end
resolved_globs() click to toggle source
# File lib/cli/resources/package.rb, line 159
def resolved_globs
  @resolved_globs
end
run_script_pre_packaging(staging_dir) click to toggle source
# File lib/cli/resources/package.rb, line 175
def run_script_pre_packaging(staging_dir)
  pre_packaging_script = package_base.join('pre_packaging')

  if File.exists?(pre_packaging_script)
    say('Pre-packaging...')
    FileUtils.cp(pre_packaging_script, staging_dir, :preserve => true)

    old_env = ENV

    begin
      ENV.delete_if { |key, _| key[0, 7] == 'BUNDLE_' }
      if ENV['RUBYOPT']
        ENV['RUBYOPT'] = ENV['RUBYOPT'].sub('-rbundler/setup', '')
      end
      # todo: test these
      ENV['BUILD_DIR'] = staging_dir
      ENV['RELEASE_DIR'] = release_base.to_s
      Dir.chdir(staging_dir) do
        output = `bash -x pre_packaging 2>&1`

        unless $?.exitstatus == 0
          output.split("\n").each do |line|
            say("> #{line}")
          end
          raise Bosh::Cli::InvalidPackage, "'#{name}' pre-packaging failed"
        end
      end

    ensure
      ENV.delete('BUILD_DIR')
      old_env.each { |k, v| ENV[k] = old_env[k] }
    end

    FileUtils.rm(File.join(staging_dir, 'pre_packaging'))
  end
end