Class: Linecook::AmiPacker

Inherits:
Object
  • Object
show all
Includes:
Downloader, Locking
Defined in:
lib/linecook-gem/packager/packer.rb

Constant Summary collapse

SOURCE_URL =
'https://releases.hashicorp.com/packer/'
PACKER_VERSION =
'0.12.0'
PACKER_PATH =
File.join(Linecook::Config::LINECOOK_HOME, 'bin', 'packer')
PRE_MOUNT_COMMANDS =
[
  'parted -s {{.Device}} mklabel msdos',
  'parted -s {{.Device}} mkpart primary ext2 0% 100%',
  'mkfs.ext4 {{.Device}}1',
  'tune2fs -L cloudimg-rootfs {{.Device}}1',
]
POST_MOUNT_COMMANDS =
[
  'tar -C {{.MountPath}} -xpf {{ user `source_image_path` }}',
  'cp /etc/resolv.conf {{.MountPath}}/etc',
  'echo "LABEL=cloudimg-rootfs   /        ext4   defaults,discard        0 0" > {{.MountPath}}/etc/fstab',
  'grub-install --root-directory={{.MountPath}} {{.Device}}',
  'rm -rf {{.MountPath}}/etc/network',
  'cp -r /etc/network {{.MountPath}}/etc/',
]
ROOT_DEVICE_MAP =
{
  device_name: 'xvda',
  delete_on_termination: true
}
BUILDER_CONFIG =
{
  type: 'amazon-chroot',
  access_key: '{{ user `aws_access_key` }}',
  secret_key: '{{ user `aws_secret_key` }}',
  ami_name: 'packer-image.{{ user `image_name` }} {{timestamp}}',
  from_scratch: true,
  root_device_name: ROOT_DEVICE_MAP[:device_name],
  ami_block_device_mappings: [ ROOT_DEVICE_MAP ],
  pre_mount_commands: PRE_MOUNT_COMMANDS,
  post_mount_commands: POST_MOUNT_COMMANDS,
}.freeze
CHROOT_COMMANDS =
[
  'apt-get update',
  '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',
  'update-grub',
  'rm -f /etc/init/fake-container-events.conf', # HACK
  'DEBIAN_FRONTEND=noninteractive dpkg-reconfigure resolvconf' # re-linkify resolvconf
]

Constants included from Downloader

Downloader::LOCK_WAIT_TIMEOUT

Instance Method Summary collapse

Methods included from Locking

#clear_lock, #lock, #lock_path, #lockfile, #unlock

Methods included from Downloader

#download, #unzip

Constructor Details

#initialize(config) ⇒ AmiPacker

Returns a new instance of AmiPacker.



66
67
68
69
70
71
72
73
74
# File 'lib/linecook-gem/packager/packer.rb', line 66

def initialize(config)
  system("#{packer_path} --version")
  @hvm = config[:hvm] || true
  @root_size = config[:root_size] || 10
  @region = config[:region] || 'us-east-1'
  @copy_regions = config[:copy_regions] || []
  @accounts = config[:account_ids] || []
  @write_txt = Linecook.config[:packager] && Linecook.config[:packager][:ami] && Linecook.config[:packager][:ami][:update_txt]
end

Instance Method Details

#package(image, directory) ⇒ Object



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
# File 'lib/linecook-gem/packager/packer.rb', line 76

def package(image, directory)
  @image = image
  kitchen_config = load_config(directory).send(:data).instance_variable_get(:@data)
  image_config = kitchen_config[:suites].find{ |x| x[:name] == image.name }
  if image_config && image_config[:packager]
    packager = image_config[:packager] || {}
  end
  conf_file = Tempfile.new("#{@image.id}-packer.json")
  config = generate_config(packager)
  conf_file.write(config)
  conf_file.close
  output = []
  PTY.spawn("sudo #{PACKER_PATH} build -machine-readable #{conf_file.path}") do |stdout, _, _|
    begin
      stdout.each do |line|
        output << line if line =~ /artifact/
        tokens = line.split(',')
        if tokens.length > 4
          out = tokens[4].gsub('%!(PACKER_COMMA)', ',')
          time = DateTime.strptime(tokens[0], '%s').strftime('%c')
          puts "#{time} | #{out}"
        else
          puts "unexpected output format"
          puts tokens
        end
      end
    rescue Errno::EIO
      puts "Packer finshed executing"
    end
  end
  extract_amis_from_output(output)
ensure
  conf_file.close
  conf_file.unlink
end