builderator 0.3.15 → 1.0.0.pre.rc.1
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/Gemfile +9 -0
- data/Gemfile.lock +440 -0
- data/README.md +72 -18
- data/Rakefile +1 -2
- data/VERSION +1 -1
- data/bin/build-clean +102 -0
- data/bin/build-data +45 -0
- data/builderator.gemspec +7 -4
- data/docs/configuration.md +154 -0
- data/docs/configuration/cookbook.md +19 -0
- data/docs/configuration/profile.md +71 -0
- data/docs/versioning.md +65 -0
- data/lib/builderator.rb +3 -0
- data/lib/builderator/config.rb +93 -0
- data/lib/builderator/config/attributes.rb +287 -0
- data/lib/builderator/config/defaults.rb +163 -0
- data/lib/builderator/config/file.rb +336 -0
- data/lib/builderator/config/rash.rb +80 -0
- data/lib/builderator/control/cleaner.rb +138 -0
- data/lib/builderator/control/cookbook.rb +16 -0
- data/lib/builderator/control/data.rb +16 -0
- data/lib/builderator/control/data/image.rb +98 -0
- data/lib/builderator/control/version.rb +128 -0
- data/lib/builderator/control/version/auto.rb +48 -0
- data/lib/builderator/control/version/bump.rb +82 -0
- data/lib/builderator/control/version/comparable.rb +77 -0
- data/lib/builderator/control/version/git.rb +45 -0
- data/lib/builderator/control/version/scm.rb +92 -0
- data/lib/builderator/interface.rb +67 -0
- data/lib/builderator/interface/berkshelf.rb +38 -0
- data/lib/builderator/interface/packer.rb +75 -0
- data/lib/builderator/interface/vagrant.rb +31 -0
- data/lib/builderator/metadata.rb +5 -3
- data/lib/builderator/model/cleaner.rb +49 -0
- data/lib/builderator/model/cleaner/images.rb +93 -0
- data/lib/builderator/model/cleaner/instances.rb +58 -0
- data/lib/builderator/model/cleaner/launch_configs.rb +47 -0
- data/lib/builderator/model/cleaner/scaling_groups.rb +45 -0
- data/lib/builderator/model/cleaner/snapshots.rb +50 -0
- data/lib/builderator/model/cleaner/volumes.rb +48 -0
- data/lib/builderator/patch/berkshelf.rb +18 -0
- data/lib/builderator/patch/thor-actions.rb +47 -0
- data/lib/builderator/tasks.rb +127 -17
- data/lib/builderator/tasks/berkshelf.rb +63 -0
- data/lib/builderator/tasks/packer.rb +17 -56
- data/lib/builderator/tasks/vagrant.rb +111 -42
- data/lib/builderator/tasks/vendor.rb +94 -0
- data/lib/builderator/tasks/version.rb +58 -0
- data/lib/builderator/util.rb +37 -11
- data/lib/builderator/util/aws_exception.rb +1 -1
- data/lib/builderator/util/limit_exception.rb +12 -11
- data/lib/builderator/util/task_exception.rb +0 -2
- data/mkmf.log +4 -0
- data/spec/config_spec.rb +30 -0
- data/spec/data/Berksfile +6 -0
- data/spec/data/Buildfile +0 -0
- data/spec/data/Vagrantfile +0 -0
- data/spec/data/history.json +483 -0
- data/spec/data/packer.json +0 -0
- data/spec/interface_spec.rb +36 -0
- data/spec/resource/Buildfile +27 -0
- data/spec/spec_helper.rb +90 -0
- data/spec/version_spec.rb +282 -0
- data/template/Berksfile.erb +10 -0
- data/template/Buildfile.erb +28 -0
- data/template/Gemfile.erb +16 -0
- data/template/README.md.erb +61 -0
- data/template/Vagrantfile.erb +75 -0
- data/template/gitignore.erb +104 -0
- data/{.rubocop.yml → template/rubocop.erb} +0 -0
- metadata +203 -56
- data/.gitignore +0 -14
- data/lib/builderator/control/ami.rb +0 -65
- data/lib/builderator/control/clean.rb +0 -130
- data/lib/builderator/model.rb +0 -46
- data/lib/builderator/model/images.rb +0 -89
- data/lib/builderator/model/instances.rb +0 -55
- data/lib/builderator/model/launch_configs.rb +0 -46
- data/lib/builderator/model/scaling_groups.rb +0 -43
- data/lib/builderator/model/snapshots.rb +0 -49
- data/lib/builderator/model/volumes.rb +0 -48
- data/lib/builderator/tasks/ami.rb +0 -47
- data/lib/builderator/tasks/berks.rb +0 -68
- data/lib/builderator/tasks/clean.rb +0 -97
- data/lib/builderator/util/berkshim.rb +0 -34
- data/lib/builderator/util/cookbook.rb +0 -87
- data/lib/builderator/util/packer.rb +0 -39
- data/lib/builderator/util/shell.rb +0 -44
@@ -0,0 +1,75 @@
|
|
1
|
+
require_relative '../interface'
|
2
|
+
|
3
|
+
module Builderator
|
4
|
+
# :nodoc:
|
5
|
+
class Interface
|
6
|
+
class << self
|
7
|
+
def packer
|
8
|
+
@packer ||= Packer.new
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Generate packer.json
|
14
|
+
##
|
15
|
+
class Packer < Interface
|
16
|
+
command 'packer'
|
17
|
+
attr_reader :packerfile
|
18
|
+
|
19
|
+
def initialize(*_)
|
20
|
+
super
|
21
|
+
|
22
|
+
@packerfile ||= {
|
23
|
+
:builders => [],
|
24
|
+
:provisioners => []
|
25
|
+
}.tap do |json|
|
26
|
+
Config.profile.current.packer.build.each do |_, build|
|
27
|
+
json[:builders] << build.to_hash.tap do |b|
|
28
|
+
b[:tags] = Config.profile.current.tags
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
## Initialize the staging directory
|
33
|
+
json[:provisioners] << {
|
34
|
+
:type => 'shell',
|
35
|
+
:inline => "sudo mkdir -p #{Config.chef.staging_directory}/cache && "\
|
36
|
+
"sudo chown $(whoami) -R #{Config.chef.staging_directory}"
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
_artifact_provisioners
|
41
|
+
_chef_provisioner
|
42
|
+
end
|
43
|
+
|
44
|
+
def render
|
45
|
+
JSON.pretty_generate(packerfile)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
## Upload artifacts to the build container
|
51
|
+
def _artifact_provisioners
|
52
|
+
Config.profile.current.artifact.each do |_, artifact|
|
53
|
+
packerfile[:provisioners] << {
|
54
|
+
:type => 'file',
|
55
|
+
:source => artifact.path,
|
56
|
+
:destination => artifact.destination
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def _chef_provisioner
|
62
|
+
packerfile[:provisioners] << {
|
63
|
+
:type => 'chef-solo',
|
64
|
+
:run_list => Config.profile.current.chef.run_list,
|
65
|
+
:cookbook_paths => Config.local.cookbook_path,
|
66
|
+
:data_bags_path => Config.local.data_bag_path,
|
67
|
+
:environments_path => Config.local.environment_path,
|
68
|
+
:chef_environment => Config.profile.current.chef.environment,
|
69
|
+
:json => Config.profile.current.chef.node_attrs,
|
70
|
+
:staging_directory => Config.chef.staging_directory
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative '../interface'
|
2
|
+
|
3
|
+
module Builderator
|
4
|
+
# :nodoc:
|
5
|
+
class Interface
|
6
|
+
class << self
|
7
|
+
def vagrant
|
8
|
+
@vagrant ||= Vagrant.new
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Render a temporary Vagrantfile
|
14
|
+
##
|
15
|
+
class Vagrant < Interface
|
16
|
+
command 'vagrant'
|
17
|
+
template 'template/Vagrantfile.erb'
|
18
|
+
|
19
|
+
def command
|
20
|
+
c = ''
|
21
|
+
c << 'ulimit -n 1024; ' if bundled?
|
22
|
+
c << 'VAGRANT_I_KNOW_WHAT_IM_DOING_PLEASE_BE_QUIET=true ' if bundled?
|
23
|
+
c << which
|
24
|
+
end
|
25
|
+
|
26
|
+
def source
|
27
|
+
directory.join('Vagrantfile')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/builderator/metadata.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
require_relative './util'
|
2
|
+
|
3
|
+
# :nodoc:
|
1
4
|
module Builderator
|
2
|
-
|
3
|
-
|
4
|
-
DESCRIPTION = IO.read(File.join(PATH, 'README.md')) rescue 'README.md not found!'
|
5
|
+
VERSION = Util.source_path('VERSION').read rescue '0.0.1'
|
6
|
+
DESCRIPTION = Util.source_path('README.md').read rescue 'README.md not found!'
|
5
7
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Builderator
|
2
|
+
module Model
|
3
|
+
module Cleaner
|
4
|
+
##
|
5
|
+
# Shared model interface
|
6
|
+
##
|
7
|
+
class Base
|
8
|
+
attr_reader :resources
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
fetch(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def fetch
|
15
|
+
@resources = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def find(filters = {})
|
19
|
+
Util.filter(resources, filters)
|
20
|
+
end
|
21
|
+
|
22
|
+
def select(set = [])
|
23
|
+
resources.select { |k, _| set.include?(k) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def in_use
|
27
|
+
find(Config.cleaner.filters)
|
28
|
+
end
|
29
|
+
|
30
|
+
def in_use?(key)
|
31
|
+
@in_use ||= in_use
|
32
|
+
|
33
|
+
@in_use.include?(key)
|
34
|
+
end
|
35
|
+
|
36
|
+
def unused
|
37
|
+
resources.reject { |k, _| in_use?(k) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
require_relative './cleaner/images'
|
45
|
+
require_relative './cleaner/instances'
|
46
|
+
require_relative './cleaner/launch_configs'
|
47
|
+
require_relative './cleaner/scaling_groups'
|
48
|
+
require_relative './cleaner/snapshots'
|
49
|
+
require_relative './cleaner/volumes'
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require_relative '../../util'
|
3
|
+
|
4
|
+
module Builderator
|
5
|
+
module Model
|
6
|
+
# :nodoc:
|
7
|
+
module Cleaner
|
8
|
+
def self.images
|
9
|
+
@images ||= Images.new
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# EC2 AMI Resources
|
14
|
+
##
|
15
|
+
class Images < Model::Cleaner::Base
|
16
|
+
PROPERTIES = %w(image_location state owner_id public architecture image_type
|
17
|
+
name description root_device_type virtualization_type
|
18
|
+
hypervisor)
|
19
|
+
|
20
|
+
def fetch
|
21
|
+
@resources = {}.tap do |i|
|
22
|
+
Util.ec2.describe_images(:filters => [
|
23
|
+
{
|
24
|
+
:name => 'state',
|
25
|
+
:values => %w(available)
|
26
|
+
}
|
27
|
+
], :owners => %w(self)).each do |page|
|
28
|
+
page.images.each do |image|
|
29
|
+
properties = Util.from_tags(image.tags)
|
30
|
+
properties['creation_date'] = DateTime.iso8601(image.creation_date)
|
31
|
+
PROPERTIES.each { |pp| properties[pp] = image[pp.to_sym] }
|
32
|
+
|
33
|
+
i[image.image_id] = {
|
34
|
+
:id => image.image_id,
|
35
|
+
:properties => properties,
|
36
|
+
:snapshots => image.block_device_mappings.map { |b| b.ebs.snapshot_id rescue nil }.reject(&:nil?),
|
37
|
+
:parent => properties.fetch('parent_ami', '(undefined)')
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def snapshots
|
45
|
+
resources.values.map { |i| i[:snapshots] }.flatten
|
46
|
+
end
|
47
|
+
|
48
|
+
def latest
|
49
|
+
{}.tap do |latest|
|
50
|
+
## Group images
|
51
|
+
group_by = Config.cleaner.group_by
|
52
|
+
groups = {}.tap do |object|
|
53
|
+
break { 'all' => resources.values } if group_by.empty?
|
54
|
+
|
55
|
+
resources.each do |_, image|
|
56
|
+
## Construct a grouping-key from image properties
|
57
|
+
grouping_key = group_by.map do |grouping_property|
|
58
|
+
image[:properties].fetch(grouping_property.to_s, '(unknown)')
|
59
|
+
end.join(':')
|
60
|
+
|
61
|
+
## Create an array for the group if it doesn't already exist
|
62
|
+
## and add the image to it
|
63
|
+
(object[grouping_key] ||= []) << image
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
## Sort each grouping
|
68
|
+
groups.each do |_, group|
|
69
|
+
group.sort! { |a, b| b[:properties][Config.cleaner.sort_by] <=> a[:properties][Config.cleaner.sort_by] }
|
70
|
+
end
|
71
|
+
|
72
|
+
## Slice to `keep` length
|
73
|
+
groups.each do |_, group|
|
74
|
+
group.slice!(Config.cleaner.keep..-1)
|
75
|
+
end
|
76
|
+
|
77
|
+
## Reduce
|
78
|
+
groups.values.flatten.each { |i| latest[i[:id]] = i }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def in_use
|
83
|
+
{}.tap do |used|
|
84
|
+
used.merge!(select(Cleaner.instances.images))
|
85
|
+
used.merge!(select(Cleaner.launch_configs.images))
|
86
|
+
used.merge!(latest)
|
87
|
+
used.merge!(select(used.values.map { |i| i[:parent] }))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require_relative '../../util'
|
3
|
+
|
4
|
+
module Builderator
|
5
|
+
module Model
|
6
|
+
# :nodoc:
|
7
|
+
module Cleaner
|
8
|
+
def self.instances
|
9
|
+
@instances ||= Instances.new
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# EC2 Instance resources
|
14
|
+
##
|
15
|
+
class Instances < Model::Cleaner::Base
|
16
|
+
PROPERTIES = %w(private_dns_name public_dns_name instance_type
|
17
|
+
subnet_id vpc_id private_ip_address public_ip_address
|
18
|
+
architecture root_device_type virtualization_type
|
19
|
+
hypervisor)
|
20
|
+
|
21
|
+
def fetch
|
22
|
+
@resources = {}.tap do |i|
|
23
|
+
Util.ec2.describe_instances(:filters => [
|
24
|
+
{
|
25
|
+
:name => 'instance-state-name',
|
26
|
+
:values => %w(pending running shutting-down stopping stopped)
|
27
|
+
}
|
28
|
+
]).each do |page|
|
29
|
+
page.reservations.each do |r|
|
30
|
+
r.instances.each do |instance|
|
31
|
+
properties = Util.from_tags(instance.tags)
|
32
|
+
properties['availability_zone'] = instance.placement.availability_zone
|
33
|
+
properties['creation_date'] = instance.launch_time.to_datetime
|
34
|
+
PROPERTIES.each { |pp| properties[pp] = instance[pp.to_sym] }
|
35
|
+
|
36
|
+
i[instance.instance_id] = {
|
37
|
+
:id => instance.instance_id,
|
38
|
+
:image => instance.image_id,
|
39
|
+
:volumes => instance.block_device_mappings.map { |b| b.ebs.volume_id },
|
40
|
+
:properties => properties
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def images
|
49
|
+
resources.values.map { |i| i[:image] }
|
50
|
+
end
|
51
|
+
|
52
|
+
def volumes
|
53
|
+
resources.values.map { |i| i[:volumes] }.flatten
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require_relative '../../util'
|
3
|
+
|
4
|
+
module Builderator
|
5
|
+
module Model
|
6
|
+
# :nodoc:
|
7
|
+
module Cleaner
|
8
|
+
def self.launch_configs
|
9
|
+
@launch_configs ||= LaunchConfigs.new
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# ASG LaunchConfiguration Resources
|
14
|
+
##
|
15
|
+
class LaunchConfigs < Model::Cleaner::Base
|
16
|
+
PROPERTIES = %w(launch_configuration_arn key_name security_groups
|
17
|
+
user_data instance_type spot_price iam_instance_profile
|
18
|
+
ebs_optimized associate_public_ip_address placement_tenancy)
|
19
|
+
|
20
|
+
def fetch
|
21
|
+
@resources = {}.tap do |i|
|
22
|
+
Util.asg.describe_launch_configurations.each do |page|
|
23
|
+
page.launch_configurations.each do |l|
|
24
|
+
properties = { 'creation_date' => l.created_time.to_datetime }
|
25
|
+
PROPERTIES.each { |pp| properties[pp] = l[pp.to_sym] }
|
26
|
+
|
27
|
+
i[l.launch_configuration_name] = {
|
28
|
+
:id => l.launch_configuration_name,
|
29
|
+
:properties => properties,
|
30
|
+
:image => l.image_id
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def images
|
38
|
+
resources.values.map { |l| l[:image] }
|
39
|
+
end
|
40
|
+
|
41
|
+
def in_use
|
42
|
+
select(Cleaner.scaling_groups.launch_configs)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require_relative '../../util'
|
3
|
+
|
4
|
+
module Builderator
|
5
|
+
module Model
|
6
|
+
# :nodoc:
|
7
|
+
module Cleaner
|
8
|
+
def self.scaling_groups
|
9
|
+
@scaling_groups ||= ScalingGroups.new
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# AutoScaling Group Resoruces
|
14
|
+
##
|
15
|
+
class ScalingGroups < Model::Cleaner::Base
|
16
|
+
attr_reader :resources
|
17
|
+
PROPERTIES = %w(auto_scaling_group_arn min_size max_size desired_capacity
|
18
|
+
default_cooldown availability_zones load_balancer_names
|
19
|
+
vpc_zone_identifier status termination_policies)
|
20
|
+
|
21
|
+
def fetch
|
22
|
+
@resources = {}.tap do |i|
|
23
|
+
Util.asg.describe_auto_scaling_groups.each do |page|
|
24
|
+
page.auto_scaling_groups.each do |a|
|
25
|
+
properties = Util.from_tags(a.tags)
|
26
|
+
properties['creation_date'] = a.created_time.to_datetime
|
27
|
+
PROPERTIES.each { |pp| properties[pp] = a[pp.to_sym] }
|
28
|
+
|
29
|
+
i[a.launch_configuration_name] = {
|
30
|
+
:id => a.auto_scaling_group_name,
|
31
|
+
:properties => properties,
|
32
|
+
:config => a.launch_configuration_name
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def launch_configs
|
40
|
+
resources.values.map { |g| g[:config] }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require_relative '../../util'
|
3
|
+
|
4
|
+
module Builderator
|
5
|
+
module Model
|
6
|
+
# :nodoc:
|
7
|
+
module Cleaner
|
8
|
+
def self.snapshots
|
9
|
+
@snapshots ||= Snapshots.new
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# EC2 Snapshot Resources
|
14
|
+
##
|
15
|
+
class Snapshots < Model::Cleaner::Base
|
16
|
+
PROPERTIES = %w(state owner_id description volume_size)
|
17
|
+
|
18
|
+
def fetch
|
19
|
+
@resources = {}.tap do |s|
|
20
|
+
Util.ec2.describe_snapshots(:filters => [
|
21
|
+
{
|
22
|
+
:name => 'status',
|
23
|
+
:values => %w(completed)
|
24
|
+
}
|
25
|
+
], :owner_ids => ['self']).each do |page|
|
26
|
+
page.snapshots.each do |snap|
|
27
|
+
properties = Util.from_tags(snap.tags)
|
28
|
+
properties['creation_date'] = snap.start_time.to_datetime
|
29
|
+
PROPERTIES.each { |pp| properties[pp] = snap[pp.to_sym] }
|
30
|
+
|
31
|
+
s[snap.snapshot_id] = {
|
32
|
+
:id => snap.snapshot_id,
|
33
|
+
:properties => properties,
|
34
|
+
:volume => snap.volume_id
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def in_use
|
42
|
+
{}.tap do |used|
|
43
|
+
used.merge!(select(Cleaner.volumes.snapshots))
|
44
|
+
used.merge!(select(Cleaner.images.snapshots))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|