forked from kaorimatz/packer-templates
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathRakefile
305 lines (267 loc) · 9.28 KB
/
Rakefile
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
require 'json'
require 'net/http'
require 'pathname'
require 'rainbow'
require 'rspec/core/rake_task'
require 'uri'
VAGRANT_PROVIDERS = {
virtualbox: {
builder_type: 'virtualbox-iso'
},
vmware_desktop: {
builder_type: 'vmware-iso'
}
}.freeze
task default: ['packer:validate', 'packer:check_iso_url']
namespace :packer do
desc 'Validate all the packer templates'
task :validate do
Pathname.glob('*.json').sort.each do |template|
puts Rainbow("Validating #{template}...").green
unless system "packer validate #{template}"
puts Rainbow("#{template} is not a valid packer template").red
raise "#{template} is not a valid packer template"
end
end
end
desc 'Check if all the ISO URLs are available'
task :check_iso_url do
Pathname.glob('*.json').sort.each do |template|
json = JSON.parse(template.read)
mirror = json['variables']['mirror']
iso_urls = json['builders'].map do |builder|
builder['iso_url'].sub('{{user `mirror`}}', mirror)
end
iso_urls.uniq.each do |iso_url|
puts Rainbow("Checking if #{iso_url} is available...").green
request_head(iso_url) do |response|
unless available?(response)
puts Rainbow("#{iso_url} is not available: #{response.message}").red
raise "#{iso_url} is not available"
end
end
end
end
end
desc 'Build and upload the vagrant box to Atlas'
task :release, [:template, :slug, :version, :provider] do |_t, args|
template = Pathname.new(args[:template])
slug = args[:slug]
version = args[:version]
provider = args[:provider]
json = JSON.parse(template.read)
builders = json['builders']
builders.select! do |builder|
builder['type'] == VAGRANT_PROVIDERS[provider.to_sym][:builder_type]
end
post_processors = json['post-processors']
post_processors << atlas_post_processor_config(slug, version, provider)
json['post-processors'] = [post_processors]
file = Tempfile.open('packer-templates') do |f|
f.tap do |f|
JSON.dump(json, f)
end
end
unless system("packer build -var-file=vars/release.json '#{file.path}'")
puts Rainbow("Failed to release #{slug} to Atlas").red
raise "Failed to release #{slug} to Atlas"
end
end
end
desc 'Run serverspec tests'
RSpec::Core::RakeTask.new(:spec, :host) do |_t, args|
ENV['HOST'] = args[:host]
end
namespace :reallyenglish do
require 'yaml'
require 'vagrant_cloud'
vagrantcloud_user_name = ENV["VAGRANTCLOUD_USERNAME"] || "mitsuruy"
# workaround "can't find executable vagrant for gem vagrant. vagrant is not
# currently included in the bundle, perhaps you meant to add it to your
# Gemfile? (Gem::Exception)". in _bundled_ environemnt, bundler cannot find
# `vagrant` gem installed outside of the environment.
vagrant_path = ""
Bundler.with_clean_env do
vagrant_path = Pathname.new(`gem which vagrant`).parent.parent + 'bin'
end
ENV['PATH'] = "#{vagrant_path}:#{ENV['PATH']}"
@yaml = YAML.load_file("box.reallyenglish.yml")
@all_boxes = @yaml["box"].map { |i| i["name"] }
ENV['VAGRANT_VAGRANTFILE'] = 'Vagrantfile.reallyenglish'
namespace 'test' do
def vagrant_hostname(name)
"#{name.gsub(/[.]/, '_')}-virtualbox"
end
def version_of(name)
box = @yaml["box"].select { |i| i["name"] == name }.first
raise "cannot find #{name}" unless box
raise "box #{name} does not have `version` key" unless box.key?("version")
box["version"]
end
desc 'build and test all boxes'
task :all => @all_boxes.map { |i| "test:#{i}" }
@all_boxes.each do |b|
desc "Test #{b}"
tasks = [ "reallyenglish:build:#{b}", "reallyenglish:import:#{b}",
"reallyenglish:boot:#{b}", "reallyenglish:spec:#{b}",
"reallyenglish:destroy:#{b}" ]
task b.to_sym => tasks do |_t|
# boot the box with single CPU to test if the box boots. no spec files
# are executed because what is tested here is that the box is able to
# boot with a single CPU. when it does not, vagrant will fail.
#
# requested at https://github.com/reallyenglish/packer-templates/pull/54#pullrequestreview-70731612
Rake::Task["reallyenglish:boot_single_cpu:#{b}"].execute
Rake::Task["reallyenglish:destroy:#{b}"].execute
end
end
end
namespace 'build' do
desc 'build all boxes'
task :all => @all_boxes.map { |i| "build:#{i}" }
@all_boxes.each do |b|
desc "Build #{b}"
task b.to_sym do |_t|
json_file = "#{b}.json"
r = system("packer build -only virtualbox-iso -var 'cpus=#{ ENV['VAGRANT_CPU_CORE'] || 2 }' '#{json_file}'")
raise "Failed to build #{i}" unless r
end
end
end
namespace 'import' do
desc 'import all boxes'
task :all => @all_boxes.map { |i| "import:#{i}" }
@all_boxes.each do |b|
desc "import #{b} as a test box"
task b.to_sym do |_t|
box_name = "#{vagrantcloud_user_name}/test-#{b}"
box_file = "#{b}-virtualbox.box"
r = system("vagrant box add --force --name '#{box_name}' '#{box_file}'")
raise "Failed to box add test image #{b}" unless r
end
end
end
namespace 'boot' do
desc 'boot all boxes'
task :all => @all_boxes.map { |i| "boot:#{i}" }
@all_boxes.each do |b|
desc "boot #{b} box"
task b.to_sym do |_t|
r = system("vagrant up '#{vagrant_hostname(b)}'")
raise "Failed to boot #{i}" unless r
end
end
end
namespace 'boot_single_cpu' do
desc 'boot all boxes with single CPU'
task :all => @all_boxes.map { |i| "boot_single_cpu:#{i}" }
@all_boxes.each do |b|
desc "boot #{b} box with single CPU"
task b.to_sym do |_t|
env_defined = ENV['VAGRANT_CPU_CORE'] ? true : false
old_env = nil
if env_defined
old_env = ENV['VAGRANT_CPU_CORE']
end
ENV['VAGRANT_CPU_CORE'] = "1"
r = system("vagrant up '#{vagrant_hostname(b)}'")
if env_defined
ENV['VAGRANT_CPU_CORE'] = old_env
else
ENV.delete('VAGRANT_CPU_CORE')
end
raise "Failed to boot #{i} with single CPU" unless r
end
end
end
namespace 'spec' do
desc 'Run serverspec tests on a VM'
task :all => @all_boxes.map { |i| "spec:#{i}" }
@all_boxes.each do |b|
desc "Run serverspec on #{b} box"
RSpec::Core::RakeTask.new("#{b}") do |t|
t.pattern = 'reallyenglish_spec/**/*_spec.rb'
ENV['HOST'] = vagrant_hostname(b)
end
end
end
namespace 'destroy' do
desc 'Destroy all VMs'
task :all => @all_boxes.map { |i| "destroy:#{i}" }
@all_boxes.each do |b|
desc "Destroy #{b} VM"
task b.to_sym do |_t|
r = system("vagrant destroy -f '#{vagrant_hostname(b)}'")
raise "Failed to destroy #{vagrant_hostname(b)}" unless r
end
end
end
namespace 'clean' do
desc 'Clean all VMs'
task :all => @all_boxes.map { |i| "clean:#{i}" }
@all_boxes.each do |b|
desc "Clean #{b}"
task b.to_sym do |_t|
r = system("rm -f #{vagrant_hostname(b)}.box")
raise "Failed to remove #{vagrant_hostname(b)}.box" unless r
end
end
end
namespace 'upload' do
# XXX this target is useful only for the default VAGRANTCLOUD_USERNAME
# vagrant_cloud gem assumes single user user case only, although
# vagrantcloud service provides ACLs per box, i.e. user `foo` cannot upload
# `bar/boxname`, which is NOT owned by user `foo`.
@all_boxes.each do |b|
desc "Upload #{vagrant_hostname(b)}.box to vagrant cloud"
task b.to_sym do |_t|
unless ENV["VAGRANTCLOUD_ACCESS_TOKEN"]
raise "environment variable VAGRANTCLOUD_ACCESS_TOKEN must be defined"
end
vagrantcloud_access_token = ENV["VAGRANTCLOUD_ACCESS_TOKEN"]
account = VagrantCloud::Account.new(vagrantcloud_user_name, vagrantcloud_access_token)
filename = "#{b}-virtualbox.box"
boxname = "ansible-#{b}"
raise "cannot find #{filename}" unless File.exist?(filename)
puts "Ensuring the `#{boxname}` box is created in vagrantcloud"
box = account.ensure_box(boxname)
puts "Ensuring the box has version `#{version_of(b)}`"
version = box.ensure_version(version_of(b))
puts "Ensuring the version `#{version_of(b)}` has virtualbox provider"
provider = version.ensure_provider('virtualbox', nil)
puts "Uploading `#{filename}` to vagrantcloud"
provider.upload_file(filename)
puts "Successfully uploaded"
end
end
end
desc "Destroy all VMs and clean all created boxes"
task :clean do
begin
system("vagrant destroy -f")
ensure
r = system("rm -f *.box")
raise "Failed to destroy VMs" unless r
end
end
end
def request_head(uri, &block)
uri = URI(uri)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
http.request_head(uri, &block)
end
def available?(response)
response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPRedirection)
end
def atlas_post_processor_config(slug, version, provider)
{
'type' => 'atlas',
'artifact' => slug,
'artifact_type' => 'vagrant.box',
'metadata' => {
'version' => version,
'provider' => provider
}
}
end