buildpack-support 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +202 -0
- data/NOTICE +2 -0
- data/docs/cache.md +77 -0
- data/docs/component.md +1 -0
- data/docs/configuration.md +27 -0
- data/docs/logging.md +54 -0
- data/docs/other.md +1 -0
- data/docs/rake.md +1 -0
- data/docs/repository.md +116 -0
- data/docs/test.md +1 -0
- data/lib/buildpack_support.rb +18 -0
- data/lib/buildpack_support/base_buildpack.rb +166 -0
- data/lib/buildpack_support/buildpack_version.rb +124 -0
- data/lib/buildpack_support/cache.rb +24 -0
- data/lib/buildpack_support/cache/application_cache.rb +41 -0
- data/lib/buildpack_support/cache/cached_file.rb +103 -0
- data/lib/buildpack_support/cache/download_cache.rb +280 -0
- data/lib/buildpack_support/cache/inferred_network_failure.rb +26 -0
- data/lib/buildpack_support/cache/internet_availability.rb +64 -0
- data/lib/buildpack_support/component.rb +24 -0
- data/lib/buildpack_support/component/application.rb +76 -0
- data/lib/buildpack_support/component/base_component.rb +78 -0
- data/lib/buildpack_support/component/base_droplet.rb +96 -0
- data/lib/buildpack_support/component/downloads.rb +88 -0
- data/lib/buildpack_support/component/services.rb +84 -0
- data/lib/buildpack_support/component/versioned_dependency_component.rb +71 -0
- data/lib/buildpack_support/component/versioned_downloads.rb +57 -0
- data/lib/buildpack_support/component/with_timing.rb +40 -0
- data/lib/buildpack_support/configuration_utils.rb +58 -0
- data/lib/buildpack_support/constantize.rb +46 -0
- data/lib/buildpack_support/dash_case.rb +29 -0
- data/lib/buildpack_support/directory_finder.rb +45 -0
- data/lib/buildpack_support/filtering_pathname.rb +227 -0
- data/lib/buildpack_support/format_duration.rb +57 -0
- data/lib/buildpack_support/logging.rb +22 -0
- data/lib/buildpack_support/logging/delegating_logger.rb +48 -0
- data/lib/buildpack_support/logging/logger_factory.rb +148 -0
- data/lib/buildpack_support/qualify_path.rb +36 -0
- data/lib/buildpack_support/rake.rb +22 -0
- data/lib/buildpack_support/rake/buildpack_stage_task.rb +86 -0
- data/lib/buildpack_support/rake/cached_artifact_finder.rb +99 -0
- data/lib/buildpack_support/rake/check_api_doc_task.rb +70 -0
- data/lib/buildpack_support/rake/dependency_cache_task.rb +87 -0
- data/lib/buildpack_support/rake/disable_remote_downloads_task.rb +80 -0
- data/lib/buildpack_support/rake/package_task.rb +133 -0
- data/lib/buildpack_support/rake/package_zip_task.rb +80 -0
- data/lib/buildpack_support/rake/repository_configuration_finder.rb +66 -0
- data/lib/buildpack_support/rake/write_version_file_task.rb +82 -0
- data/lib/buildpack_support/repository.rb +24 -0
- data/lib/buildpack_support/repository/configured_item.rb +81 -0
- data/lib/buildpack_support/repository/repository_index.rb +98 -0
- data/lib/buildpack_support/repository/wildcard_version_resolver.rb +75 -0
- data/lib/buildpack_support/shell.rb +41 -0
- data/lib/buildpack_support/snake_case.rb +30 -0
- data/lib/buildpack_support/space_case.rb +29 -0
- data/lib/buildpack_support/test/application_helper.rb +41 -0
- data/lib/buildpack_support/test/base_component_helper.rb +59 -0
- data/lib/buildpack_support/test/base_droplet_helper.rb +36 -0
- data/lib/buildpack_support/test/console_helper.rb +57 -0
- data/lib/buildpack_support/test/environment_helper.rb +32 -0
- data/lib/buildpack_support/test/internet_availability_helper.rb +29 -0
- data/lib/buildpack_support/test/logging_helper.rb +50 -0
- data/lib/buildpack_support/test/scratch_helper.rb +32 -0
- data/lib/buildpack_support/test/versioned_dependency_component_helper.rb +32 -0
- data/lib/buildpack_support/test/with_load_path_helper.rb +27 -0
- data/lib/buildpack_support/to_b.rb +38 -0
- data/lib/buildpack_support/tokenized_version.rb +157 -0
- data/lib/buildpack_support/version.rb +23 -0
- data/spec/buildpack_support/base_buildpack_spec.rb +112 -0
- data/spec/buildpack_support/buildpack_version_spec.rb +122 -0
- data/spec/buildpack_support/cache/application_cache_spec.rb +56 -0
- data/spec/buildpack_support/cache/cached_file_spec.rb +94 -0
- data/spec/buildpack_support/cache/download_cache_spec.rb +293 -0
- data/spec/buildpack_support/cache/internet_availability_spec.rb +57 -0
- data/spec/buildpack_support/cache/yield_file_with_content.rb +30 -0
- data/spec/buildpack_support/component/application_spec.rb +81 -0
- data/spec/buildpack_support/component/base_component_spec.rb +81 -0
- data/spec/buildpack_support/component/base_droplet_spec.rb +72 -0
- data/spec/buildpack_support/component/downloads_spec.rb +63 -0
- data/spec/buildpack_support/component/services_spec.rb +80 -0
- data/spec/buildpack_support/component/versioned_dependency_component_spec.rb +58 -0
- data/spec/buildpack_support/component/versioned_downloads_spec.rb +58 -0
- data/spec/buildpack_support/component/with_timing_spec.rb +30 -0
- data/spec/buildpack_support/configuration_utils_spec.rb +39 -0
- data/spec/buildpack_support/constantize_spec.rb +34 -0
- data/spec/buildpack_support/dash_case_spec.rb +41 -0
- data/spec/buildpack_support/directory_finder_spec.rb +41 -0
- data/spec/buildpack_support/filtering_pathname_spec.rb +443 -0
- data/spec/buildpack_support/format_duration_spec.rb +60 -0
- data/spec/buildpack_support/logging/delegating_logger_spec.rb +62 -0
- data/spec/buildpack_support/logging/logger_factory_spec.rb +262 -0
- data/spec/buildpack_support/qualify_path_spec.rb +42 -0
- data/spec/buildpack_support/rake/buildpack_stage_task_spec.rb +88 -0
- data/spec/buildpack_support/rake/cached_artifact_finder_spec.rb +73 -0
- data/spec/buildpack_support/rake/check_api_doc_task_spec.rb +69 -0
- data/spec/buildpack_support/rake/dependency_cache_task_spec.rb +133 -0
- data/spec/buildpack_support/rake/disable_remote_downloads_task_spec.rb +91 -0
- data/spec/buildpack_support/rake/package_task_spec.rb +335 -0
- data/spec/buildpack_support/rake/package_zip_task_spec.rb +91 -0
- data/spec/buildpack_support/rake/repository_configuration_finder_spec.rb +61 -0
- data/spec/buildpack_support/rake/write_version_file_task_spec.rb +96 -0
- data/spec/buildpack_support/repository/configured_item_spec.rb +78 -0
- data/spec/buildpack_support/repository/repository_index_spec.rb +118 -0
- data/spec/buildpack_support/repository/wildcard_version_resolver_spec.rb +73 -0
- data/spec/buildpack_support/shell_spec.rb +32 -0
- data/spec/buildpack_support/snake_case_spec.rb +45 -0
- data/spec/buildpack_support/space_case_spec.rb +41 -0
- data/spec/buildpack_support/to_b_spec.rb +41 -0
- data/spec/buildpack_support/tokenized_version_spec.rb +132 -0
- data/spec/fixtures/application/test-file +0 -0
- data/spec/fixtures/config/found-config.yml +2 -0
- data/spec/fixtures/droplet-resources/droplet-resource +0 -0
- data/spec/fixtures/stub-download-with-top-level.zip +0 -0
- data/spec/fixtures/stub-download.tar.gz +0 -0
- data/spec/fixtures/stub-download.zip +0 -0
- data/spec/fixtures/test-cache.yml +18 -0
- data/spec/fixtures/test-index.yml +2 -0
- data/spec/fixtures/test_component.rb +0 -0
- data/spec/fixtures/zip-contents/test-directory/test-deep-file +0 -0
- data/spec/fixtures/zip-contents/test-file +0 -0
- data/spec/spec_helper.rb +30 -0
- metadata +416 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# Encoding: utf-8
|
|
2
|
+
# Copyright 2013-2014 the original author or authors.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
require 'buildpack_support/cache'
|
|
17
|
+
require 'buildpack_support/cache/cached_file'
|
|
18
|
+
require 'buildpack_support/cache/inferred_network_failure'
|
|
19
|
+
require 'buildpack_support/cache/internet_availability'
|
|
20
|
+
require 'buildpack_support/directory_finder'
|
|
21
|
+
require 'buildpack_support/logging/logger_factory'
|
|
22
|
+
require 'monitor'
|
|
23
|
+
require 'net/http'
|
|
24
|
+
require 'tmpdir'
|
|
25
|
+
require 'uri'
|
|
26
|
+
|
|
27
|
+
module BuildpackSupport
|
|
28
|
+
module Cache
|
|
29
|
+
|
|
30
|
+
# A cache for downloaded files that is configured to use a filesystem as the backing store.
|
|
31
|
+
#
|
|
32
|
+
# Note: this class is thread-safe, however access to the cached files is not
|
|
33
|
+
#
|
|
34
|
+
# References:
|
|
35
|
+
# * {https://en.wikipedia.org/wiki/HTTP_ETag ETag Wikipedia Definition}
|
|
36
|
+
# * {http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html HTTP/1.1 Header Field Definitions}
|
|
37
|
+
class DownloadCache
|
|
38
|
+
extend DirectoryFinder
|
|
39
|
+
|
|
40
|
+
# The location to find cached resources in the buildpack
|
|
41
|
+
CACHED_RESOURCES_DIRECTORY = DownloadCache.load_path_peer('resources/cache').freeze
|
|
42
|
+
|
|
43
|
+
# Creates an instance of the cache that is backed by a number of filesystem locations. The first argument
|
|
44
|
+
# (+mutable_cache_root+) is the only location that downloaded files will be stored in.
|
|
45
|
+
#
|
|
46
|
+
# @param [Pathname] mutable_cache_root the filesystem location in which find cached files in. This will also be
|
|
47
|
+
# the location that all downloaded files are written to.
|
|
48
|
+
# @param [Pathname] immutable_cache_roots other filesystem locations to find cached files in. No files will be
|
|
49
|
+
# written to these locations.
|
|
50
|
+
def initialize(mutable_cache_root = Pathname.new(Dir.tmpdir), *immutable_cache_roots)
|
|
51
|
+
@logger = BuildpackSupport::Logging::LoggerFactory.instance.get_logger DownloadCache
|
|
52
|
+
@mutable_cache_root = mutable_cache_root
|
|
53
|
+
@immutable_cache_roots = immutable_cache_roots.unshift mutable_cache_root
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Retrieves an item from the cache. Yields an open file containing the item's content or raises an exception if
|
|
57
|
+
# the item cannot be retrieved.
|
|
58
|
+
#
|
|
59
|
+
# @param [String] uri the URI of the item
|
|
60
|
+
# @yield [file, downloaded] the file representing the cached item and whether the file was downloaded or was
|
|
61
|
+
# already in the cache
|
|
62
|
+
# @return [Void]
|
|
63
|
+
def get(uri, &block)
|
|
64
|
+
cached_file, downloaded = nil, nil
|
|
65
|
+
cached_file, downloaded = from_mutable_cache uri if InternetAvailability.instance.available?
|
|
66
|
+
cached_file, downloaded = from_immutable_caches(uri), false unless cached_file
|
|
67
|
+
|
|
68
|
+
fail "Unable to find cached file for #{uri}" unless cached_file
|
|
69
|
+
cached_file.cached(File::RDONLY, downloaded, &block)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Removes an item from the mutable cache.
|
|
73
|
+
#
|
|
74
|
+
# @param [String] uri the URI of the item
|
|
75
|
+
# @return [Void]
|
|
76
|
+
def evict(uri)
|
|
77
|
+
CachedFile.new(@mutable_cache_root, uri).destroy
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
FAILURE_LIMIT = 5.freeze
|
|
83
|
+
|
|
84
|
+
HTTP_ERRORS = [
|
|
85
|
+
EOFError,
|
|
86
|
+
Errno::ECONNABORTED,
|
|
87
|
+
Errno::ECONNREFUSED,
|
|
88
|
+
Errno::ECONNRESET,
|
|
89
|
+
Errno::EHOSTDOWN,
|
|
90
|
+
Errno::EHOSTUNREACH,
|
|
91
|
+
Errno::EINVAL,
|
|
92
|
+
Errno::ENETDOWN,
|
|
93
|
+
Errno::ENETRESET,
|
|
94
|
+
Errno::ENETUNREACH,
|
|
95
|
+
Errno::ENONET,
|
|
96
|
+
Errno::ENOTCONN,
|
|
97
|
+
Errno::EPIPE,
|
|
98
|
+
Errno::ETIMEDOUT,
|
|
99
|
+
Net::HTTPBadResponse,
|
|
100
|
+
Net::HTTPHeaderSyntaxError,
|
|
101
|
+
Net::ProtocolError,
|
|
102
|
+
SocketError,
|
|
103
|
+
Timeout::Error
|
|
104
|
+
].freeze
|
|
105
|
+
|
|
106
|
+
REDIRECT_TYPES = [
|
|
107
|
+
Net::HTTPMovedPermanently,
|
|
108
|
+
Net::HTTPFound,
|
|
109
|
+
Net::HTTPSeeOther,
|
|
110
|
+
Net::HTTPTemporaryRedirect
|
|
111
|
+
].freeze
|
|
112
|
+
|
|
113
|
+
TIMEOUT_SECONDS = 10.freeze
|
|
114
|
+
|
|
115
|
+
private_constant :FAILURE_LIMIT, :HTTP_ERRORS, :REDIRECT_TYPES, :TIMEOUT_SECONDS
|
|
116
|
+
|
|
117
|
+
def attempt(http, request, cached_file)
|
|
118
|
+
downloaded = false
|
|
119
|
+
|
|
120
|
+
http.request request do |response|
|
|
121
|
+
@logger.debug { "Status: #{response.code}" }
|
|
122
|
+
|
|
123
|
+
if response.is_a? Net::HTTPOK
|
|
124
|
+
cache_etag response, cached_file
|
|
125
|
+
cache_last_modified response, cached_file
|
|
126
|
+
cache_content response, cached_file
|
|
127
|
+
downloaded = true
|
|
128
|
+
elsif response.is_a? Net::HTTPNotModified
|
|
129
|
+
@logger.debug { 'Cached copy up to date' }
|
|
130
|
+
elsif redirect?(response)
|
|
131
|
+
downloaded = update URI(response['Location']), cached_file
|
|
132
|
+
else
|
|
133
|
+
fail InferredNetworkFailure, "Bad response: #{response}"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
downloaded
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def cache_content(response, cached_file)
|
|
141
|
+
cached_file.cached(File::CREAT | File::WRONLY) do |f|
|
|
142
|
+
@logger.debug { "Persisting content to #{f.path}" }
|
|
143
|
+
|
|
144
|
+
f.truncate(0)
|
|
145
|
+
response.read_body { |chunk| f.write chunk }
|
|
146
|
+
f.fsync
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
validate_size response['Content-Length'], cached_file
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def cache_etag(response, cached_file)
|
|
153
|
+
etag = response['Etag']
|
|
154
|
+
|
|
155
|
+
return unless etag
|
|
156
|
+
|
|
157
|
+
@logger.debug { "Persisting etag: #{etag}" }
|
|
158
|
+
|
|
159
|
+
cached_file.etag(File::CREAT | File::WRONLY) do |f|
|
|
160
|
+
f.truncate(0)
|
|
161
|
+
f.write etag
|
|
162
|
+
f.fsync
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def cache_last_modified(response, cached_file)
|
|
167
|
+
last_modified = response['Last-Modified']
|
|
168
|
+
|
|
169
|
+
return unless last_modified
|
|
170
|
+
|
|
171
|
+
@logger.debug { "Persisting last-modified: #{last_modified}" }
|
|
172
|
+
|
|
173
|
+
cached_file.last_modified(File::CREAT | File::WRONLY) do |f|
|
|
174
|
+
f.truncate(0)
|
|
175
|
+
f.write last_modified
|
|
176
|
+
f.fsync
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def from_mutable_cache(uri)
|
|
181
|
+
cached_file = CachedFile.new(@mutable_cache_root, uri)
|
|
182
|
+
cached = update URI(uri), cached_file
|
|
183
|
+
[cached_file, cached]
|
|
184
|
+
rescue => e
|
|
185
|
+
@logger.warn { "Unable to download #{uri} into cache #{@mutable_cache_root}: #{e.message}" }
|
|
186
|
+
nil
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def from_immutable_caches(uri)
|
|
190
|
+
@immutable_cache_roots.each do |cache_root|
|
|
191
|
+
candidate = CachedFile.new cache_root, uri
|
|
192
|
+
|
|
193
|
+
next unless candidate.cached?
|
|
194
|
+
|
|
195
|
+
@logger.debug { "#{uri} found in cache #{cache_root}" }
|
|
196
|
+
return candidate
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
nil
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Beware known problems with timeouts: https://www.ruby-forum.com/topic/143840
|
|
203
|
+
def http_options(rich_uri)
|
|
204
|
+
{ read_timeout: TIMEOUT_SECONDS,
|
|
205
|
+
connect_timeout: TIMEOUT_SECONDS,
|
|
206
|
+
open_timeout: TIMEOUT_SECONDS,
|
|
207
|
+
use_ssl: secure?(rich_uri) }
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def proxy(uri)
|
|
211
|
+
proxy_uri = if secure?(uri)
|
|
212
|
+
URI.parse(ENV['https_proxy'] || ENV['HTTPS_PROXY'] || '')
|
|
213
|
+
else
|
|
214
|
+
URI.parse(ENV['http_proxy'] || ENV['HTTP_PROXY'] || '')
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
@logger.debug { "Proxy: #{proxy_uri.host}, #{proxy_uri.port}, #{proxy_uri.user}, #{proxy_uri.password}" }
|
|
218
|
+
Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def redirect?(response)
|
|
222
|
+
REDIRECT_TYPES.any? { |t| response.is_a? t }
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def request(uri, cached_file)
|
|
226
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
|
227
|
+
|
|
228
|
+
if cached_file.etag?
|
|
229
|
+
cached_file.etag(File::RDONLY) { |f| request['If-None-Match'] = File.read(f) }
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
if cached_file.last_modified?
|
|
233
|
+
cached_file.last_modified(File::RDONLY) { |f| request['If-Modified-Since'] = File.read(f) }
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
@logger.debug { "Request: #{request.path}, #{request.to_hash}" }
|
|
237
|
+
request
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def secure?(uri)
|
|
241
|
+
uri.scheme == 'https'
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def update(uri, cached_file)
|
|
245
|
+
proxy(uri).start(uri.host, uri.port, http_options(uri)) do |http|
|
|
246
|
+
@logger.debug { "HTTP: #{http.address}, #{http.port}, #{http_options(uri)}" }
|
|
247
|
+
request = request uri, cached_file
|
|
248
|
+
request.basic_auth uri.user, uri.password
|
|
249
|
+
|
|
250
|
+
failures = 0
|
|
251
|
+
begin
|
|
252
|
+
attempt http, request, cached_file
|
|
253
|
+
rescue InferredNetworkFailure, *HTTP_ERRORS => e
|
|
254
|
+
if (failures += 1) > FAILURE_LIMIT
|
|
255
|
+
InternetAvailability.instance.available false, "Request failed: #{e.message}"
|
|
256
|
+
raise e
|
|
257
|
+
else
|
|
258
|
+
@logger.warn { "Request failure #{failures}, retrying: #{e.message}" }
|
|
259
|
+
retry
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def validate_size(expected_size, cached_file)
|
|
266
|
+
return unless expected_size
|
|
267
|
+
|
|
268
|
+
actual_size = cached_file.cached(File::RDONLY) { |f| f.size }
|
|
269
|
+
@logger.debug { "Validated content size #{actual_size} is #{expected_size}" }
|
|
270
|
+
|
|
271
|
+
return if expected_size.to_i == actual_size
|
|
272
|
+
|
|
273
|
+
cached_file.destroy
|
|
274
|
+
fail InferredNetworkFailure, "Content has invalid size. Was #{actual_size}, should be #{expected_size}."
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
end
|
|
280
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Encoding: utf-8
|
|
2
|
+
# Copyright 2013-2014 the original author or authors.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
require 'buildpack_support/cache'
|
|
17
|
+
|
|
18
|
+
module BuildpackSupport
|
|
19
|
+
module Cache
|
|
20
|
+
|
|
21
|
+
# An error thrown when a we infer that an error has occurred (rather than receiving an explicit indication)
|
|
22
|
+
class InferredNetworkFailure < StandardError
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Encoding: utf-8
|
|
2
|
+
# Copyright 2013-2014 the original author or authors.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
require 'buildpack_support/cache'
|
|
17
|
+
require 'buildpack_support/configuration_utils'
|
|
18
|
+
require 'buildpack_support/logging/logger_factory'
|
|
19
|
+
require 'monitor'
|
|
20
|
+
require 'singleton'
|
|
21
|
+
|
|
22
|
+
module BuildpackSupport
|
|
23
|
+
module Cache
|
|
24
|
+
|
|
25
|
+
# Maintains the current state of internet availability.
|
|
26
|
+
class InternetAvailability
|
|
27
|
+
include ::Singleton
|
|
28
|
+
|
|
29
|
+
# Creates a new instance. Availability is assumed to be +true+ unless +remote_downloads+ is set to +disabled+
|
|
30
|
+
# in +config/cache.yml+.
|
|
31
|
+
def initialize
|
|
32
|
+
@logger = BuildpackSupport::Logging::LoggerFactory.instance.get_logger InternetAvailability
|
|
33
|
+
@monitor = Monitor.new
|
|
34
|
+
@monitor.synchronize { @available = remote_downloads? }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns whether the internet is available
|
|
38
|
+
#
|
|
39
|
+
# @return [Boolean] +true+ if the internet is available, +false+ otherwise
|
|
40
|
+
def available?
|
|
41
|
+
@monitor.synchronize { @available }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Sets whether the internet is available
|
|
45
|
+
#
|
|
46
|
+
# @param [Boolean] available whether the internet is available
|
|
47
|
+
# @param [String, nil] message an optional message to be printed when the availability is set
|
|
48
|
+
def available(available, message = nil)
|
|
49
|
+
@monitor.synchronize do
|
|
50
|
+
@available = available
|
|
51
|
+
@logger.warn { "Internet availability set to #{available}: #{message}" } if message
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def remote_downloads?
|
|
58
|
+
BuildpackSupport::ConfigurationUtils.new.load('cache')['remote_downloads'] != 'disabled'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Encoding: utf-8
|
|
2
|
+
# Copyright 2013-2014 the original author or authors.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
require 'buildpack_support'
|
|
17
|
+
|
|
18
|
+
module BuildpackSupport
|
|
19
|
+
|
|
20
|
+
# A module encapsulating all of the code for the component utilities
|
|
21
|
+
module Component
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Encoding: utf-8
|
|
2
|
+
# Copyright 2013-2014 the original author or authors.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
require 'buildpack_support/component'
|
|
17
|
+
require 'buildpack_support/component/services'
|
|
18
|
+
require 'buildpack_support/filtering_pathname'
|
|
19
|
+
require 'yaml'
|
|
20
|
+
|
|
21
|
+
module BuildpackSupport
|
|
22
|
+
module Component
|
|
23
|
+
|
|
24
|
+
# An abstraction around the application as uploaded by the user. This abstraction is intended to hide any
|
|
25
|
+
# modifications made to the filesystem by other components. Think of this as an immutable representation of the
|
|
26
|
+
# application as it was uploaded.
|
|
27
|
+
#
|
|
28
|
+
# A new instance of this type should be created once for the application.
|
|
29
|
+
class Application
|
|
30
|
+
|
|
31
|
+
# @!attribute [r] details
|
|
32
|
+
# @return [Hash] the parsed contents of the +VCAP_APPLICATION+ environment variable
|
|
33
|
+
attr_reader :details
|
|
34
|
+
|
|
35
|
+
# @!attribute [r] environment
|
|
36
|
+
# @return [Hash] all environment variables except +VCAP_APPLICATION+ and +VCAP_SERVICES+. Those values are
|
|
37
|
+
# available separately in parsed form.
|
|
38
|
+
attr_reader :environment
|
|
39
|
+
|
|
40
|
+
# @!attribute [r] root
|
|
41
|
+
# @return [BuildpackSupport::FilteringPathname] the root of the application's fileystem filtered so that it only
|
|
42
|
+
# shows files that have been uploaded by the user
|
|
43
|
+
attr_reader :root
|
|
44
|
+
|
|
45
|
+
# @!attribute [r] services
|
|
46
|
+
# @return [Hash] the parsed contents of the +VCAP_SERVICES+ environment variable
|
|
47
|
+
attr_reader :services
|
|
48
|
+
|
|
49
|
+
# Create a new instance of the application abstraction
|
|
50
|
+
#
|
|
51
|
+
# @param [Pathname] root the root of the application
|
|
52
|
+
def initialize(root)
|
|
53
|
+
initial = children(root)
|
|
54
|
+
@root = BuildpackSupport::FilteringPathname.new(root, ->(path) { initial.member? path }, false)
|
|
55
|
+
|
|
56
|
+
@environment = ENV.to_hash
|
|
57
|
+
@details = parse(@environment.delete('VCAP_APPLICATION'))
|
|
58
|
+
@services = Services.new(parse(@environment.delete('VCAP_SERVICES')))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def children(root, s = Set.new)
|
|
64
|
+
s << root
|
|
65
|
+
root.children.each { |child| children(child, s) } if root.directory?
|
|
66
|
+
s
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def parse(input)
|
|
70
|
+
input ? YAML.load(input) : {}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|