Class: Berkshelf::CommunityREST

Inherits:
Faraday::Connection
  • Object
show all
Defined in:
lib/berkshelf/community_rest.rb

Constant Summary collapse

V1_API =
'http://cookbooks.opscode.com/api/v1/cookbooks'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri = V1_API, options = {}) ⇒ CommunityREST

Returns a new instance of CommunityREST.

Parameters:

  • uri (String) (defaults to: V1_API)

    (CommunityREST::V1_API) location of community site to connect to

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :retries (Integer) — default: 5

    retry requests on 5XX failures

  • :retry_interval (Float) — default: 0.5

    how often we should pause between retries



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/berkshelf/community_rest.rb', line 75

def initialize(uri = V1_API, options = {})
  options         = options.reverse_merge(retries: 5, retry_interval: 0.5)
  @api_uri        = Addressable::URI.parse(uri)
  @retries        = options[:retries]
  @retry_interval = options[:retry_interval]

  builder = Faraday::Builder.new do |b|
    b.response :parse_json
    b.request :retry,
      max: @retries,
      interval: @retry_interval,
      exceptions: [Faraday::Error::TimeoutError]

    b.adapter :net_http
  end

  super(api_uri, builder: builder)
end

Instance Attribute Details

#api_uriString (readonly)

Returns:



60
61
62
# File 'lib/berkshelf/community_rest.rb', line 60

def api_uri
  @api_uri
end

#retriesInteger (readonly)

Returns how many retries to attempt on HTTP requests.

Returns:

  • (Integer)

    how many retries to attempt on HTTP requests



63
64
65
# File 'lib/berkshelf/community_rest.rb', line 63

def retries
  @retries
end

#retry_intervalFloat (readonly)

Returns time to wait between retries.

Returns:

  • (Float)

    time to wait between retries



66
67
68
# File 'lib/berkshelf/community_rest.rb', line 66

def retry_interval
  @retry_interval
end

Class Method Details

.unpack(target, destination = Dir.mktmpdir) ⇒ String

Parameters:

  • target (String)

    file path to the tar.gz archive on disk

  • destination (String) (defaults to: Dir.mktmpdir)

    file path to extract the contents of the target to

Returns:



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/berkshelf/community_rest.rb', line 14

def unpack(target, destination = Dir.mktmpdir)
  if is_gzip_file(target)
    Archive::Tar::Minitar.unpack(Zlib::GzipReader.new(File.open(target, 'rb')), destination)
  elsif is_tar_file(target)
    Archive::Tar::Minitar.unpack(target, destination)
  elsif is_bzip2_file(target)
    Archive::Tar::Minitar.unpack(RBzip2::Decompressor.new(File.open(target, 'rb')), destination)
  else
    raise Berkshelf::UnknownCompressionType.new(target)
  end
  destination
end

.uri_escape_version(version) ⇒ String

Parameters:

Returns:



30
31
32
# File 'lib/berkshelf/community_rest.rb', line 30

def uri_escape_version(version)
  version.to_s.gsub('.', '_')
end

.version_from_uri(uri) ⇒ String

Parameters:

Returns:



37
38
39
# File 'lib/berkshelf/community_rest.rb', line 37

def version_from_uri(uri)
  File.basename(uri.to_s).gsub('_', '.')
end

Instance Method Details

#download(name, version) ⇒ String

Parameters:

Returns:



98
99
100
101
102
103
# File 'lib/berkshelf/community_rest.rb', line 98

def download(name, version)
  archive = stream(find(name, version)[:file])
  self.class.unpack(archive.path)
ensure
  archive.unlink unless archive.nil?
end

#find(name, version) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/berkshelf/community_rest.rb', line 105

def find(name, version)
  response = get("#{name}/versions/#{self.class.uri_escape_version(version)}")

  case response.status
  when (200..299)
    response.body
  when 404
    raise CookbookNotFound, "Cookbook '#{name}' not found at site: '#{api_uri}'"
  else
    raise CommunitySiteError, "Error finding cookbook '#{name}' (#{version}) at site: '#{api_uri}'"
  end
end

#latest_version(name) ⇒ String

Returns the latest version of the cookbook and it’s download link.

Returns:



121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/berkshelf/community_rest.rb', line 121

def latest_version(name)
  response = get(name)

  case response.status
  when (200..299)
    self.class.version_from_uri response.body['latest_version']
  when 404
    raise CookbookNotFound, "Cookbook '#{name}' not found at site: '#{api_uri}'"
  else
    raise CommunitySiteError, "Error retrieving latest version of cookbook '#{name}' at site: '#{api_uri}'"
  end
end

#satisfy(name, constraint) ⇒ String

Parameters:

Returns:



156
157
158
159
160
# File 'lib/berkshelf/community_rest.rb', line 156

def satisfy(name, constraint)
  Solve::Solver.satisfy_best(constraint, versions(name)).to_s
rescue Solve::Errors::NoSolutionError
  nil
end

#stream(target) ⇒ Tempfile

Stream the response body of a remote URL to a file on the local file system

Parameters:

  • target (String)

    a URL to stream the response body from

Returns:

  • (Tempfile)


168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/berkshelf/community_rest.rb', line 168

def stream(target)
  local = Tempfile.new('community-rest-stream')
  local.binmode

  retryable(tries: retries, on: OpenURI::HTTPError, sleep: retry_interval) do
    open(target, 'rb', headers) do |remote|
      local.write(remote.read)
    end
  end

  local
ensure
  local.close(false) unless local.nil?
end

#versions(name) ⇒ Array

Parameters:

Returns:

  • (Array)


137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/berkshelf/community_rest.rb', line 137

def versions(name)
  response = get(name)

  case response.status
  when (200..299)
    response.body['versions'].collect do |version_uri|
      self.class.version_from_uri(version_uri)
    end
  when 404
    raise CookbookNotFound, "Cookbook '#{name}' not found at site: '#{api_uri}'"
  else
    raise CommunitySiteError, "Error retrieving versions of cookbook '#{name}' at site: '#{api_uri}'"
  end
end