Skip to content

Commit be7dfdb

Browse files
committed
Download latest dependencies
This is the third step in an effort to create a way to build offline- only buildpacks. This change uses the buildpack's DownloadCache and VersionResolver to populate a cache in the staging area. This cache contains the latest version (as identified by the configuration) of all of the dependencies that might be used by the buildpack at runtime. As this logic was so complex, this and the other offline build tasks were broken out into their own Task classes. [#67851722]
1 parent b518ba7 commit be7dfdb

9 files changed

Lines changed: 305 additions & 59 deletions

File tree

Rakefile

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
$LOAD_PATH.unshift File.expand_path('../rakelib', __FILE__)
18+
1719
require 'rake/clean'
18-
require 'rspec/core/rake_task'
19-
require 'rubocop/rake_task'
20-
require 'yard'
2120

21+
require 'rspec/core/rake_task'
2222
RSpec::Core::RakeTask.new
2323
CLOBBER << 'coverage'
2424

25+
require 'rubocop/rake_task'
2526
Rubocop::RakeTask.new
2627

28+
require 'yard'
2729
YARD::Rake::YardocTask.new
2830
CLEAN << '.yardoc'
2931
CLOBBER << 'doc'
@@ -34,4 +36,20 @@ task :check_api_doc do
3436
abort "\nFailed due to undocumented public API:\n\n#{output}" if output !~ /100.00% documented/
3537
end
3638

39+
require_relative 'rakelib/dependency_cache_task'
40+
require_relative 'rakelib/offline'
41+
require_relative 'rakelib/stage_buildpack_task'
42+
require_relative 'rakelib/tar_file_task'
43+
44+
CLOBBER << Offline::BUILD_DIR
45+
CLEAN << Offline::STAGING_DIR
46+
47+
dependency_cache_task = Offline::DependencyCacheTask.new
48+
stage_files_task = Offline::StageBuildpackTask.new(Dir['bin/**/*', 'config/**/*', 'lib/**/*', 'resources/**/*']
49+
.reject { |f| File.directory? f })
50+
tar_file_task = Offline::TarFileTask.new(dependency_cache_task, stage_files_task)
51+
52+
desc 'Create a buildpack for use offline'
53+
task offline: [tar_file_task.targets]
54+
3755
task default: %w(rubocop check_api_doc spec)

java-buildpack.iml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@
263263
<sourceFolder url="file://$MODULE_DIR$/spec/java_buildpack" isTestSource="true" />
264264
<excludeFolder url="file://$MODULE_DIR$/.idea" />
265265
<excludeFolder url="file://$MODULE_DIR$/.yardoc" />
266+
<excludeFolder url="file://$MODULE_DIR$/build" />
266267
<excludeFolder url="file://$MODULE_DIR$/coverage" />
267268
<excludeFolder url="file://$MODULE_DIR$/doc" />
268269
</content>

lib/java_buildpack/util/cache/file_cache.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def any_last_modified(&block)
126126
def data
127127
fail 'no data cached' unless cached?
128128
@cached.open(File::RDONLY) do |cached_file|
129-
yield cached_file
129+
yield cached_file if block_given?
130130
end
131131
end
132132

lib/java_buildpack/util/configuration_utils.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class << self
3737
# left to its default and exists to allow the logger to use the utility.
3838
# @return [Hash] the configuration or an empty hash if the configuration file does not exist
3939
def load(identifier, should_log = true)
40-
file = CACHE_DIRECTORY + "#{identifier}.yml"
40+
file = CONFIG_DIRECTORY + "#{identifier}.yml"
4141

4242
if file.exist?
4343
configuration = YAML.load_file(file)
@@ -51,7 +51,7 @@ def load(identifier, should_log = true)
5151

5252
private
5353

54-
CACHE_DIRECTORY = Pathname.new(File.expand_path('../../../config', File.dirname(__FILE__))).freeze
54+
CONFIG_DIRECTORY = Pathname.new(File.expand_path('../../../config', File.dirname(__FILE__))).freeze
5555

5656
def logger
5757
JavaBuildpack::Logging::LoggerFactory.get_logger ConfigurationUtils

rakelib/dependency_cache_task.rb

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# Encoding: utf-8
2+
# Cloud Foundry Java Buildpack
3+
# Copyright (c) 2014 the original author or authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
18+
19+
require 'java_buildpack/logging/logger_factory'
20+
require 'java_buildpack/repository/version_resolver'
21+
require 'java_buildpack/util/configuration_utils'
22+
require 'java_buildpack/util/cache/download_cache'
23+
require 'java_buildpack/util/snake_case'
24+
require 'offline'
25+
require 'pathname'
26+
require 'yaml'
27+
28+
module Offline
29+
30+
class DependencyCacheTask < Rake::TaskLib
31+
include Offline
32+
33+
attr_reader :targets
34+
35+
def initialize
36+
JavaBuildpack::Logging::LoggerFactory.setup "#{BUILD_DIR}/"
37+
38+
@default_repository_root = configuration('repository')['default_repository_root'].chomp('/')
39+
@cache = cache
40+
41+
configurations = component_ids.map { |component_id| configurations(configuration(component_id)) }.flatten
42+
@targets = uris(configurations).each { |uri| create_task(uri) }
43+
end
44+
45+
end
46+
47+
private
48+
49+
ARCHITECTURE_PATTERN = /\{architecture\}/.freeze
50+
51+
DEFAULT_REPOSITORY_ROOT_PATTERN = /\{default.repository.root\}/.freeze
52+
53+
PLATFORM_PATTERN = /\{platform\}/.freeze
54+
55+
def augment_architecture(raw)
56+
if raw.respond_to? :map
57+
raw.map { |r| augment_architecture r }
58+
else
59+
raw =~ ARCHITECTURE_PATTERN ? ARCHITECTURES.map { |p| raw.gsub ARCHITECTURE_PATTERN, p } : raw
60+
end
61+
end
62+
63+
def augment_path(raw)
64+
if raw.respond_to? :map
65+
raw.map { |r| augment_path r }
66+
else
67+
"#{raw.chomp('/')}/index.yml"
68+
end
69+
end
70+
71+
def augment_platform(raw)
72+
if raw.respond_to? :map
73+
raw.map { |r| augment_platform r }
74+
else
75+
raw =~ PLATFORM_PATTERN ? PLATFORMS.map { |p| raw.gsub PLATFORM_PATTERN, p } : raw
76+
end
77+
end
78+
79+
def augment_repository_root(raw)
80+
if raw.respond_to? :map
81+
raw.map { |r| augment_repository_root r }
82+
else
83+
raw.gsub DEFAULT_REPOSITORY_ROOT_PATTERN, @default_repository_root
84+
end
85+
end
86+
87+
def cache
88+
JavaBuildpack::Util::Cache::DownloadCache.new(Pathname.new("#{STAGING_DIR}/resources/cache")).freeze
89+
end
90+
91+
def component_ids
92+
configuration('components').values.flatten.map { |component| component.split('::').last.snake_case }
93+
end
94+
95+
def configuration(id)
96+
JavaBuildpack::Util::ConfigurationUtils.load(id, false)
97+
end
98+
99+
def configurations(configuration)
100+
configurations = []
101+
102+
if repository_configuration?(configuration)
103+
configurations << configuration
104+
else
105+
configurations << configuration.values.map { |v| configurations(v) }
106+
end
107+
108+
configurations
109+
end
110+
111+
def index_uris(configuration)
112+
[configuration['repository_root']]
113+
.map { |r| augment_repository_root r }
114+
.map { |r| augment_platform r }
115+
.map { |r| augment_architecture r }
116+
.map { |r| augment_path r }.flatten
117+
end
118+
119+
def repository_configuration?(configuration)
120+
configuration['version'] && configuration['repository_root']
121+
end
122+
123+
def uris(configurations)
124+
uris = []
125+
126+
configurations.each do |configuration|
127+
index_uris(configuration).each do |index_uri|
128+
@cache.get(index_uri) do |file|
129+
index = YAML.load(file)
130+
uris << index[version(configuration, index).to_s]
131+
end
132+
end
133+
end
134+
135+
uris
136+
end
137+
138+
def version(configuration, index)
139+
JavaBuildpack::Repository::VersionResolver.resolve(JavaBuildpack::Util::TokenizedVersion.new(configuration['version']), index.keys)
140+
end
141+
142+
def create_task(uri)
143+
task uri do |t|
144+
puts "Caching #{t.name}"
145+
cache.get(t.name)
146+
end
147+
148+
uri
149+
end
150+
151+
end

rakelib/offline.rake

Lines changed: 0 additions & 53 deletions
This file was deleted.

rakelib/offline.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Encoding: utf-8
2+
# Cloud Foundry Java Buildpack
3+
# Copyright (c) 2014 the original author or authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
module Offline
18+
19+
ARCHITECTURES = %w(x86_64)
20+
21+
BUILD_DIR = 'build'.freeze
22+
23+
PLATFORMS = %w(centos6 lucid mountainlion precise)
24+
25+
STAGING_DIR = "#{BUILD_DIR}/staging".freeze
26+
27+
def verbose?
28+
verbose == true
29+
end
30+
31+
end

rakelib/stage_buildpack_task.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Encoding: utf-8
2+
# Cloud Foundry Java Buildpack
3+
# Copyright (c) 2014 the original author or authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
require 'offline'
18+
19+
module Offline
20+
21+
class StageBuildpackTask < Rake::TaskLib
22+
include Offline
23+
24+
attr_reader :targets
25+
26+
def initialize(source_files)
27+
@targets = source_files.map { |source| create_task(source, target(source)) }
28+
end
29+
30+
def target(source)
31+
"#{STAGING_DIR}/#{source}"
32+
end
33+
34+
private
35+
36+
def create_task(source, target)
37+
file(target => [source]) do |t|
38+
rm_f t.name, verbose: verbose?
39+
mkdir_p File.dirname(t.name), verbose: verbose?
40+
cp t.source, t.name, verbose: verbose?
41+
end
42+
43+
target
44+
end
45+
46+
end
47+
48+
end

0 commit comments

Comments
 (0)