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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d3cf921c31e786054ae969f8e6c1a90353d29425
4
- data.tar.gz: dd9d3643c179ea74141cb2758b62274caff13d8b
3
+ metadata.gz: 4c609eabae7f16453cf3a38d0de4637acc199f84
4
+ data.tar.gz: 6406d3fe9102552f5ee59886f38cb55514245015
5
5
  SHA512:
6
- metadata.gz: 530ee97b09e4364cd13f05c09dbd68e8e0f2e55025a9e0473ae2e3aebccc45548f7f31400897385cc0f4299c8e71724e1ed193c19cd813d74af1cabeee1e2b06
7
- data.tar.gz: ff3bfd89ba139e6e3d0f43a3b5368e897d6e53d8cf4e57e3eb431f4b58591694dfa1c8d0279c9c4d5500fad6788e9f01af42af8ad43fedaed924fac0087ddd2e
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: 'REDUCED_REDUNDANCY', server_side_encryption: 'AES256', **common_opts)
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
- 'DEBIAN_FRONTEND=noninteractive dpkg-reconfigure resolvconf' # re-linkify resolvconf
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
@@ -1,3 +1,3 @@
1
1
  module Linecook
2
- VERSION = '0.7.35'
2
+ VERSION = '0.7.36'
3
3
  end
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.35
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