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.
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