class Librarian::Chef::Source::Site::Line

Attributes

metadata_cached[RW]
metadata_cached?[RW]
name[RW]
source[RW]

Public Class Methods

new(source, name) click to toggle source
# File lib/librarian/chef/source/site.rb, line 24
def initialize(source, name)
  self.source = source
  self.name = name
end

Public Instance Methods

install_version!(version, install_path) click to toggle source
# File lib/librarian/chef/source/site.rb, line 29
def install_version!(version, install_path)
  cache_version_unpacked! version

  if install_path.exist?
    debug { "Deleting #{relative_path_to(install_path)}" }
    install_path.rmtree
  end

  unpacked_path = version_unpacked_cache_path(version)

  debug { "Copying #{relative_path_to(unpacked_path)} to #{relative_path_to(install_path)}" }
  FileUtils.cp_r(unpacked_path, install_path)
end
manifests() click to toggle source
# File lib/librarian/chef/source/site.rb, line 43
def manifests
  version_uris.map do |version_uri|
    Manifest.new(source, name, version_uri)
  end
end
to_version(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 49
def to_version(version_uri)
  version_uri_metadata(version_uri)["version"]
end
version_dependencies(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 53
def version_dependencies(version)
  version_manifest(version)["dependencies"]
end

Private Instance Methods

cache_metadata!() click to toggle source
# File lib/librarian/chef/source/site.rb, line 171
def cache_metadata!
  metadata_cached? and return or metadata_cached!
  cache_remote_json! metadata_cache_path, uri
end
cache_path() click to toggle source
# File lib/librarian/chef/source/site.rb, line 118
def cache_path
  @cache_path ||= source.cache_path.join(name)
end
cache_remote_json!(path, uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 227
def cache_remote_json!(path, uri)
  cache_remote_object!(path, uri, :type => :json)
end
cache_remote_object!(path, uri, options = { }) click to toggle source
# File lib/librarian/chef/source/site.rb, line 231
def cache_remote_object!(path, uri, options = { })
  path = Pathname(path)
  uri = to_uri(uri)
  type = options[:type]

  debug { "Caching #{uri} to #{path}" }

  response = http_get(uri)

  object = response.body
  case type
  when :json
    JSON.parse(object) # verify that it's really JSON.
  end
  write! path, object
end
cache_version!(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 183
def cache_version!(version)
  path = version_cache_path(version)
  path.file? and return

  version_uris.each do |version_uri|
    m = version_uri_metadata(version_uri)
    v = m["version"]
    if version.to_s == v
      write! path, version_uri.to_s
      break
    end
  end
end
cache_version_package!(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 197
def cache_version_package!(version)
  version_uri = to_version_uri(version)
  cache_version_uri_package! version_uri
end
cache_version_unpacked!(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 210
def cache_version_unpacked!(version)
  version_uri = to_version_uri(version)
  cache_version_uri_unpacked! version_uri
end
cache_version_uri_metadata!(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 176
def cache_version_uri_metadata!(version_uri)
  path = version_uri_metadata_cache_path(version_uri)
  path.file? and return

  cache_remote_json! path, version_uri
end
cache_version_uri_package!(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 202
def cache_version_uri_package!(version_uri)
  path = version_uri_package_cache_path(version_uri)
  path.file? and return

  file_uri = version_uri_metadata(version_uri)["file"]
  cache_remote_object! path, file_uri
end
cache_version_uri_unpacked!(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 215
def cache_version_uri_unpacked!(version_uri)
  cache_version_uri_package!(version_uri)

  path = version_uri_unpacked_cache_path(version_uri)
  path.directory? and return

  package_path = version_uri_package_cache_path(version_uri)
  unpacked_path = version_uri_unpacked_cache_path(version_uri)

  unpack_package! unpacked_path, package_path
end
debug(*args, &block) click to toggle source
# File lib/librarian/chef/source/site.rb, line 330
def debug(*args, &block)
  environment.logger.debug(*args, &block)
end
environment() click to toggle source
# File lib/librarian/chef/source/site.rb, line 62
def environment
  source.environment
end
extract_archive!(source, destination) click to toggle source
# File lib/librarian/chef/source/site.rb, line 272
def extract_archive!(source, destination)
  source = Pathname(source)
  destination = Pathname(destination)

  return extract_archive_targz! source, destination if path_detect_gzip?(source)
  return extract_archive_tar! source, destination if path_detect_tar?(source)
  raise "Unrecognized archive format!"
end
extract_archive_tar!(source, destination) click to toggle source
# File lib/librarian/chef/source/site.rb, line 287
def extract_archive_tar!(source, destination)
  source.open "rb" do |input|
    Archive::Tar::Minitar.unpack(input, destination.to_s)
  end
end
extract_archive_targz!(source, destination) click to toggle source
# File lib/librarian/chef/source/site.rb, line 281
def extract_archive_targz!(source, destination)
  Zlib::GzipReader.open(source) do |input|
    Archive::Tar::Minitar.unpack(input, destination.to_s)
  end
end
hexdigest(bytes) click to toggle source
# File lib/librarian/chef/source/site.rb, line 321
def hexdigest(bytes)
  Digest::MD5.hexdigest(bytes)[0..15]
end
http(uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 338
def http(uri)
  net_http = environment.net_http_class(uri.host).new(uri.host, uri.port)
  net_http.use_ssl = true if uri.scheme == 'https'
  net_http
end
http_get(uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 344
def http_get(uri)
  max_redirects = 10
  redirects = []

  loop do
    debug { "Performing http-get for #{uri}" }
    http = http(uri)
    http.use_ssl = uri.scheme == 'https'
    request = Net::HTTP::Get.new(uri.path)
    response = http.start{|http| http.request(request)}

    case response
    when Net::HTTPSuccess
      debug { "Responded with success" }
      return response
    when Net::HTTPRedirection
      location = response["Location"]
      debug { "Responded with redirect to #{uri}" }
      redirects.size > max_redirects and raise Error,
        "Could not get #{uri} because too many redirects!"
      redirects.include?(location) and raise Error,
        "Could not get #{uri} because redirect cycle!"
      redirects << location
      uri = URI.parse(location)
      # continue the loop
    else
      raise Error, "Could not get #{uri} because #{response.code} #{response.message}!"
    end
  end
end
memo(method, *path) { || ... } click to toggle source
# File lib/librarian/chef/source/site.rb, line 375
def memo(method, *path)
  ivar = "@#{method}".to_sym
  unless memo = instance_variable_get(ivar)
    memo = instance_variable_set(ivar, { })
  end

  memo.key?(path) or memo[path] = yield
  memo[path]
end
metadata() click to toggle source
# File lib/librarian/chef/source/site.rb, line 100
def metadata
  @metadata ||= begin
    cache_metadata!
    parse_local_json(metadata_cache_path)
  end
end
metadata_cache_path() click to toggle source
# File lib/librarian/chef/source/site.rb, line 122
def metadata_cache_path
  @metadata_cache_path ||= cache_path.join("metadata.json")
end
metadata_cached!() click to toggle source
# File lib/librarian/chef/source/site.rb, line 114
def metadata_cached!
  self.metadata_cached = true
end
parse_local_json(path) click to toggle source
# File lib/librarian/chef/source/site.rb, line 317
def parse_local_json(path)
  JSON.parse(path.read)
end
path_detect_gzip?(path) click to toggle source
# File lib/librarian/chef/source/site.rb, line 253
def path_detect_gzip?(path)
  Zlib::GzipReader.open(path) { true }
rescue Zlib::GzipFile::Error
  false
end
path_detect_tar?(path) click to toggle source
# File lib/librarian/chef/source/site.rb, line 259
def path_detect_tar?(path)
  path_read_bytes_at(path, 257, 8) == "ustar\x0000"
end
path_read_bytes_at(path, pos, len) click to toggle source
# File lib/librarian/chef/source/site.rb, line 263
def path_read_bytes_at(path, pos, len)
  path = Pathname(path)
  path.stat.size >= pos + len or return
  path.open "rb" do |f|
    f.seek pos ; f.pos == pos or return
    f.read(len)
  end
end
relative_path_to(path) click to toggle source
# File lib/librarian/chef/source/site.rb, line 334
def relative_path_to(path)
  environment.logger.relative_path_to(path)
end
to_uri(uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 325
def to_uri(uri)
  uri = URI(uri) unless URI === uri
  uri
end
to_version_uri(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 107
def to_version_uri(version)
  memo(__method__, version.to_s) do
    cache_version! version
    version_cache_path(version).read
  end
end
unpack_package!(path, source) click to toggle source
# File lib/librarian/chef/source/site.rb, line 293
def unpack_package!(path, source)
  path = Pathname(path)
  source = Pathname(source)

  temp = environment.scratch_path.join(SecureRandom.hex(16))
  temp.mkpath

  debug { "Unpacking #{relative_path_to(source)} to #{relative_path_to(temp)}" }
  extract_archive! source, temp

  # Cookbook files, as pulled from Opscode Community Site API, are
  # embedded in a subdirectory of the tarball. If created by git archive they
  # can include the subfolder `pax_global_header`, which is ignored.
  subtemps = temp.children
  subtemps.empty? and raise "The package archive was empty!"
  subtemps.delete_if{|pth| pth.to_s[/pax_global_header/]}
  subtemps.size > 1 and raise "The package archive has too many children!"
  subtemp = subtemps.first
  debug { "Moving #{relative_path_to(subtemp)} to #{relative_path_to(path)}" }
  FileUtils.mv(subtemp, path)
ensure
  temp.rmtree if temp && temp.exist?
end
uri() click to toggle source
# File lib/librarian/chef/source/site.rb, line 66
def uri
  @uri ||= URI.parse("#{source.uri}/cookbooks/#{name}")
end
version_cache_path(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 126
def version_cache_path(version)
  memo(__method__, version.to_s) do
    cache_path.join("version").join(version.to_s)
  end
end
version_manifest(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 86
def version_manifest(version)
  version_uri = to_version_uri(version)
  version_uri_manifest(version_uri)
end
version_metadata(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 74
def version_metadata(version)
  version_uri = to_version_uri(version)
  version_uri_metadata(version_uri)
end
version_metadata_cache_path(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 138
def version_metadata_cache_path(version)
  version_uri = to_version_uri(version)
  version_uri_metadata_cache_path(version_uri)
end
version_package_cache_path(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 149
def version_package_cache_path(version)
  version_uri = to_version_uri(version)
  version_uri_package_cache_path(version_uri)
end
version_unpacked_cache_path(version) click to toggle source
# File lib/librarian/chef/source/site.rb, line 160
def version_unpacked_cache_path(version)
  version_uri = to_version_uri(version)
  version_uri_unpacked_cache_path(version_uri)
end
version_uri_cache_path(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 132
def version_uri_cache_path(version_uri)
  memo(__method__, version_uri.to_s) do
    cache_path.join("version-uri").join(hexdigest(version_uri))
  end
end
version_uri_manifest(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 91
def version_uri_manifest(version_uri)
  memo(__method__, version_uri.to_s) do
    cache_version_uri_unpacked! version_uri
    unpacked_path = version_uri_unpacked_cache_path(version_uri)
    manifest_path = ManifestReader.manifest_path(unpacked_path)
    ManifestReader.read_manifest(name, manifest_path)
  end
end
version_uri_metadata(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 79
def version_uri_metadata(version_uri)
  memo(__method__, version_uri.to_s) do
    cache_version_uri_metadata! version_uri
    parse_local_json(version_uri_metadata_cache_path(version_uri))
  end
end
version_uri_metadata_cache_path(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 143
def version_uri_metadata_cache_path(version_uri)
  memo(__method__, version_uri.to_s) do
    version_uri_cache_path(version_uri).join("metadata.json")
  end
end
version_uri_package_cache_path(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 154
def version_uri_package_cache_path(version_uri)
  memo(__method__, version_uri.to_s) do
    version_uri_cache_path(version_uri).join("package.tar.gz")
  end
end
version_uri_unpacked_cache_path(version_uri) click to toggle source
# File lib/librarian/chef/source/site.rb, line 165
def version_uri_unpacked_cache_path(version_uri)
  memo(__method__, version_uri.to_s) do
    version_uri_cache_path(version_uri).join("package")
  end
end
version_uris() click to toggle source
# File lib/librarian/chef/source/site.rb, line 70
def version_uris
  metadata["versions"]
end
write!(path, bytes) click to toggle source
# File lib/librarian/chef/source/site.rb, line 248
def write!(path, bytes)
  path.dirname.mkpath
  path.open("wb"){|f| f.write(bytes)}
end