builderator 0.3.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -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