linecook-gem 0.7.35 → 0.7.36
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/image/s3.rb +1 -1
- data/lib/linecook-gem/packager/packer.rb +4 -1
- data/lib/linecook-gem/packager/packer/ami.rb +89 -0
- data/lib/linecook-gem/packager/packer/base.rb +126 -0
- data/lib/linecook-gem/packager/packer/gcp.rb +118 -0
- data/lib/linecook-gem/version.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c609eabae7f16453cf3a38d0de4637acc199f84
|
4
|
+
data.tar.gz: 6406d3fe9102552f5ee59886f38cb55514245015
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3f8e661860c24c3933737251b06c2477646f184ca2d78af8b84acb2d208de4845793a8587875d7be5ef3172c37d03ed45d9ab0552d1dd535a05cce6b5ae1f5f
|
7
|
+
data.tar.gz: 6e1584143c306beb4d32f211080fd08d2ae70301f72e39087b6249d29d9220322b07806513695d7350933d72f93543f22b2eb561da25b2a095b3a9c8eb649d71
|
@@ -39,7 +39,7 @@ module Linecook
|
|
39
39
|
fid = File.basename(path)
|
40
40
|
pbar = ProgressBar.create(title: fid, total: file.size)
|
41
41
|
common_opts = { bucket: Linecook.config[:aws][:s3][:bucket], key: File.join([PREFIX, group, fid].compact) }
|
42
|
-
resp = client.create_multipart_upload(storage_class: '
|
42
|
+
resp = client.create_multipart_upload(storage_class: 'STANDARD', server_side_encryption: 'AES256', **common_opts)
|
43
43
|
id = resp.upload_id
|
44
44
|
part = 0
|
45
45
|
total = 0
|
@@ -61,7 +61,10 @@ module Linecook
|
|
61
61
|
'update-grub',
|
62
62
|
'rm -f /etc/init/fake-container-events.conf', # HACK
|
63
63
|
'mkdir -p /run/resolvconf/interface',
|
64
|
-
'
|
64
|
+
'echo "resolvconf resolvconf/linkify-resolvconf boolean true" | debconf-set-selections', # write debconf
|
65
|
+
'dpkg-reconfigure -f noninteractive resolvconf', # re-linkify resolvconf
|
66
|
+
'truncate --size 0 /etc/resolv.conf', # clear build resolvconf config
|
67
|
+
'truncate --size 0 /etc/resolvconf/resolv.conf.d/original' # clear build resolvconf config
|
65
68
|
]
|
66
69
|
|
67
70
|
def initialize(config)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'linecook-gem/packager/packer/base'
|
2
|
+
require 'linecook-gem/packager/route53'
|
3
|
+
|
4
|
+
module Linecook
|
5
|
+
class AmiPacker < Linecook::Packer
|
6
|
+
|
7
|
+
ROOT_DEVICE_MAP = {
|
8
|
+
device_name: 'xvda',
|
9
|
+
delete_on_termination: true
|
10
|
+
}
|
11
|
+
|
12
|
+
BUILDER_CONFIG = {
|
13
|
+
type: 'amazon-chroot',
|
14
|
+
access_key: '{{ user `aws_access_key` }}',
|
15
|
+
secret_key: '{{ user `aws_secret_key` }}',
|
16
|
+
ami_name: 'packer-image.{{ user `image_name` }} {{timestamp}}',
|
17
|
+
from_scratch: true,
|
18
|
+
root_device_name: ROOT_DEVICE_MAP[:device_name],
|
19
|
+
ami_block_device_mappings: [ ROOT_DEVICE_MAP ],
|
20
|
+
pre_mount_commands: PRE_MOUNT_COMMANDS,
|
21
|
+
post_mount_commands: POST_MOUNT_COMMANDS,
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
|
25
|
+
def initialize(config)
|
26
|
+
system("#{packer_path} --version")
|
27
|
+
@hvm = config[:hvm] || true
|
28
|
+
@root_size = config[:root_size] || 10
|
29
|
+
@region = config[:region] || 'us-east-1'
|
30
|
+
@copy_regions = config[:copy_regions] || []
|
31
|
+
@accounts = config[:account_ids] || []
|
32
|
+
@write_txt = Linecook.config[:packager] && Linecook.config[:packager][:ami] && Linecook.config[:packager][:ami][:update_txt]
|
33
|
+
end
|
34
|
+
|
35
|
+
def package(image, directory)
|
36
|
+
super(image, directory)
|
37
|
+
extract_amis_from_output
|
38
|
+
end
|
39
|
+
private
|
40
|
+
|
41
|
+
# TO DO:
|
42
|
+
# support for multiple accounts, multiple regions
|
43
|
+
# code to extract ami name(s) from output
|
44
|
+
# amis = `grep "amazon-ebs,artifact,0,id" packer.log`.chomp.split(',')[5].split('%!(PACKER_COMMA)')
|
45
|
+
# route53 TXT record integration
|
46
|
+
|
47
|
+
def generate_config(packager)
|
48
|
+
packager ||= {}
|
49
|
+
config = {
|
50
|
+
variables: {
|
51
|
+
aws_access_key: Linecook.config[:aws][:access_key],
|
52
|
+
aws_secret_key: Linecook.config[:aws][:secret_key],
|
53
|
+
image_name: "linecook-#{@image.id}",
|
54
|
+
source_image_path: @image.path
|
55
|
+
},
|
56
|
+
builders: [
|
57
|
+
BUILDER_CONFIG.merge(
|
58
|
+
ami_users: @accounts,
|
59
|
+
ami_regions: @copy_regions,
|
60
|
+
ami_virtualization_type: virt_type,
|
61
|
+
root_volume_size: @root_size
|
62
|
+
).deep_merge(packager[:builder] || {})
|
63
|
+
],
|
64
|
+
provisioners: build_provisioner(CHROOT_COMMANDS)
|
65
|
+
}
|
66
|
+
|
67
|
+
unless config[:builders].first[:ami_block_device_mappings].find { |x| x[:device_name] == ROOT_DEVICE_MAP[:device_name] }
|
68
|
+
config[:builders].first[:ami_block_device_mappings].prepend ROOT_DEVICE_MAP
|
69
|
+
end
|
70
|
+
JSON.pretty_generate(config)
|
71
|
+
end
|
72
|
+
|
73
|
+
def extract_amis_from_output
|
74
|
+
amis = @output.grep(/amazon-chroot,artifact,0,id/).first.chomp.split(',')[5].split('%!(PACKER_COMMA)')
|
75
|
+
amis.each do |info_str|
|
76
|
+
ami_info = info_str.split(':')
|
77
|
+
ami_region = ami_info[0]
|
78
|
+
ami_id = ami_info[1]
|
79
|
+
puts "Built #{ami_id} for #{ami_region}"
|
80
|
+
Linecook::Route53.upsert_record(@image.name, ami_id, ami_region) if @write_txt
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def virt_type
|
85
|
+
@hvm ? 'hvm' : 'paravirtual'
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'mkmf'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'tempfile'
|
6
|
+
require 'tmpdir'
|
7
|
+
require 'pty'
|
8
|
+
|
9
|
+
require 'linecook-gem/image'
|
10
|
+
require 'linecook-gem/util/downloader'
|
11
|
+
require 'linecook-gem/util/locking'
|
12
|
+
require 'linecook-gem/util/common'
|
13
|
+
|
14
|
+
module Linecook
|
15
|
+
class Packer
|
16
|
+
|
17
|
+
include Downloader
|
18
|
+
include Locking
|
19
|
+
|
20
|
+
SOURCE_URL = 'https://releases.hashicorp.com/packer/'
|
21
|
+
PACKER_VERSION = '0.12.0'
|
22
|
+
PACKER_PATH = File.join(Linecook::Config::LINECOOK_HOME, 'bin', 'packer')
|
23
|
+
|
24
|
+
PRE_MOUNT_COMMANDS = [
|
25
|
+
'parted -s {{.Device}} mklabel msdos',
|
26
|
+
'parted -s {{.Device}} mkpart primary ext2 0% 100%',
|
27
|
+
'mkfs.ext4 {{.Device}}1',
|
28
|
+
'tune2fs -L cloudimg-rootfs {{.Device}}1',
|
29
|
+
]
|
30
|
+
|
31
|
+
POST_MOUNT_COMMANDS = [
|
32
|
+
'tar -C {{.MountPath}} -xpf {{ user `source_image_path` }}',
|
33
|
+
'cp /etc/resolv.conf {{.MountPath}}/etc',
|
34
|
+
'echo "LABEL=cloudimg-rootfs / ext4 defaults,discard 0 0" > {{.MountPath}}/etc/fstab',
|
35
|
+
'grub-install --root-directory={{.MountPath}} {{.Device}}',
|
36
|
+
'rm -rf {{.MountPath}}/etc/network',
|
37
|
+
'cp -r /etc/network {{.MountPath}}/etc/',
|
38
|
+
]
|
39
|
+
|
40
|
+
CHROOT_COMMANDS = [
|
41
|
+
'apt-get update',
|
42
|
+
'DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y --force-yes --no-upgrade install grub-pc grub-legacy-ec2', # FIXME - ec2 specific
|
43
|
+
'update-grub',
|
44
|
+
'rm -f /etc/init/fake-container-events.conf', # HACK
|
45
|
+
'mkdir -p /run/resolvconf/interface',
|
46
|
+
'DEBIAN_FRONTEND=noninteractive dpkg-reconfigure resolvconf' # re-linkify resolvconf
|
47
|
+
]
|
48
|
+
|
49
|
+
def initialize
|
50
|
+
raise 'Not implemented'
|
51
|
+
end
|
52
|
+
|
53
|
+
def package(image, directory)
|
54
|
+
@image = image
|
55
|
+
kitchen_config = load_config(directory).send(:data).instance_variable_get(:@data)
|
56
|
+
image_config = kitchen_config[:suites].find{ |x| x[:name] == image.name }
|
57
|
+
if image_config && image_config[:packager]
|
58
|
+
packager = image_config[:packager] || {}
|
59
|
+
end
|
60
|
+
conf_file = Tempfile.new("#{@image.id}-packer.json")
|
61
|
+
config = generate_config(packager)
|
62
|
+
conf_file.write(config)
|
63
|
+
conf_file.close
|
64
|
+
@output = []
|
65
|
+
PTY.spawn("sudo #{PACKER_PATH} build -machine-readable #{conf_file.path}") do |stdout, _, _|
|
66
|
+
begin
|
67
|
+
stdout.each do |line|
|
68
|
+
@output << line if line =~ /artifact/
|
69
|
+
tokens = line.split(',')
|
70
|
+
if tokens.length > 4
|
71
|
+
out = tokens[4].gsub('%!(PACKER_COMMA)', ',')
|
72
|
+
time = DateTime.strptime(tokens[0], '%s').strftime('%c')
|
73
|
+
puts "#{time} | #{out}"
|
74
|
+
else
|
75
|
+
puts "unexpected output format"
|
76
|
+
puts tokens
|
77
|
+
end
|
78
|
+
end
|
79
|
+
rescue Errno::EIO
|
80
|
+
puts "Packer finshed executing"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
ensure
|
84
|
+
conf_file.close
|
85
|
+
conf_file.unlink
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def generate_config(packager)
|
91
|
+
raise 'Not implemented'
|
92
|
+
end
|
93
|
+
|
94
|
+
def build_provisioner(chroot_commands)
|
95
|
+
provisioner = [
|
96
|
+
{
|
97
|
+
type: 'shell',
|
98
|
+
inline: chroot_commands
|
99
|
+
}
|
100
|
+
]
|
101
|
+
end
|
102
|
+
|
103
|
+
def packer_path
|
104
|
+
@path ||= begin
|
105
|
+
found = File.exists?(PACKER_PATH) ? PACKER_PATH : find_executable('packer')
|
106
|
+
path = if found
|
107
|
+
version = `#{found} --version`
|
108
|
+
Gem::Version.new(version) >= Gem::Version.new(PACKER_VERSION) ? found : nil
|
109
|
+
end
|
110
|
+
path ||= get_packer
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def get_packer
|
115
|
+
puts "packer too old (<#{PACKER_VERSION}) or not present, getting latest packer"
|
116
|
+
arch = 1.size == 8 ? 'amd64' : '386'
|
117
|
+
|
118
|
+
FileUtils.rm_f(Dir[File.join(File.dirname(PACKER_PATH), "*")])
|
119
|
+
path = File.join(File.dirname(PACKER_PATH), 'packer.zip')
|
120
|
+
url = File.join(SOURCE_URL, PACKER_VERSION, "packer_#{PACKER_VERSION}_linux_#{arch}.zip")
|
121
|
+
download(url, path)
|
122
|
+
unzip(path)
|
123
|
+
PACKER_PATH
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'fog/google'
|
2
|
+
|
3
|
+
require 'linecook-gem/packager/packer/base'
|
4
|
+
|
5
|
+
module Linecook
|
6
|
+
class GCPPacker < Linecook::Packer
|
7
|
+
|
8
|
+
BUILDER_CONFIG = {
|
9
|
+
type: 'null',
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
# run with 'shell-local'
|
13
|
+
PRE_MOUNT_COMMANDS = [
|
14
|
+
|
15
|
+
# create a sparse image with dd
|
16
|
+
"dd if=/dev/zero of=#{image_path} bs=1 count=0 seek=#{image_size}",
|
17
|
+
"parted -s $(losetup | grep #{image_path} | awk '{print $1}') mklabel msdos",
|
18
|
+
"parted -s $(losetup | grep #{image_path} | awk '{print $1}') mkpart primary ext4 0% 100%",
|
19
|
+
"mkfs.ext4 $(losetup | grep #{image_path} | awk '{print $1}')p1",
|
20
|
+
"tune2fs -L cloudimg-rootfs $(losetup | grep #{image_path} | awk '{print $1}')p1",
|
21
|
+
"mount $(losetup | grep #{image_path} | awk '{print $1}')p1 /mnt/#{build_uuid}"
|
22
|
+
]
|
23
|
+
|
24
|
+
CHROOT_SETUP = [
|
25
|
+
# tar -C "${MOUNT_PATH}" -xpf "${TAR_PATH}"
|
26
|
+
#
|
27
|
+
#mount --bind /dev "${MOUNT_PATH}"/dev
|
28
|
+
#mount --bind /proc "${MOUNT_PATH}"/proc
|
29
|
+
#mount --bind /sys "${MOUNT_PATH}"/sys
|
30
|
+
#
|
31
|
+
#echo "LABEL=cloudimg-rootfs / ext4 defaults,discard 0 0" >> "${MOUNT_PATH}"/etc/fstab
|
32
|
+
]
|
33
|
+
|
34
|
+
CHROOT_COMMNANDS_EXTRA = [
|
35
|
+
#APT_PACKAGES=(
|
36
|
+
# grub-pc
|
37
|
+
# cloud-init
|
38
|
+
# cloud-initramfs-growroot
|
39
|
+
# gce-daemon
|
40
|
+
# gce-startup-scripts
|
41
|
+
# gce-image-bundle
|
42
|
+
# gce-cloud-config
|
43
|
+
#)
|
44
|
+
#
|
45
|
+
#DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confdef" \
|
46
|
+
# -o Dpkg::Options::="--force-confold" -y --force-yes --no-upgrade install "${APT_PACKAGES}"
|
47
|
+
#
|
48
|
+
#rm -f /etc/hostname
|
49
|
+
#ln -s /usr/share/google/set-hostname /etc/dhcp/dhclient-exit-hooks.d/
|
50
|
+
#
|
51
|
+
#echo "169.254.169.254 metadata.google.internal metadata" >> /etc/hosts
|
52
|
+
#echo "127.0.0.1 localhost" >> /etc/hosts
|
53
|
+
]
|
54
|
+
|
55
|
+
CHROOT_UNMOUNT = [
|
56
|
+
"umount /mnt/#{build_uuid}/dev",
|
57
|
+
"umount /mnt/#{build_uuid}/sys",
|
58
|
+
"umount /mnt/#{build_uuid}/proc",
|
59
|
+
"umount /mnt/#{build_uuid}"
|
60
|
+
]
|
61
|
+
|
62
|
+
COMPRESS_IMAGE = [
|
63
|
+
"losetup -d $(losetup | grep #{image_path} | awk '{print $1}')",
|
64
|
+
"mkdir -p /tmp/#{build_uuid}",
|
65
|
+
"mv #{image_path} /tmp/#{build_uuid}/disk.raw", #must be called disk.raw
|
66
|
+
"cd /tmp/#{build_uuid} && tar -czvf #{build_uuid}.tar.gz disk.raw",
|
67
|
+
"rm /tmp#{build_uuid}/disk.raw"
|
68
|
+
]
|
69
|
+
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def upload
|
74
|
+
connection = Fog::Storage::Google.new
|
75
|
+
|
76
|
+
image_source = File.open("/tmp/#{build_uuid}/#{build_uuid}.tar.gz")
|
77
|
+
connection.put_object("bucket", "#{image_name}-#{build_uuid}.tar.gz", image_source)
|
78
|
+
image_source.close
|
79
|
+
image_source.unlink
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_gcp_image
|
84
|
+
connection = Fog::Compute.new(:provider => "Google")
|
85
|
+
|
86
|
+
rawdisk = {
|
87
|
+
source: "gs://#{bucket}/#{image_slug}",
|
88
|
+
container_type: "TAR"
|
89
|
+
}
|
90
|
+
|
91
|
+
|
92
|
+
img = connection.images.create(name: "test-image", # FIXME - from config
|
93
|
+
description: "Test image (via fog)", # FIXME - from config
|
94
|
+
raw_disk: rawdisk)
|
95
|
+
|
96
|
+
img.reload # will raise if image was not saved correctly
|
97
|
+
end
|
98
|
+
|
99
|
+
# run with 'shell-local' and "execute_command"
|
100
|
+
# https://www.packer.io/docs/provisioners/shell-local.html
|
101
|
+
# to wrap everything with chroot
|
102
|
+
|
103
|
+
# Rather than use the 'googlecloud' provider in packer, which would require us to spin up a VM
|
104
|
+
# We post-process the image locally, and upload it to google cloud. Google is able to deal with tarballs
|
105
|
+
# directly, so there's no need for a fancy chroot builder.
|
106
|
+
#
|
107
|
+
# Gist of how it works:
|
108
|
+
# 1. Use a null builder to post-process a linecook image into an acceptable format for google
|
109
|
+
# 2. Snapshot that image as a tarball
|
110
|
+
# 3. Upload that image to google storage
|
111
|
+
# 4. Create a google compute image from the tarball URL. https://cloud.google.com/compute/docs/images/import-existing-image
|
112
|
+
|
113
|
+
|
114
|
+
# https://github.com/Shopify/google-cloud-images/blob/master/deps/chroot-commands.sh
|
115
|
+
# https://github.com/Shopify/google-cloud-images/blob/master/deps/generate-image.sh
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
data/lib/linecook-gem/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: linecook-gem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.36
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dale Hamel
|
@@ -283,6 +283,9 @@ files:
|
|
283
283
|
- lib/linecook-gem/image/s3.rb
|
284
284
|
- lib/linecook-gem/packager.rb
|
285
285
|
- lib/linecook-gem/packager/packer.rb
|
286
|
+
- lib/linecook-gem/packager/packer/ami.rb
|
287
|
+
- lib/linecook-gem/packager/packer/base.rb
|
288
|
+
- lib/linecook-gem/packager/packer/gcp.rb
|
286
289
|
- lib/linecook-gem/packager/route53.rb
|
287
290
|
- lib/linecook-gem/packager/squashfs.rb
|
288
291
|
- lib/linecook-gem/util/common.rb
|