image_builder 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rubocop.yml +16 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +29 -0
- data/bin/image_builder +234 -0
- data/image_builder.gemspec +30 -0
- data/lib/image_builder.rb +38 -0
- data/lib/image_builder/backends/backend_base.rb +10 -0
- data/lib/image_builder/backends/packer.rb +109 -0
- data/lib/image_builder/builders/aws_base.rb +101 -0
- data/lib/image_builder/builders/aws_chroot.rb +33 -0
- data/lib/image_builder/builders/aws_ebs.rb +15 -0
- data/lib/image_builder/builders/aws_instance.rb +45 -0
- data/lib/image_builder/builders/builder_base.rb +12 -0
- data/lib/image_builder/builders/null.rb +39 -0
- data/lib/image_builder/post_processors/compress.rb +24 -0
- data/lib/image_builder/post_processors/post_processors_base.rb +10 -0
- data/lib/image_builder/post_processors/vagrant.rb +41 -0
- data/lib/image_builder/provisioners/chef_base.rb +96 -0
- data/lib/image_builder/provisioners/chef_client.rb +115 -0
- data/lib/image_builder/provisioners/chef_solo.rb +33 -0
- data/lib/image_builder/provisioners/file.rb +26 -0
- data/lib/image_builder/provisioners/provisioner_base.rb +10 -0
- data/lib/image_builder/provisioners/shell.rb +47 -0
- data/lib/image_builder/version.rb +4 -0
- data/spec/aws_chroot_builder_spec.rb +30 -0
- data/spec/aws_ebs_builder_spec.rb +30 -0
- data/spec/aws_instance_builder_spec.rb +30 -0
- data/spec/chef_client_provisioner_spec.rb +32 -0
- data/spec/chef_solo_provisioner_spec.rb +28 -0
- data/spec/compress_postprocessor_spec.rb +15 -0
- data/spec/fixtures/test-knife.rb +40 -0
- data/spec/null_builder_spec.rb +21 -0
- data/spec/packer_backend_spec.rb +145 -0
- data/spec/vagrant_postprocessor_spec.rb +20 -0
- metadata +236 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
require_relative './backend_base.rb'
|
2
|
+
require 'json'
|
3
|
+
require 'mixlib/shellout'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
# rubocop:disable Style/ClassVars
|
7
|
+
|
8
|
+
module ImageBuilder
|
9
|
+
module Backends
|
10
|
+
# Generic class doc comment
|
11
|
+
class Packer < ImageBuilder::Backends::Base
|
12
|
+
attr_accessor :description
|
13
|
+
attr_accessor :min_packer_version
|
14
|
+
attr_accessor :builders
|
15
|
+
attr_accessor :post_processors
|
16
|
+
attr_accessor :provisioners
|
17
|
+
attr_accessor :variables
|
18
|
+
|
19
|
+
@@default_path = ['/bin', '/usr/bin', '/sbin', '/usr/sbin', '/usr/local/bin']
|
20
|
+
@@default_path << ::File.join(ENV['GEM_HOME'], 'bin') if ENV.key? 'GEM_HOME'
|
21
|
+
|
22
|
+
@@packer_exe = 'packer'
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@builders = []
|
26
|
+
@post_processors = []
|
27
|
+
@provisioners = []
|
28
|
+
@variables = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.packer_path(path)
|
32
|
+
@@packer_exe = ::File.expand_path(path)
|
33
|
+
@@default_path.unshift ::File.dirname(::File.expand_path(@@packer_exe))
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.packer_path=(path)
|
37
|
+
packer_path(path)
|
38
|
+
end
|
39
|
+
|
40
|
+
# rubocop:disable Metrics/LineLength
|
41
|
+
def add_builder(builder_obj)
|
42
|
+
fail ArgumentError, 'Invalid builder object, does not respond to packer_hash()' unless builder_obj.respond_to?(:packer_hash)
|
43
|
+
@builders << builder_obj.packer_hash
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_post_processor(post_obj)
|
47
|
+
fail ArgumentError, 'Invalid post-processor object, does not respond to packer_hash()' unless post_obj.respond_to?(:packer_hash)
|
48
|
+
@post_processors << post_obj.packer_hash
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_provisioner(provisioner_obj)
|
52
|
+
fail ArgumentError, 'Invalid provisioner object, does not respond to packer_hash()' unless provisioner_obj.respond_to?(:packer_hash)
|
53
|
+
@provisioners << provisioner_obj.packer_hash
|
54
|
+
end
|
55
|
+
# rubocop:enable Metrics/LineLength
|
56
|
+
|
57
|
+
def add_variable(name, value = '')
|
58
|
+
@variables[name] = value
|
59
|
+
end
|
60
|
+
|
61
|
+
def build(args = [])
|
62
|
+
validate
|
63
|
+
|
64
|
+
cmd = [@@packer_exe, 'build'].concat(args)
|
65
|
+
cmd << '-'
|
66
|
+
|
67
|
+
# Some provisioners may take a long time to run without giving output (applying OS updates via Chef
|
68
|
+
# to CentOS6 comes to mind), so extend the timeout to an hour.
|
69
|
+
shellout = Mixlib::ShellOut.new(cmd, env: { 'PATH' => @@default_path.join(':') }, input: to_json, timeout: 3600)
|
70
|
+
shellout.live_stdout = STDOUT
|
71
|
+
shellout.live_stderr = STDERR
|
72
|
+
shellout.run_command
|
73
|
+
shellout.error!
|
74
|
+
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate(args = [])
|
79
|
+
cmd = [@@packer_exe, 'validate'].concat(args)
|
80
|
+
cmd << '-'
|
81
|
+
|
82
|
+
shellout = Mixlib::ShellOut.new(cmd, env: { 'PATH' => @@default_path.join(':') }, input: to_json)
|
83
|
+
shellout.inspect
|
84
|
+
shellout.run_command
|
85
|
+
shellout.error!
|
86
|
+
|
87
|
+
shellout.stdout
|
88
|
+
|
89
|
+
true
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_json
|
93
|
+
config = {}
|
94
|
+
|
95
|
+
attr_to_hash(config, :description)
|
96
|
+
attr_to_hash(config, :min_packer_version)
|
97
|
+
attr_to_hash(config, :variables)
|
98
|
+
attr_to_hash(config, :builders, true)
|
99
|
+
attr_to_hash(config, :provisioners)
|
100
|
+
|
101
|
+
# Special handling for post-processors, since the packer config name uses '-', and ruby doesn't
|
102
|
+
# like those (you know....subtraction operator, and all that)
|
103
|
+
config['post-processors'] = @post_processors unless @post_processors.nil? || @post_processors.empty?
|
104
|
+
|
105
|
+
config.to_json
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require_relative './builder_base.rb'
|
2
|
+
|
3
|
+
module ImageBuilder
|
4
|
+
module Builders
|
5
|
+
module AWS
|
6
|
+
# Generic class doc comment
|
7
|
+
class Base < ImageBuilder::Builders::Base
|
8
|
+
attr_accessor :access_key
|
9
|
+
attr_accessor :ami_name
|
10
|
+
attr_accessor :instance_type
|
11
|
+
attr_accessor :region
|
12
|
+
attr_accessor :secret_key
|
13
|
+
attr_accessor :source_ami
|
14
|
+
attr_accessor :ssh_username
|
15
|
+
# - opt -
|
16
|
+
attr_accessor :ami_block_device_mappings
|
17
|
+
attr_accessor :ami_description
|
18
|
+
attr_accessor :ami_groups
|
19
|
+
attr_accessor :ami_product_codes
|
20
|
+
attr_accessor :ami_regions
|
21
|
+
attr_accessor :ami_users
|
22
|
+
attr_accessor :ami_virtualization_type
|
23
|
+
attr_accessor :associate_public_ip_address
|
24
|
+
attr_accessor :availability_zone
|
25
|
+
attr_accessor :enhanced_networking
|
26
|
+
attr_accessor :iam_instance_profile
|
27
|
+
attr_accessor :launch_block_device_mappings
|
28
|
+
attr_accessor :run_tags
|
29
|
+
attr_accessor :security_group_id
|
30
|
+
attr_accessor :security_group_ids
|
31
|
+
attr_accessor :spot_price
|
32
|
+
attr_accessor :spot_price_auto_product
|
33
|
+
attr_accessor :ssh_port
|
34
|
+
attr_accessor :ssh_private_key_file
|
35
|
+
attr_accessor :ssh_private_ip
|
36
|
+
attr_accessor :ssh_timeout
|
37
|
+
attr_accessor :subnet_id
|
38
|
+
attr_accessor :tags
|
39
|
+
attr_accessor :temporary_key_pair_name
|
40
|
+
attr_accessor :token
|
41
|
+
attr_accessor :user_data
|
42
|
+
attr_accessor :user_data_file
|
43
|
+
attr_accessor :vpc_id
|
44
|
+
|
45
|
+
attr_reader :type
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@access_key = ENV['AWS_ACCESS_KEY_ID'] || ENV['AWS_ACCESS_KEY']
|
49
|
+
@secret_key = ENV['AWS_SECRET_ACCESS_KEY'] || ENV['AWS_SECRET_KEY']
|
50
|
+
@region = 'us-east-1'
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.default_block_device_mappings
|
54
|
+
[
|
55
|
+
{ device_name: '/dev/sdf', virtual_name: 'ephemeral0' },
|
56
|
+
{ device_name: '/dev/sdg', virtual_name: 'ephemeral1' },
|
57
|
+
{ device_name: '/dev/sdh', virtual_name: 'ephemeral2' },
|
58
|
+
{ device_name: '/dev/sdi', virtual_name: 'ephemeral3' }
|
59
|
+
]
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.default_launch_block_device_mappings
|
63
|
+
[
|
64
|
+
{ device_name: '/dev/sdb', no_device: true },
|
65
|
+
{ device_name: '/dev/sdc', no_device: true },
|
66
|
+
{ device_name: '/dev/sdd', no_device: true }
|
67
|
+
]
|
68
|
+
end
|
69
|
+
|
70
|
+
def packer_hash
|
71
|
+
hash = {}
|
72
|
+
|
73
|
+
req_attrs = [
|
74
|
+
:type, :name, :access_key, :ami_name, :instance_type,
|
75
|
+
:region, :secret_key, :source_ami, :ssh_username
|
76
|
+
]
|
77
|
+
|
78
|
+
opt_attrs = [
|
79
|
+
:ami_description, :ami_groups, :ami_product_codes, :ami_regions, :ami_regions, :ami_users,
|
80
|
+
:ami_virtualization_type, :associate_public_ip_address, :availability_zone, :enhanced_networking,
|
81
|
+
:iam_instance_profile, :run_tags, :security_group_id, :security_group_ids, :spot_price,
|
82
|
+
:spot_price_auto_product, :ssh_port, :ssh_private_key_file, :ssh_private_ip, :ssh_timeout,
|
83
|
+
:subnet_id, :tags, :temporary_key_pair_name, :token, :user_data, :user_data_file, :vpc_id,
|
84
|
+
:launch_block_device_mappings, :ami_block_device_mappings
|
85
|
+
]
|
86
|
+
|
87
|
+
# Required attrs
|
88
|
+
req_attrs.each do |a|
|
89
|
+
attr_to_hash(hash, a, true)
|
90
|
+
end
|
91
|
+
|
92
|
+
opt_attrs.each do |a|
|
93
|
+
attr_to_hash(hash, a)
|
94
|
+
end
|
95
|
+
|
96
|
+
hash
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative './aws_base.rb'
|
2
|
+
|
3
|
+
module ImageBuilder
|
4
|
+
module Builders
|
5
|
+
module AWS
|
6
|
+
# Generic class doc comment
|
7
|
+
class Chroot < ImageBuilder::Builders::AWS::Base
|
8
|
+
attr_accessor :chroot_mounts
|
9
|
+
attr_accessor :command_wrapper
|
10
|
+
attr_accessor :copy_files
|
11
|
+
attr_accessor :device_path
|
12
|
+
attr_accessor :mount_path
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
@type = 'amazon-chroot'
|
17
|
+
end
|
18
|
+
|
19
|
+
def packer_hash
|
20
|
+
hash = super
|
21
|
+
|
22
|
+
attr_to_hash(hash, :chroot_mounts)
|
23
|
+
attr_to_hash(hash, :command_wrapper)
|
24
|
+
attr_to_hash(hash, :copy_files)
|
25
|
+
attr_to_hash(hash, :device_path)
|
26
|
+
attr_to_hash(hash, :mount_path)
|
27
|
+
|
28
|
+
hash
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative './aws_base.rb'
|
2
|
+
|
3
|
+
module ImageBuilder
|
4
|
+
module Builders
|
5
|
+
module AWS
|
6
|
+
# Generic class doc comment
|
7
|
+
class Instance < ImageBuilder::Builders::AWS::Base
|
8
|
+
attr_accessor :account_id
|
9
|
+
attr_accessor :s3_bucket
|
10
|
+
attr_accessor :x509_cert_path
|
11
|
+
attr_accessor :x509_key_path
|
12
|
+
# - opt -
|
13
|
+
attr_accessor :bundle_destination
|
14
|
+
attr_accessor :bundle_prefix
|
15
|
+
attr_accessor :bundle_upload_command
|
16
|
+
attr_accessor :bundle_vol_command
|
17
|
+
attr_accessor :x509_upload_path
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
super
|
21
|
+
@type = 'amazon-instance'
|
22
|
+
end
|
23
|
+
|
24
|
+
def packer_hash
|
25
|
+
hash = super
|
26
|
+
|
27
|
+
# Required
|
28
|
+
attr_to_hash(hash, :account_id, true)
|
29
|
+
attr_to_hash(hash, :s3_bucket, true)
|
30
|
+
attr_to_hash(hash, :x509_cert_path, true)
|
31
|
+
attr_to_hash(hash, :x509_key_path, true)
|
32
|
+
|
33
|
+
# Optional
|
34
|
+
attr_to_hash(hash, :bundle_destination)
|
35
|
+
attr_to_hash(hash, :bundle_prefix)
|
36
|
+
attr_to_hash(hash, :bundle_upload_command)
|
37
|
+
attr_to_hash(hash, :bundle_vol_command)
|
38
|
+
attr_to_hash(hash, :x509_upload_path)
|
39
|
+
|
40
|
+
hash
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative './builder_base.rb'
|
2
|
+
require 'etc'
|
3
|
+
|
4
|
+
module ImageBuilder
|
5
|
+
module Builders
|
6
|
+
# Generic class doc comment
|
7
|
+
class Null < ImageBuilder::Builders::Base
|
8
|
+
attr_accessor :host
|
9
|
+
attr_accessor :ssh_password
|
10
|
+
attr_accessor :ssh_username
|
11
|
+
attr_accessor :ssh_private_key_file
|
12
|
+
attr_accessor :port
|
13
|
+
|
14
|
+
attr_reader :type
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@type = 'null'
|
18
|
+
@host = '127.0.0.1'
|
19
|
+
@port = 22
|
20
|
+
@ssh_username = Etc.getlogin
|
21
|
+
@ssh_private_key_file = ::File.join(::Dir.home, '.ssh', 'id_rsa')
|
22
|
+
end
|
23
|
+
|
24
|
+
def packer_hash
|
25
|
+
hash = {}
|
26
|
+
|
27
|
+
attr_to_hash(hash, :type, true)
|
28
|
+
attr_to_hash(hash, :name, true)
|
29
|
+
attr_to_hash(hash, :host, true)
|
30
|
+
attr_to_hash(hash, :ssh_username, true)
|
31
|
+
attr_to_hash(hash, :ssh_password)
|
32
|
+
attr_to_hash(hash, :ssh_private_key_file)
|
33
|
+
attr_to_hash(hash, :port)
|
34
|
+
|
35
|
+
hash
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative './post_processors_base.rb'
|
2
|
+
|
3
|
+
module ImageBuilder
|
4
|
+
module PostProcessors
|
5
|
+
# Generic class doc comment
|
6
|
+
class Compress < ImageBuilder::PostProcessors::Base
|
7
|
+
attr_accessor :output
|
8
|
+
attr_reader :type
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@type = 'compress'
|
12
|
+
end
|
13
|
+
|
14
|
+
def packer_hash
|
15
|
+
hash = {}
|
16
|
+
|
17
|
+
attr_to_hash(hash, :type, true)
|
18
|
+
attr_to_hash(hash, :output, true)
|
19
|
+
|
20
|
+
hash
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative './post_processors_base.rb'
|
2
|
+
|
3
|
+
module ImageBuilder
|
4
|
+
module PostProcessors
|
5
|
+
# Generic class doc comment
|
6
|
+
class Vagrant < ImageBuilder::PostProcessors::Base
|
7
|
+
attr_accessor :compression_level
|
8
|
+
attr_accessor :include
|
9
|
+
attr_accessor :keep_input_artifact
|
10
|
+
attr_accessor :output
|
11
|
+
attr_accessor :vagrantfile_template
|
12
|
+
attr_accessor :override
|
13
|
+
|
14
|
+
attr_reader :type
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@type = 'vagrant'
|
18
|
+
@compression_level = 6
|
19
|
+
@keep_input_artifact = false
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_override(provider, override_hash)
|
23
|
+
@override[provider] = override_hash
|
24
|
+
end
|
25
|
+
|
26
|
+
def packer_hash
|
27
|
+
hash = {}
|
28
|
+
|
29
|
+
attr_to_hash(hash, :type, true)
|
30
|
+
attr_to_hash(hash, :compression_level)
|
31
|
+
attr_to_hash(hash, :include)
|
32
|
+
attr_to_hash(hash, :keep_input_artifact)
|
33
|
+
attr_to_hash(hash, :output)
|
34
|
+
attr_to_hash(hash, :vagrantfile_template)
|
35
|
+
attr_to_hash(hash, :override)
|
36
|
+
|
37
|
+
hash
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|