1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
require "bundler"
require "omnibus"
require_relative "../build-chef-gem"
require_relative "../../../../tasks/gemfile_util"
module BuildChefGem
class GemInstallSoftwareDef
def self.define(software, software_filename)
new(software, software_filename).send(:define)
end
include BuildChefGem
include Omnibus::Logging
protected
def initialize(software, software_filename)
@software = software
@software_filename = software_filename
end
attr_reader :software, :software_filename
def define
software.name "#{File.basename(software_filename)[0..-4]}"
software.default_version gem_version
# If the source directory for building stuff changes, tell omnibus to
# de-cache us
software.source path: File.expand_path("../..", __FILE__)
# ruby and bundler and friends
software.dependency "ruby"
software.dependency "rubygems"
gem_name = self.gem_name
gem_version = self.gem_version
gem_metadata = self.gem_metadata
lockfile_path = self.lockfile_path
software.build do
extend BuildChefGem
if gem_version == "<skip>"
if gem_metadata
block do
log.info(log_key) { "#{gem_name} has source #{gem_metadata} in #{lockfile_path}. We only cache rubygems.org installs in omnibus to keep things simple. The chef step will build #{gem_name} ..." }
end
else
block do
log.info(log_key) { "#{gem_name} is not in the #{lockfile_path}. This can happen if your OS doesn't build it, or if chef no longer depends on it. Skipping ..." }
end
end
else
block do
log.info(log_key) { "Found version #{gem_version} of #{gem_name} in #{lockfile_path}. Building early to take advantage of omnibus caching ..." }
end
gem "install #{gem_name} -v #{gem_version} --no-doc --no-ri --ignore-dependencies --verbose -- #{install_args_for(gem_name)}", env: env
end
end
end
# Path above omnibus (where Gemfile is)
def root_path
File.expand_path("../../../../..", __FILE__)
end
def gemfile_path
# gemfile path could be relative to software filename (and often is)
@gemfile_path ||= begin
# Grab the version (and maybe source) from the lockfile so omnibus knows whether
# to toss the cache or not
gemfile_path = File.join(root_path, "Gemfile")
platform_gemfile_path = "#{gemfile_path}.#{Omnibus::Ohai["platform"]}"
if File.exist?(platform_gemfile_path)
gemfile_path = platform_gemfile_path
end
gemfile_path
end
end
def lockfile_path
@lockfile_path ||= "#{gemfile_path}.lock"
end
def gem_name
@gem_name ||= begin
# File must be named chef-<gemname>.rb
# Will look at chef/Gemfile.lock and install that version of the gem using "gem install"
# (and only that version)
if File.basename(software_filename) =~ /^chef-gem-(.+)\.rb$/
$1
else
raise "#{software_filename} must be named chef-<gemname>.rb to build a gem automatically"
end
end
end
def gem_metadata
@gem_metadata ||= begin
selected = GemfileUtil.select_gems(gemfile_path, without_groups: without_groups)
result = GemfileUtil.locked_gems(lockfile_path, selected)[gem_name]
if result
log.info(software.name) { "Using #{gem_name} version #{result[:version]} from #{gemfile_path}" }
result
elsif GemfileUtil.locked_gems(lockfile_path, GemfileUtil.select_gems(gemfile_path))[gem_name]
log.info(software.name) { "#{gem_name} not loaded from #{gemfile_path} because it was only in groups #{without_groups.join(", ")}, skipping" }
nil
else
raise "#{gem_name} not found in #{gemfile_path} or #{lockfile_path}"
end
end
end
def gem_version
@gem_version ||= begin
if gem_metadata && URI(gem_metadata[:source]) == URI("https://rubygems.org/")
gem_metadata[:version]
else
"<skip>"
end
end
end
end
end
|