linecook-gem 0.6.10 → 0.7.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.
- checksums.yaml +4 -4
- data/lib/linecook-gem.rb +4 -6
- data/lib/linecook-gem/baker.rb +110 -0
- data/lib/linecook-gem/baker/docker.rb +114 -0
- data/lib/linecook-gem/cli.rb +63 -115
- data/lib/linecook-gem/config.rb +45 -0
- data/lib/linecook-gem/image.rb +77 -0
- data/lib/linecook-gem/image/crypt.rb +7 -40
- data/lib/linecook-gem/image/s3.rb +14 -14
- data/lib/linecook-gem/packager.rb +30 -0
- data/lib/linecook-gem/packager/packer.rb +249 -0
- data/lib/linecook-gem/packager/route53.rb +62 -0
- data/lib/linecook-gem/packager/squashfs.rb +51 -0
- data/lib/linecook-gem/util/downloader.rb +3 -42
- data/lib/linecook-gem/util/secrets.rb +47 -0
- data/lib/linecook-gem/version.rb +1 -1
- data/man/LINECOOK.1 +117 -86
- metadata +62 -110
- data/lib/linecook-gem/builder/build.rb +0 -44
- data/lib/linecook-gem/builder/darwin_backend.rb +0 -98
- data/lib/linecook-gem/builder/linux_backend.rb +0 -11
- data/lib/linecook-gem/builder/lxc.rb +0 -286
- data/lib/linecook-gem/builder/manager.rb +0 -79
- data/lib/linecook-gem/image/github.rb +0 -27
- data/lib/linecook-gem/image/manager.rb +0 -73
- data/lib/linecook-gem/packager/ebs.rb +0 -373
- data/lib/linecook-gem/packager/manager.rb +0 -23
- data/lib/linecook-gem/provisioner/chef-zero.rb +0 -149
- data/lib/linecook-gem/provisioner/manager.rb +0 -47
- data/lib/linecook-gem/provisioner/packer.rb +0 -82
- data/lib/linecook-gem/util/config.rb +0 -134
- data/lib/linecook-gem/util/executor.rb +0 -33
- data/lib/linecook-gem/util/ssh.rb +0 -190
@@ -1,373 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
require 'open-uri'
|
3
|
-
require 'timeout'
|
4
|
-
require 'tmpdir'
|
5
|
-
require 'securerandom'
|
6
|
-
|
7
|
-
require 'linecook-gem/util/ssh'
|
8
|
-
require 'linecook-gem/util/executor'
|
9
|
-
|
10
|
-
require 'aws-sdk'
|
11
|
-
|
12
|
-
module Linecook
|
13
|
-
# Installs a linecook image on a target device
|
14
|
-
module Packager
|
15
|
-
class EBS
|
16
|
-
include Executor
|
17
|
-
|
18
|
-
def initialize(hvm: true, size: 10, region: nil, copy_regions: [], account_ids: [])
|
19
|
-
@hvm = hvm
|
20
|
-
@size = size
|
21
|
-
@region = region
|
22
|
-
@copy_regions = copy_regions
|
23
|
-
@account_ids = account_ids
|
24
|
-
end
|
25
|
-
|
26
|
-
def package(image, type: nil, ami: nil)
|
27
|
-
@image = image
|
28
|
-
@source = File.basename(@image)
|
29
|
-
@name = "#{@source}-#{SecureRandom.hex(4)}"
|
30
|
-
@type = type
|
31
|
-
setup_image
|
32
|
-
prepare
|
33
|
-
execute("tar -C #{@mountpoint} -cpf - . | sudo tar -C #{@root} -xpf -")
|
34
|
-
finalize
|
35
|
-
snapshot
|
36
|
-
cleanup
|
37
|
-
create_ami if ami
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def prepare
|
43
|
-
@mountpoint = Dir.mktmpdir
|
44
|
-
execute("mkdir -p #{@mountpoint}")
|
45
|
-
execute("mount #{@image} #{@mountpoint}")
|
46
|
-
create_volume
|
47
|
-
format_and_mount
|
48
|
-
end
|
49
|
-
|
50
|
-
def finalize
|
51
|
-
execute("echo \"UUID=\\\"$(blkid -o value -s UUID #{@rootdev})\\\" / ext4 defaults 1 2\" > /tmp/fstab")
|
52
|
-
execute("mv /tmp/fstab #{@root}/etc/fstab")
|
53
|
-
chroot_exec('apt-get update')
|
54
|
-
chroot_exec('apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y --force-yes --no-upgrade install grub-pc grub-legacy-ec2')
|
55
|
-
chroot_exec('update-grub')
|
56
|
-
execute("grub-install --root-directory=#{@root} $(echo #{@rootdev} | sed \"s/[0-9]*//g\")") if @hvm
|
57
|
-
end
|
58
|
-
|
59
|
-
def cleanup
|
60
|
-
execute("umount #{@image}")
|
61
|
-
execute("rm -f #{@image}")
|
62
|
-
execute("rmdir #{@mountpoint}")
|
63
|
-
end
|
64
|
-
|
65
|
-
def chroot_exec(command)
|
66
|
-
execute("mount -o bind /dev #{@root}/dev")
|
67
|
-
execute("mount -o bind /sys #{@root}/sys")
|
68
|
-
execute("mount -t proc none #{@root}/proc")
|
69
|
-
execute("cp /etc/resolv.conf #{@root}/etc")
|
70
|
-
execute("chroot #{@root} #{command}")
|
71
|
-
execute("umount #{@root}/dev")
|
72
|
-
execute("umount #{@root}/sys")
|
73
|
-
execute("umount #{@root}/proc")
|
74
|
-
end
|
75
|
-
|
76
|
-
def partition
|
77
|
-
execute("parted -s #{@rootdev} mklabel msdos")
|
78
|
-
execute("parted -s #{@rootdev} mkpart primary ext2 0% 100%")
|
79
|
-
@rootdev = "#{@rootdev}1"
|
80
|
-
end
|
81
|
-
|
82
|
-
def format_and_mount
|
83
|
-
partition if @hvm
|
84
|
-
execute("mkfs.ext4 #{@rootdev}")
|
85
|
-
@root = Dir.mktmpdir
|
86
|
-
execute("mkdir -p #{@root}")
|
87
|
-
execute("mount #{@rootdev} #{@root}")
|
88
|
-
end
|
89
|
-
|
90
|
-
def instance_id
|
91
|
-
@instance_id ||= metadata('instance-id')
|
92
|
-
end
|
93
|
-
|
94
|
-
def availability_zone
|
95
|
-
@availability_zone ||= metadata('placement/availability-zone')
|
96
|
-
end
|
97
|
-
|
98
|
-
def client(region: nil)
|
99
|
-
@client = nil if region
|
100
|
-
@client ||= begin
|
101
|
-
region ||= @region
|
102
|
-
puts "Using AWS region #{region} for following request"
|
103
|
-
credentials = Aws::Credentials.new(Linecook.config[:aws][:access_key], Linecook.config[:aws][:secret_key])
|
104
|
-
Aws::EC2::Client.new(region: region, credentials: credentials)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def create_volume
|
109
|
-
resp = client.create_volume({
|
110
|
-
size: @size,
|
111
|
-
availability_zone: availability_zone, # required
|
112
|
-
volume_type: "standard", # accepts standard, io1, gp2
|
113
|
-
})
|
114
|
-
|
115
|
-
@volume_id = resp.volume_id
|
116
|
-
rootdev = free_device
|
117
|
-
|
118
|
-
puts "Waiting for volume to become available"
|
119
|
-
wait_for_state('available', 120) do
|
120
|
-
client.describe_volumes(volume_ids: [@volume_id]).volumes.first.state
|
121
|
-
end
|
122
|
-
|
123
|
-
resp = client.attach_volume({
|
124
|
-
volume_id: @volume_id,
|
125
|
-
instance_id: instance_id,
|
126
|
-
device: rootdev,
|
127
|
-
})
|
128
|
-
|
129
|
-
puts "Waiting for volume to attach"
|
130
|
-
wait_for_state('attached', 120) do
|
131
|
-
client.describe_volumes(volume_ids: [@volume_id]).volumes.first.attachments.first.state
|
132
|
-
end
|
133
|
-
@rootdev = "/dev/#{rootdev}"
|
134
|
-
end
|
135
|
-
|
136
|
-
def snapshot
|
137
|
-
execute("umount #{@root}")
|
138
|
-
puts 'Creating snapshot'
|
139
|
-
resp = client.detach_volume(volume_id: @volume_id)
|
140
|
-
wait_for_state('available', 120) do
|
141
|
-
client.describe_volumes(volume_ids: [@volume_id]).volumes.first.state
|
142
|
-
end
|
143
|
-
resp = client.create_snapshot(volume_id: @volume_id, description: "Snapshot of #{@name}")
|
144
|
-
@snapshot_id = resp.snapshot_id
|
145
|
-
tag(@snapshot_id, Name: "Linecook snapshot for #{@source}", type: @type, image: @name, hvm: @hvm.to_s)
|
146
|
-
client.delete_volume(volume_id: @volume_id)
|
147
|
-
end
|
148
|
-
|
149
|
-
def create_ami
|
150
|
-
|
151
|
-
puts "Waiting for snapshot #{@snapshot_id} to be completed"
|
152
|
-
wait_for_state('completed', 900) do
|
153
|
-
client.describe_snapshots(snapshot_ids: [@snapshot_id]).snapshots.first.state
|
154
|
-
end
|
155
|
-
|
156
|
-
puts "Registering an AMI with for #{@name}"
|
157
|
-
options = {
|
158
|
-
name: @name,
|
159
|
-
virtualization_type: @hvm ? 'hvm' : 'paravirtual',
|
160
|
-
architecture: 'x86_64', # fixme
|
161
|
-
root_device_name: '/dev/sda1', # fixme when does this need to be sda?
|
162
|
-
block_device_mappings: [{
|
163
|
-
device_name: '/dev/sda1',
|
164
|
-
ebs: {
|
165
|
-
snapshot_id: @snapshot_id,
|
166
|
-
volume_size: @size,
|
167
|
-
volume_type: @hvm ? 'gp2' : 'standard', # fixme: support iops?
|
168
|
-
delete_on_termination: true,
|
169
|
-
}
|
170
|
-
}]
|
171
|
-
}
|
172
|
-
options.merge!({sriov_net_support: 'simple'}) if @hvm
|
173
|
-
|
174
|
-
resp = client.register_image(**options)
|
175
|
-
@ami_id = resp.image_id
|
176
|
-
|
177
|
-
puts "Waiting for #{@ami_id} to become available"
|
178
|
-
|
179
|
-
wait_for_state('available', 300) do
|
180
|
-
client.describe_images(image_ids: [@ami_id]).images.first.state
|
181
|
-
end
|
182
|
-
|
183
|
-
amis = {
|
184
|
-
@region => @ami_id
|
185
|
-
}
|
186
|
-
|
187
|
-
@copy_regions.each do |region|
|
188
|
-
puts "Copying #{@ami_id} to #{region}"
|
189
|
-
resp = client(region: region).copy_image({
|
190
|
-
source_region: @region,
|
191
|
-
source_image_id: @ami_id,
|
192
|
-
name: @name,
|
193
|
-
description: "Copy of #{@name}",
|
194
|
-
})
|
195
|
-
ami = resp.image_id
|
196
|
-
puts "Waiting for #{ami} to become available in #{region}"
|
197
|
-
wait_for_state('available', 1800) do
|
198
|
-
client.describe_images(image_ids: [ami]).images.first.state
|
199
|
-
end
|
200
|
-
amis[region] = ami
|
201
|
-
end
|
202
|
-
|
203
|
-
unless @account_ids.empty?
|
204
|
-
amis.each do |region, ami|
|
205
|
-
puts "Updating account permissions for #{ami} in #{region}"
|
206
|
-
client(region: region).modify_image_attribute({
|
207
|
-
operation_type: 'add',
|
208
|
-
attribute: 'launchPermission',
|
209
|
-
image_id: ami,
|
210
|
-
user_ids: @account_ids
|
211
|
-
})
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
amis.each do |region, ami|
|
216
|
-
tag(ami, region: region, source: @source, name: @name, type: @type, hvm: @hvm.to_s)
|
217
|
-
end
|
218
|
-
amis
|
219
|
-
end
|
220
|
-
|
221
|
-
def free_device
|
222
|
-
prefix = device_prefix
|
223
|
-
('f'..'zzz').to_a.each do |suffix|
|
224
|
-
device = "#{prefix}#{suffix}"
|
225
|
-
if free_device?(device)
|
226
|
-
lock_device(device)
|
227
|
-
return device
|
228
|
-
end
|
229
|
-
end
|
230
|
-
return nil
|
231
|
-
end
|
232
|
-
|
233
|
-
def free_device?(device)
|
234
|
-
test("[ ! -e /dev/#{device} ]") && test("[ ! -e /run/lock/linecook-#{device} ]")
|
235
|
-
end
|
236
|
-
|
237
|
-
def lock_device(device)
|
238
|
-
execute("echo #{Process.pid} > /run/lock/linecook-#{device}")
|
239
|
-
end
|
240
|
-
|
241
|
-
def unlock_device(device)
|
242
|
-
execute("rm /run/lock/linecook-#{device}")
|
243
|
-
end
|
244
|
-
|
245
|
-
def device_prefix
|
246
|
-
prefixes = ['xvd', 'sd']
|
247
|
-
capture('ls -1 /sys/block').lines.each do |dev|
|
248
|
-
prefixes.each do |prefix|
|
249
|
-
return prefix if dev =~ /^#{prefix}/
|
250
|
-
end
|
251
|
-
end
|
252
|
-
return prefixes.first
|
253
|
-
end
|
254
|
-
|
255
|
-
def setup_image
|
256
|
-
path = "/tmp/#{File.basename(@image)}"
|
257
|
-
if instance_id
|
258
|
-
return if File.exists?(@image)
|
259
|
-
Linecook::Downloader.download(image_url, path, encrypted: true)
|
260
|
-
@image = path
|
261
|
-
else
|
262
|
-
start_node
|
263
|
-
@remote.run("wget '#{image_url}' -nv -O #{path}")
|
264
|
-
@image = Linecook::Crypto.new(remote: @remote).decrypt_file(path)
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
def image_url
|
269
|
-
@url ||= Linecook::ImageManager.url(File.basename(@image), type: @type)
|
270
|
-
end
|
271
|
-
|
272
|
-
def start_node
|
273
|
-
resp = client.run_instances(
|
274
|
-
image_id: find_ami,
|
275
|
-
min_count: 1,
|
276
|
-
max_count: 1,
|
277
|
-
instance_type: 'c4.large',
|
278
|
-
instance_initiated_shutdown_behavior: 'terminate',
|
279
|
-
security_groups: [security_group],
|
280
|
-
key_name: key_pair
|
281
|
-
)
|
282
|
-
@instance_id = resp.instances.first.instance_id
|
283
|
-
@availability_zone = resp.instances.first.placement.availability_zone
|
284
|
-
|
285
|
-
puts 'Waiting for temporary instance to come online'
|
286
|
-
wait_for_state('running', 300) do
|
287
|
-
client.describe_instances(instance_ids: [@instance_id]).reservations.first.instances.first.state.name
|
288
|
-
end
|
289
|
-
tag(@instance_id, Name: 'linecook-temporary-installer-node')
|
290
|
-
@remote = Linecook::SSH.new(instance_ip, username: 'ubuntu', keyfile: Linecook::SSH.private_key)
|
291
|
-
@remote.upload("exec shutdown -h 60 'Delayed shutdown started'", '/tmp/delay-shutdown')
|
292
|
-
execute('mv /tmp/delay-shutdown /etc/init/delay-shutdown.conf') # ubuntism is ok, since the temporary host can always be ubuntu
|
293
|
-
execute('start delay-shutdown')
|
294
|
-
# Install crypto deps
|
295
|
-
execute('apt-get install -y --force-yes build-essential ruby ruby-dev')
|
296
|
-
execute('gem install rbnacl rbnacl-libsodium')
|
297
|
-
end
|
298
|
-
|
299
|
-
def find_ami
|
300
|
-
url = "http://uec-images.ubuntu.com/query/trusty/server/released.current.txt"
|
301
|
-
type = @hvm ? 'hvm' : 'paravirtual'
|
302
|
-
data = open(url).read.split("\n").map{|l| l.split}.detect do |ary|
|
303
|
-
ary[4] == 'ebs' &&
|
304
|
-
ary[5] == 'amd64' &&
|
305
|
-
ary[6] == @region &&
|
306
|
-
ary.last == type
|
307
|
-
end
|
308
|
-
data[7]
|
309
|
-
end
|
310
|
-
|
311
|
-
def instance_ip
|
312
|
-
client.describe_instances(instance_ids: [@instance_id]).reservations.first.instances.first.public_ip_address
|
313
|
-
end
|
314
|
-
|
315
|
-
def security_group
|
316
|
-
group_name = 'linecook-global-ssh'
|
317
|
-
resp = client.describe_security_groups(filters: [{name: 'group-name', values: [group_name]}])
|
318
|
-
if resp.security_groups.length < 1
|
319
|
-
resp = client.create_security_group({
|
320
|
-
group_name: group_name,
|
321
|
-
description: "Allow global ssh for linecook temporary builder instances",
|
322
|
-
})
|
323
|
-
|
324
|
-
resp = client.authorize_security_group_ingress({
|
325
|
-
group_name: group_name,
|
326
|
-
ip_protocol: "tcp",
|
327
|
-
from_port: 22,
|
328
|
-
to_port: 22,
|
329
|
-
cidr_ip: "0.0.0.0/0",
|
330
|
-
})
|
331
|
-
end
|
332
|
-
group_name
|
333
|
-
end
|
334
|
-
|
335
|
-
def tag(id, **kwargs)
|
336
|
-
puts "Will tag #{id} with #{kwargs}"
|
337
|
-
resp = client(region: kwargs[:region]).create_tags(resources: [id], tags: kwargs.map{ |k,v| {key: k.to_s, value: v.to_s } })
|
338
|
-
end
|
339
|
-
|
340
|
-
def key_pair
|
341
|
-
pubkey = Linecook::SSH.public_key
|
342
|
-
resp = client.describe_key_pairs({
|
343
|
-
filters: [ { name: 'fingerprint', values: [Linecook::SSH.sshv2_fingerprint(pubkey)] } ]
|
344
|
-
})
|
345
|
-
|
346
|
-
if resp.key_pairs.length >= 1
|
347
|
-
return resp.key_pairs.first.key_name
|
348
|
-
else
|
349
|
-
keyname = "linecook-#{SecureRandom.uuid}"
|
350
|
-
resp = client.import_key_pair({
|
351
|
-
key_name: keyname,
|
352
|
-
public_key_material: pubkey,
|
353
|
-
})
|
354
|
-
return keyname
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
def metadata(key)
|
359
|
-
(Timeout::timeout(1) { Net::HTTP.get(URI(File.join("http://169.254.169.254/latest/meta-data", key))) } rescue nil)
|
360
|
-
end
|
361
|
-
|
362
|
-
def wait_for_state(desired, timeout)
|
363
|
-
attempts = 0
|
364
|
-
state = nil
|
365
|
-
while attempts < timeout && state != desired
|
366
|
-
state = yield
|
367
|
-
attempts += 1
|
368
|
-
sleep(1)
|
369
|
-
end
|
370
|
-
end
|
371
|
-
end
|
372
|
-
end
|
373
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'linecook-gem/packager/ebs'
|
2
|
-
|
3
|
-
module Linecook
|
4
|
-
module Packager
|
5
|
-
extend self
|
6
|
-
|
7
|
-
def package(image, type: type, **args)
|
8
|
-
provider.package(image, type: type, **args)
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
def provider
|
13
|
-
name = Linecook.config[:packager][:provider]
|
14
|
-
config = Linecook.config[:packager][name]
|
15
|
-
case name
|
16
|
-
when :ebs
|
17
|
-
Linecook::Packager::EBS.new(**config)
|
18
|
-
else
|
19
|
-
fail "No packager implemented for for #{name}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,149 +0,0 @@
|
|
1
|
-
require 'tmpdir'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
require 'chef-provisioner'
|
5
|
-
require 'chefdepartie'
|
6
|
-
|
7
|
-
module Linecook
|
8
|
-
module Chef
|
9
|
-
extend self
|
10
|
-
|
11
|
-
def provision(build, role)
|
12
|
-
chef_config = setup
|
13
|
-
role_config = Linecook.config[:roles][role.to_sym]
|
14
|
-
script = ChefProvisioner::Bootstrap.generate(
|
15
|
-
profile: role_config[:profile] || false,
|
16
|
-
node_name: chef_config[:node_name],
|
17
|
-
chef_version: chef_config[:version] || nil,
|
18
|
-
first_boot: {
|
19
|
-
run_list: role_config[:run_list]
|
20
|
-
},
|
21
|
-
audit: Linecook.config[:provisioner][:chefzero][:audit]
|
22
|
-
)
|
23
|
-
|
24
|
-
puts "Establishing connection to build..."
|
25
|
-
build.start
|
26
|
-
build.ssh.forward(chef_port)
|
27
|
-
build.ssh.upload(script, '/tmp/chef_bootstrap')
|
28
|
-
build.ssh.run('[ -f /var/chef/cache/chef-client-running.pid ] && sudo rm -f /var/chef/cache/chef-client-running.pid || true')
|
29
|
-
build.ssh.run("sudo hostname #{chef_config[:node_name]}")
|
30
|
-
build.ssh.run('sudo bash /tmp/chef_bootstrap')
|
31
|
-
build.ssh.run('sudo rm -rf /etc/chef')
|
32
|
-
build.ssh.stop_forwarding
|
33
|
-
Chefdepartie.stop
|
34
|
-
FileUtils.rm_rf(Cache.path)
|
35
|
-
end
|
36
|
-
|
37
|
-
def chef_port
|
38
|
-
ChefProvisioner::Config.server.split(':')[-1].to_i
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def setup
|
44
|
-
ChefProvisioner::Config.setup(client: 'linecook', listen: 'localhost')
|
45
|
-
config = Linecook.config
|
46
|
-
|
47
|
-
chef_config = config[:chef]
|
48
|
-
chef_config.merge!(node_name: "linecook-#{SecureRandom.hex(4)}",
|
49
|
-
chef_server_url: ChefProvisioner::Config.server)
|
50
|
-
Chefdepartie.run(background: true, config: chef_config, cache: Cache.path)
|
51
|
-
chef_config
|
52
|
-
end
|
53
|
-
|
54
|
-
# Required in order to have multiple builds run on different refs
|
55
|
-
module Cache
|
56
|
-
CACHE_PATH = File.join(Linecook::Config::LINECOOK_HOME, 'chefcache').freeze
|
57
|
-
PIDFILE = File.join(CACHE_PATH, 'pid')
|
58
|
-
STAMPFILE = File.join(CACHE_PATH, 'stamp')
|
59
|
-
STALE_THRESHOLD = 86400 # one day in seconds
|
60
|
-
WAIT_TIMEOUT = 60 # time to wait for port to become available again
|
61
|
-
|
62
|
-
extend self
|
63
|
-
|
64
|
-
def path
|
65
|
-
@cache_path ||= begin
|
66
|
-
FileUtils.mkdir_p(CACHE_PATH)
|
67
|
-
cache_path = Dir.mktmpdir('linecook-chef-cache')
|
68
|
-
build
|
69
|
-
copy(cache_path)
|
70
|
-
wait_for_close
|
71
|
-
cache_path
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
private
|
76
|
-
|
77
|
-
def wait_for_close
|
78
|
-
attempts = 0
|
79
|
-
while attempts < WAIT_TIMEOUT
|
80
|
-
begin
|
81
|
-
Timeout::timeout(1) do
|
82
|
-
begin
|
83
|
-
s = TCPSocket.new('127.0.0.1', Linecook::Chef.chef_port)
|
84
|
-
s.close
|
85
|
-
return true
|
86
|
-
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
87
|
-
return false
|
88
|
-
end
|
89
|
-
end
|
90
|
-
rescue Timeout::Error
|
91
|
-
puts "Port #{Linecook::Chef.chef_port} is still in use"
|
92
|
-
sleep(1)
|
93
|
-
end
|
94
|
-
attempts += 0
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def copy(cache_path)
|
99
|
-
FileUtils.copy_entry(CACHE_PATH, cache_path, preserve: true)
|
100
|
-
end
|
101
|
-
|
102
|
-
def build
|
103
|
-
if stale
|
104
|
-
puts 'Regenerating cookbook cache'
|
105
|
-
begin
|
106
|
-
Chefdepartie.run(background: true, config: Linecook.config[:chef], cache: CACHE_PATH)
|
107
|
-
rescue => e
|
108
|
-
puts e.message
|
109
|
-
puts 'Cache tainted, rebuilding completely'
|
110
|
-
Chefdepartie.stop
|
111
|
-
FileUtils.rm_rf(CACHE_PATH)
|
112
|
-
Chefdepartie.run(background: true, config: Linecook.config[:chef], cache: CACHE_PATH)
|
113
|
-
ensure
|
114
|
-
Chefdepartie.stop
|
115
|
-
end
|
116
|
-
write_stamp
|
117
|
-
unlock
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def stale
|
122
|
-
return false if locked?
|
123
|
-
lock
|
124
|
-
old?
|
125
|
-
end
|
126
|
-
|
127
|
-
def locked?
|
128
|
-
File.exists?(PIDFILE) && (true if Process.kill(0, File.read(PIDFILE)) rescue false)
|
129
|
-
end
|
130
|
-
|
131
|
-
def lock
|
132
|
-
File.write(PIDFILE, Process.pid)
|
133
|
-
end
|
134
|
-
|
135
|
-
def unlock
|
136
|
-
FileUtils.rm_f(PIDFILE)
|
137
|
-
end
|
138
|
-
|
139
|
-
def old?
|
140
|
-
return true unless File.exists?(STAMPFILE)
|
141
|
-
(Time.now.to_i - File.read(STAMPFILE).to_i) > STALE_THRESHOLD
|
142
|
-
end
|
143
|
-
|
144
|
-
def write_stamp
|
145
|
-
File.write(STAMPFILE, Time.now.to_i)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|