builderator 0.3.15 → 1.0.0.pre.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +9 -0
  3. data/Gemfile.lock +440 -0
  4. data/README.md +72 -18
  5. data/Rakefile +1 -2
  6. data/VERSION +1 -1
  7. data/bin/build-clean +102 -0
  8. data/bin/build-data +45 -0
  9. data/builderator.gemspec +7 -4
  10. data/docs/configuration.md +154 -0
  11. data/docs/configuration/cookbook.md +19 -0
  12. data/docs/configuration/profile.md +71 -0
  13. data/docs/versioning.md +65 -0
  14. data/lib/builderator.rb +3 -0
  15. data/lib/builderator/config.rb +93 -0
  16. data/lib/builderator/config/attributes.rb +287 -0
  17. data/lib/builderator/config/defaults.rb +163 -0
  18. data/lib/builderator/config/file.rb +336 -0
  19. data/lib/builderator/config/rash.rb +80 -0
  20. data/lib/builderator/control/cleaner.rb +138 -0
  21. data/lib/builderator/control/cookbook.rb +16 -0
  22. data/lib/builderator/control/data.rb +16 -0
  23. data/lib/builderator/control/data/image.rb +98 -0
  24. data/lib/builderator/control/version.rb +128 -0
  25. data/lib/builderator/control/version/auto.rb +48 -0
  26. data/lib/builderator/control/version/bump.rb +82 -0
  27. data/lib/builderator/control/version/comparable.rb +77 -0
  28. data/lib/builderator/control/version/git.rb +45 -0
  29. data/lib/builderator/control/version/scm.rb +92 -0
  30. data/lib/builderator/interface.rb +67 -0
  31. data/lib/builderator/interface/berkshelf.rb +38 -0
  32. data/lib/builderator/interface/packer.rb +75 -0
  33. data/lib/builderator/interface/vagrant.rb +31 -0
  34. data/lib/builderator/metadata.rb +5 -3
  35. data/lib/builderator/model/cleaner.rb +49 -0
  36. data/lib/builderator/model/cleaner/images.rb +93 -0
  37. data/lib/builderator/model/cleaner/instances.rb +58 -0
  38. data/lib/builderator/model/cleaner/launch_configs.rb +47 -0
  39. data/lib/builderator/model/cleaner/scaling_groups.rb +45 -0
  40. data/lib/builderator/model/cleaner/snapshots.rb +50 -0
  41. data/lib/builderator/model/cleaner/volumes.rb +48 -0
  42. data/lib/builderator/patch/berkshelf.rb +18 -0
  43. data/lib/builderator/patch/thor-actions.rb +47 -0
  44. data/lib/builderator/tasks.rb +127 -17
  45. data/lib/builderator/tasks/berkshelf.rb +63 -0
  46. data/lib/builderator/tasks/packer.rb +17 -56
  47. data/lib/builderator/tasks/vagrant.rb +111 -42
  48. data/lib/builderator/tasks/vendor.rb +94 -0
  49. data/lib/builderator/tasks/version.rb +58 -0
  50. data/lib/builderator/util.rb +37 -11
  51. data/lib/builderator/util/aws_exception.rb +1 -1
  52. data/lib/builderator/util/limit_exception.rb +12 -11
  53. data/lib/builderator/util/task_exception.rb +0 -2
  54. data/mkmf.log +4 -0
  55. data/spec/config_spec.rb +30 -0
  56. data/spec/data/Berksfile +6 -0
  57. data/spec/data/Buildfile +0 -0
  58. data/spec/data/Vagrantfile +0 -0
  59. data/spec/data/history.json +483 -0
  60. data/spec/data/packer.json +0 -0
  61. data/spec/interface_spec.rb +36 -0
  62. data/spec/resource/Buildfile +27 -0
  63. data/spec/spec_helper.rb +90 -0
  64. data/spec/version_spec.rb +282 -0
  65. data/template/Berksfile.erb +10 -0
  66. data/template/Buildfile.erb +28 -0
  67. data/template/Gemfile.erb +16 -0
  68. data/template/README.md.erb +61 -0
  69. data/template/Vagrantfile.erb +75 -0
  70. data/template/gitignore.erb +104 -0
  71. data/{.rubocop.yml → template/rubocop.erb} +0 -0
  72. metadata +203 -56
  73. data/.gitignore +0 -14
  74. data/lib/builderator/control/ami.rb +0 -65
  75. data/lib/builderator/control/clean.rb +0 -130
  76. data/lib/builderator/model.rb +0 -46
  77. data/lib/builderator/model/images.rb +0 -89
  78. data/lib/builderator/model/instances.rb +0 -55
  79. data/lib/builderator/model/launch_configs.rb +0 -46
  80. data/lib/builderator/model/scaling_groups.rb +0 -43
  81. data/lib/builderator/model/snapshots.rb +0 -49
  82. data/lib/builderator/model/volumes.rb +0 -48
  83. data/lib/builderator/tasks/ami.rb +0 -47
  84. data/lib/builderator/tasks/berks.rb +0 -68
  85. data/lib/builderator/tasks/clean.rb +0 -97
  86. data/lib/builderator/util/berkshim.rb +0 -34
  87. data/lib/builderator/util/cookbook.rb +0 -87
  88. data/lib/builderator/util/packer.rb +0 -39
  89. 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
@@ -1,5 +1,7 @@
1
+ require_relative './util'
2
+
3
+ # :nodoc:
1
4
  module Builderator
2
- PATH = File.expand_path('../../..', __FILE__)
3
- VERSION = IO.read(File.join(PATH, 'VERSION')) rescue '0.0.1'
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