builderator 0.3.10

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.
@@ -0,0 +1,89 @@
1
+ require 'aws-sdk'
2
+ require_relative '../util'
3
+
4
+ module Builderator
5
+ module Model
6
+
7
+ def self.images
8
+ @images ||= Images.new
9
+ end
10
+
11
+ ##
12
+ # EC2 AMI Resources
13
+ ##
14
+ class Images < Model::Base
15
+ LIMIT = 24
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(options = {})
49
+ {}.tap do |latest|
50
+ ## Group images
51
+ group_by = options.fetch('group-by', [])
52
+ groups = {}.tap do |g|
53
+ break { 'all' => resources.values } if group_by.empty?
54
+
55
+ resources.each do |_, image|
56
+ (g[group_by.map do |gg|
57
+ image[:properties].fetch(gg.to_s, '(unknown)')
58
+ end.join(':')] ||= []) << image
59
+ end
60
+ end
61
+
62
+ ## Sort each grouping
63
+ sort_by = options.fetch('sort-by', 'creation_date')
64
+ groups.each do |_, group|
65
+ group.sort! { |a, b| b[:properties][sort_by] <=> a[:properties][sort_by] }
66
+ end
67
+
68
+ ## Slice to `keep` length
69
+ keep = options.fetch('keep', 5)
70
+ groups.each do |_, group|
71
+ group.slice!(keep..-1)
72
+ end
73
+
74
+ ## Reduce
75
+ groups.values.flatten.each { |i| latest[i[:id]] = i }
76
+ end
77
+ end
78
+
79
+ def in_use(options = {})
80
+ {}.tap do |used|
81
+ used.merge!(select(Model.instances.images))
82
+ used.merge!(select(Model.launch_configs.images))
83
+ used.merge!(latest(options))
84
+ used.merge!(select(used.values.map { |i| i[:parent] }))
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,55 @@
1
+ require 'aws-sdk'
2
+ require_relative '../util'
3
+
4
+ module Builderator
5
+ module Model
6
+
7
+ def self.instances
8
+ @instances ||= Instances.new
9
+ end
10
+ ##
11
+ # EC2 Instance resources
12
+ ##
13
+ class Instances < Model::Base
14
+ PROPERTIES = %w(private_dns_name public_dns_name instance_type
15
+ subnet_id vpc_id private_ip_address public_ip_address
16
+ architecture root_device_type virtualization_type
17
+ hypervisor)
18
+
19
+ def fetch
20
+ @resources = {}.tap do |i|
21
+ Util.ec2.describe_instances(:filters => [
22
+ {
23
+ :name => 'instance-state-name',
24
+ :values => %w(pending running shutting-down stopping stopped)
25
+ }
26
+ ]).each do |page|
27
+ page.reservations.each do |r|
28
+ r.instances.each do |instance|
29
+ properties = Util.from_tags(instance.tags)
30
+ properties['availability_zone'] = instance.placement.availability_zone
31
+ properties['creation_date'] = instance.launch_time.to_datetime
32
+ PROPERTIES.each { |pp| properties[pp] = instance[pp.to_sym] }
33
+
34
+ i[instance.instance_id] = {
35
+ :id => instance.instance_id,
36
+ :image => instance.image_id,
37
+ :volumes => instance.block_device_mappings.map { |b| b.ebs.volume_id },
38
+ :properties => properties
39
+ }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ def images
47
+ resources.values.map { |i| i[:image] }
48
+ end
49
+
50
+ def volumes
51
+ resources.values.map { |i| i[:volumes] }.flatten
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,46 @@
1
+ require 'aws-sdk'
2
+ require_relative '../util'
3
+
4
+ module Builderator
5
+ module Model
6
+
7
+ def self.launch_configs
8
+ @launch_configs ||= LaunchConfigs.new
9
+ end
10
+
11
+ ##
12
+ # ASG LaunchConfiguration Resources
13
+ ##
14
+ class LaunchConfigs < Model::Base
15
+ LIMIT = 24
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(Model.scaling_groups.launch_configs)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,43 @@
1
+ require 'aws-sdk'
2
+ require_relative '../util'
3
+
4
+ module Builderator
5
+ module Model
6
+
7
+ def self.scaling_groups
8
+ @scaling_groups ||= ScalingGroups.new
9
+ end
10
+
11
+ ##
12
+ # AutoScaling Group Resoruces
13
+ ##
14
+ class ScalingGroups < Model::Base
15
+ attr_reader :resources
16
+ PROPERTIES = %w(auto_scaling_group_arn min_size max_size desired_capacity
17
+ default_cooldown availability_zones load_balancer_names
18
+ vpc_zone_identifier status termination_policies)
19
+
20
+ def fetch
21
+ @resources = {}.tap do |i|
22
+ Util.asg.describe_auto_scaling_groups.each do |page|
23
+ page.auto_scaling_groups.each do |a|
24
+ properties = Util.from_tags(a.tags)
25
+ properties['creation_date'] = a.created_time.to_datetime
26
+ PROPERTIES.each { |pp| properties[pp] = a[pp.to_sym] }
27
+
28
+ i[a.launch_configuration_name] = {
29
+ :id => a.auto_scaling_group_name,
30
+ :properties => properties,
31
+ :config => a.launch_configuration_name
32
+ }
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def launch_configs
39
+ resources.values.map { |g| g[:config] }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,49 @@
1
+ require 'aws-sdk'
2
+ require_relative '../util'
3
+
4
+ module Builderator
5
+ module Model
6
+
7
+ def self.snapshots
8
+ @snapshots ||= Snapshots.new
9
+ end
10
+
11
+ ##
12
+ # EC2 Snapshot Resources
13
+ ##
14
+ class Snapshots < Model::Base
15
+ LIMIT = 24
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(Model.volumes.snapshots))
44
+ used.merge!(select(Model.images.snapshots))
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,48 @@
1
+ require 'aws-sdk'
2
+ require_relative '../util'
3
+
4
+ module Builderator
5
+ module Model
6
+
7
+ def self.volumes
8
+ @volumes ||= Volumes.new
9
+ end
10
+
11
+ ##
12
+ # EC2 Volume Resources
13
+ ##
14
+ class Volumes < Model::Base
15
+ LIMIT = 8
16
+ PROPERTIES = %w(size availability_zone state volume_type iops)
17
+
18
+ def fetch
19
+ @resources = {}.tap do |v|
20
+ Util.ec2.describe_volumes.each do |page|
21
+ page.volumes.each do |vol|
22
+ properties = Util.from_tags(vol.tags)
23
+ properties['creation_date'] = vol.create_time.to_datetime
24
+ PROPERTIES.each { |pp| properties[pp] = vol[pp.to_sym] }
25
+
26
+
27
+ v[vol.volume_id] = {
28
+ :id => vol.volume_id,
29
+ :properties => properties,
30
+ :snapshot => vol.snapshot_id
31
+ }
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ def snapshots
38
+ resources.values.map { |v| v[:snapshot] }
39
+ end
40
+
41
+ def in_use(_)
42
+ {}.tap do |used|
43
+ used.merge!(select(Model.instances.volumes))
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,37 @@
1
+ require 'thor'
2
+ require_relative './tasks/ami'
3
+ require_relative './tasks/berks'
4
+ require_relative './tasks/clean'
5
+ require_relative './tasks/cookbook'
6
+ require_relative './tasks/packer'
7
+ require_relative './tasks/vagrant'
8
+
9
+ module Builderator
10
+ module Tasks
11
+ class CLI < Thor
12
+ desc 'ami SUBCOMMAND', 'Search for AMI IDs'
13
+ subcommand 'ami', Builderator::Tasks::AMI
14
+
15
+ desc 'berks SUBCOMMAND', 'Berkshelf helpers'
16
+ subcommand 'berks', Builderator::Tasks::Berks
17
+
18
+ desc 'clean SUBCOMMAND', 'Clean up things'
19
+ subcommand 'clean', Builderator::Tasks::Clean
20
+
21
+ desc 'cookbook SUBCOMMAND', 'Cookbook tasks'
22
+ subcommand 'cookbook', Builderator::Tasks::Cookbook
23
+
24
+
25
+ desc 'packer SUBCOMMAND', 'Run Packer tasks'
26
+ subcommand 'packer', Builderator::Tasks::Packer
27
+
28
+ desc 'vagrant SUBCOMMAND', 'Run Vagrant tasks'
29
+ subcommand 'vagrant', Builderator::Tasks::Vagrant
30
+
31
+ desc 'version', 'Print gem version'
32
+ def version
33
+ puts Builderator::VERSION
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ require 'thor'
2
+ require_relative '../control/ami'
3
+
4
+ module Builderator
5
+ module Tasks
6
+ class AMI < Thor
7
+ namespace :ami
8
+
9
+ class_option :root_device_type,
10
+ :default => 'ebs',
11
+ :desc => 'The type of the root device volume (ebs | instance-store)'
12
+ class_option :virtualization_type,
13
+ :default => 'hvm',
14
+ :desc => 'The virtualization type (paravirtual | hvm)'
15
+ class_option :architecture,
16
+ :default => 'x86_64',
17
+ :desc => 'The image architecture (i386 | x86_64)'
18
+
19
+ desc 'ubuntu SEARCH', 'Print the latest AMI ID for an Ubuntu image matching the SEARCH string'
20
+ def ubuntu(search = '*/hvm-ssd/ubuntu-trusty-daily-amd64-server-20*')
21
+ puts Control::AMI.latest(:owner => Builderator::Control::AMI::Owners::UBUNTU,
22
+ 'root-device-type' => options['root_device_type'],
23
+ 'virtualization-type' => options['virtualization_type'],
24
+ 'architecture' => options['architecture'],
25
+ 'name' => search).image_id
26
+ end
27
+
28
+ desc 'private [KEY VALUE ...]', 'Find the latest AMI ID with tags KEY=VALUE'
29
+ def private(*args)
30
+ puts Control::AMI.latest({ :owner => Builderator::Control::AMI::Owners::SELF,
31
+ 'root-device-type' => options['root_device_type'],
32
+ 'virtualization-type' => options['virtualization_type'],
33
+ 'architecture' => options['architecture'] }.merge(Hash[*args])).image_id
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,68 @@
1
+ require 'thor'
2
+ require 'thor/actions'
3
+ require_relative './cookbook'
4
+ require_relative '../util/cookbook'
5
+
6
+ module Builderator
7
+ module Tasks
8
+ class Berks < Thor
9
+ include Thor::Actions
10
+ class_option :config, :aliases => :c, :desc => "Path to Berkshelf's config.json"
11
+ class_option :cookbook, :aliases => :b, :desc => 'Path to the cookbook to use'
12
+ class_option :version, :type => :boolean,
13
+ :default => true,
14
+ :desc => 'Write current verison to file'
15
+
16
+ desc "local [PATH = #{ Util::Cookbook::DEFAULT_VENDOR }]", 'Vendor the local cookbook source and its dependencies'
17
+ def local(path = Util::Cookbook::DEFAULT_VENDOR)
18
+ Util::Cookbook.path(options['cookbook'])
19
+
20
+ command = 'BERKS_INSTALL_FROM=source'
21
+ command << " berks vendor #{ path }"
22
+ command << " -c #{ options['config'] }" if options.include?('config')
23
+ command << " -b #{ Util::Cookbook.berksfile }"
24
+
25
+ remove_file File.expand_path('Berksfile.lock', Util::Cookbook.path)
26
+ invoke Tasks::Cookbook, 'metadata', [], options
27
+ run command
28
+ end
29
+
30
+ desc "vendor [PATH = #{ Util::Cookbook::DEFAULT_VENDOR }]", 'Vendor a cookbook release and its dependencies'
31
+ def vendor(path = Util::Cookbook::DEFAULT_VENDOR)
32
+ Util::Cookbook.path(options['cookbook'])
33
+
34
+ command = 'BERKS_INSTALL_FROM=release'
35
+ command << " berks vendor #{ path }"
36
+ command << " -c #{ options['config'] }" if options.include?('config')
37
+ command << " -b #{ Util::Cookbook.berksfile }"
38
+
39
+ remove_file File.expand_path('Berksfile.lock', Util::Cookbook.path)
40
+ run command
41
+ end
42
+
43
+ desc 'upload', 'Upload the local cookbook source and its dependencies to the Chef server'
44
+ option 'dry-run', :type => :boolean, :default => false
45
+ def upload(path = Util::Cookbook::DEFAULT_VENDOR)
46
+ command = 'BERKS_INSTALL_FROM=source'
47
+ command << " berks upload"
48
+ command << " -c #{ options['config'] }" if options.include?('config')
49
+ command << " -b #{ Util::Cookbook.berksfile }"
50
+
51
+ invoke Tasks::Berks, :local, [path], options
52
+
53
+ return say_status :dryrun, command if options['dry-run']
54
+ run command
55
+ end
56
+
57
+ desc 'uncache', 'Delete the Berkshelf cache'
58
+ def uncache
59
+ remove_dir File.join(ENV['HOME'], '.berkshelf/cookbooks')
60
+ end
61
+
62
+ desc "clean [PATH = #{ Util::Cookbook::DEFAULT_VENDOR }]", 'Remove a local vendor directory'
63
+ def clean(path = Util::Cookbook::DEFAULT_VENDOR)
64
+ remove_dir path
65
+ end
66
+ end
67
+ end
68
+ end