awsome 0.0.0

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.
data/bin/awsome ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'awsome'
4
+ require 'optparse'
5
+
6
+ requirements_file = 'requirements.yml'
7
+ OptionParser.new do |opts|
8
+ opts.banner = 'Usage: awsome [options]'
9
+ opts.on('-r', '--requirements [FILE]', 'Use a requirements file from another location (default is ./requirements.yml)') do |opt|
10
+ requirements_file = opt
11
+ end
12
+ opts.on('-v', '--verbose', 'Print commands as they are executed') do |opt|
13
+ Awsome.config.verbose = true
14
+ end
15
+ opts.on('-d', '--debug', 'Run ec2 commands with --debug') do |opt|
16
+ Awsome.config.debug = true
17
+ end
18
+ opts.on('-s', '--stacks', 'Print out full stack traces when commands are executed') do |opt|
19
+ Awsome.config.stacks = true
20
+ end
21
+ end.parse!
22
+
23
+ instances = Awsome::Ec2.describe_instances('instance-state-name' => 'running')
24
+ requirements = Awsome::Requirements.from_yaml_file(requirements_file)
25
+ matchmaker = Awsome::Matchmaker.new(instances, requirements)
26
+ executor = Awsome::Executor.new(matchmaker.matches)
27
+
28
+ executor.execute
data/lib/awsome.rb ADDED
@@ -0,0 +1,81 @@
1
+ module Awsome
2
+ def self.config
3
+ @@config ||= Config.new
4
+ end
5
+
6
+ def self.execute(command, options={})
7
+ command = command.join(' ') if command.is_a?(Array)
8
+ if config.verbose
9
+ puts
10
+ puts command
11
+ puts '='*command.length
12
+ end
13
+ if options[:system]
14
+ result = system(command)
15
+ else
16
+ result = `#{command}`
17
+ result = options[:preprocess].call(result) if options[:preprocess]
18
+ result = map_table(result, options)
19
+ end
20
+ ensure
21
+ if config.verbose
22
+ case result
23
+ when String then puts result
24
+ else ap result
25
+ end
26
+ end
27
+ if config.stacks
28
+ ap Kernel.caller
29
+ end
30
+ end
31
+
32
+ def self.map_table(table, options)
33
+ return table unless options[:columns]
34
+ rows = table.split("\n")
35
+ rows.select! { |row| row =~ options[:filter] } if options[:filter]
36
+ rows.collect do |row|
37
+ properties = {}
38
+ values = options[:delimiter] ? row.split(options[:delimiter]) : row.split
39
+ values.each_with_index { |value, index|
40
+ field = options[:columns][index]
41
+ properties[field] = value
42
+ }
43
+ properties
44
+ end
45
+ end
46
+
47
+ def self.wait_until(opts={}, &block)
48
+ retries = opts[:retries] || 5
49
+ interval = opts[:interval] || 5
50
+ while !yield && retries > 0
51
+ puts "block returned false (#{retries} more retries)..." if Awsome.config.verbose
52
+ sleep interval
53
+ retries -= 1
54
+ end
55
+ end
56
+
57
+ class Config
58
+ attr_accessor :region, :url, :aws_access_key, :aws_secret_key, :connection_timeout,
59
+ :request_timeout, :verbose, :show_empty_fields, :debug, :show_request, :stacks
60
+
61
+ def initialize
62
+ @region = ENV['REGION']
63
+ @url = ENV['EC2_URL']
64
+ @aws_access_key = ENV['AWS_ACCESS_KEY']
65
+ @aws_secret_key = ENV['AWS_SECRET_KEY']
66
+ @show_empty_fields = true
67
+ end
68
+ end
69
+ end
70
+
71
+ require 'set'
72
+ require 'awesome_print'
73
+ require 'awsome/ec2.rb'
74
+ require 'awsome/elb.rb'
75
+ require 'awsome/ssh.rb'
76
+ require 'awsome/debian.rb'
77
+ require 'awsome/requirements.rb'
78
+ require 'awsome/executor.rb'
79
+ require 'awsome/matchmaker.rb'
80
+ require 'awsome/requirements_options.rb'
81
+ require 'awsome/instance_requirement.rb'
@@ -0,0 +1,36 @@
1
+ module Awsome
2
+ module Debian
3
+ def self.describe_debian_packages(hostname)
4
+ if Awsome::Ssh.scp("#{hostname}:/home/ubuntu/packages.csv", './packages.csv')
5
+ File.open('./packages.csv', 'r').read.strip.split(',')
6
+ else
7
+ []
8
+ end
9
+ end
10
+
11
+ def self.remove_debian_packages(hostname, *packages)
12
+ installed = describe_debian_packages(hostname)
13
+ remaining = installed.to_set - packages.to_set
14
+
15
+ return if packages.empty?
16
+
17
+ Awsome::Ssh.ssh hostname, "sudo apt-get update"
18
+ Awsome::Ssh.ssh hostname, "sudo apt-get remove -y --force-yes #{packages.join(' ')}"
19
+ Awsome::Ssh.ssh hostname, "echo #{remaining.to_a.join(',')} > ~/packages.csv"
20
+ end
21
+
22
+ def self.install_debian_packages(hostname, *packages)
23
+ installed = describe_debian_packages(hostname)
24
+ remaining = installed.to_set + packages.to_set
25
+
26
+ Awsome::Ssh.ssh hostname, "sudo apt-get update"
27
+
28
+ if packages.empty?
29
+ Awsome::Ssh.ssh hostname, "sudo apt-get upgrade"
30
+ else
31
+ Awsome::Ssh.ssh hostname, "sudo apt-get install -y --force-yes #{packages.join(' ')}"
32
+ Awsome::Ssh.ssh hostname, "echo #{remaining.to_a.join(',')} > ~/packages.csv"
33
+ end
34
+ end
35
+ end
36
+ end
data/lib/awsome/ec2.rb ADDED
@@ -0,0 +1,109 @@
1
+ module Awsome
2
+ module Ec2
3
+ def self.config
4
+ Awsome.config
5
+ end
6
+
7
+ def self.command(*cmd)
8
+ args = cmd.last.is_a?(Hash) && cmd.pop
9
+ options = cmd
10
+ options << "--region #{config.region}"
11
+ options << "--url #{config.url}"
12
+ options << "--aws-access-key #{config.aws_access_key}"
13
+ options << "--aws-secret-key #{config.aws_secret_key}"
14
+ options << "--connection-timeout #{config.connection_timeout}" if config.connection_timeout
15
+ options << "--request-timeout #{config.request_timeout}" if config.request_timeout
16
+ options << "--verbose" if config.verbose
17
+ options << "--show-empty-fields" if config.show_empty_fields
18
+ options << "--debug" if config.debug
19
+ args && args.each { |k,v| options << "--#{k} #{v}" }
20
+ options.join(' ')
21
+ end
22
+
23
+ def self.map_table(*args)
24
+ Awsome.map_table(*args)
25
+ end
26
+
27
+ @@run_instance_fields = %w(
28
+ instance_identifier
29
+ instance_id
30
+ ami_id
31
+ state
32
+ key
33
+ ami_launch_index
34
+ product_code
35
+ instance_type
36
+ instance_launch_time
37
+ availability_zone
38
+ )
39
+
40
+ def self.run_instance(properties)
41
+ cmd = command('ec2-run-instances', properties['ami_id'],
42
+ :group => properties['security_group_ids'],
43
+ :key => properties['key'],
44
+ 'instance-type'.to_sym => properties['instance_type'],
45
+ 'availability-zone'.to_sym => properties['availability_zone']
46
+ )
47
+ Awsome::Ec2::Instance.new(Awsome.execute(cmd, columns: @@run_instance_fields, filter: /^INSTANCE/).first)
48
+ end
49
+
50
+ @@describe_instance_fields = %w(
51
+ reservation_identifier
52
+ reservation_id
53
+ aws_account_id
54
+ security_group_ids
55
+ instance_identifier
56
+ instance_id
57
+ ami_id
58
+ public_dns_name
59
+ private_dns_name
60
+ state
61
+ key
62
+ ami_launch_index
63
+ product_codes
64
+ instance_type
65
+ instance_launch_time
66
+ availability_zone
67
+ )
68
+
69
+ def self.describe_instances(filters={})
70
+ cmd = [Awsome::Ec2.command('ec2-describe-instances')]
71
+ cmd += filters.collect { |k,v| "--filter \"#{k}=#{v}\"" }
72
+ preprocess = Proc.new { |text| text.gsub("\nINSTANCE", " INSTANCE") }
73
+ properties = Awsome.execute(cmd, columns: @@describe_instance_fields, filter: /^RESERVATION/, preprocess: preprocess)
74
+ properties.collect { |p| Awsome::Ec2::Instance.new(p) }
75
+ end
76
+
77
+ @@describe_volumes_fields = %w(
78
+ attachment_identifier
79
+ volume_id
80
+ instance_id
81
+ device
82
+ state
83
+ date
84
+ )
85
+
86
+ def self.describe_volumes(filters={})
87
+ cmd = [Awsome::Ec2.command('ec2-describe-volumes')]
88
+ cmd += filters.collect { |k,v| "--filter \"#{k}=#{v}\"" }
89
+ Awsome.execute(cmd, columns: @@describe_volumes_fields, filter: /^ATTACHMENT/)
90
+ end
91
+
92
+ def self.detach_volume(volume_id)
93
+ cmd = Awsome::Ec2.command('ec2-detach-volume', volume_id)
94
+ Awsome.execute(cmd)
95
+ end
96
+
97
+ def self.attach_volume(volume_id, instance_id, device)
98
+ cmd = Awsome::Ec2.command('ec2-attach-volume', volume_id, instance: instance_id, device: device)
99
+ Awsome.execute(cmd)
100
+ end
101
+
102
+ def self.terminate_instances(*instance_ids)
103
+ cmd = Awsome::Ec2.command("ec2-terminate-instances #{instance_ids.join(' ')}")
104
+ Awsome.execute(cmd)
105
+ end
106
+ end
107
+ end
108
+
109
+ require 'awsome/ec2/instance.rb'
@@ -0,0 +1,76 @@
1
+ module Awsome
2
+ module Ec2
3
+ class Instance
4
+ attr_reader :properties
5
+
6
+ def initialize(property_hash)
7
+ raise 'properties must be a hash' unless property_hash.is_a?(Hash)
8
+ @properties = property_hash.clone
9
+ end
10
+
11
+ def packages
12
+ Awsome::Debian.describe_debian_packages(@properties['public_dns_name']).to_set
13
+ end
14
+
15
+ def volumes
16
+ Awsome::Ec2.describe_volumes('attachment.instance-id' => @properties['instance_id']).collect do |p|
17
+ p['volume_id']
18
+ end.to_set
19
+ end
20
+
21
+ def wait_until_running!
22
+ Awsome.wait_until(interval: 10) do
23
+ reload!
24
+ @properties['state'] =~ /^running/
25
+ end
26
+ end
27
+
28
+ def wait_for_ssh!
29
+ Awsome.wait_until(interval: 10) { has_ssh? }
30
+ end
31
+
32
+ def reattach_volumes(*volumes)
33
+ volumes.each do |info|
34
+ Awsome::Ec2.detach_volume(info['id'])
35
+ Awsome::Ec2.attach_volume(info['id'], @properties['instance_id'], info['device'])
36
+ end
37
+ end
38
+
39
+ def deregister_from_elbs
40
+ elbs.each { |elb| elb.deregister(@properties['instance_id']) }
41
+ end
42
+
43
+ def register_with_elbs(*load_balancer_names)
44
+ Awsome::Elb.describe_lbs(*load_balancer_names).each { |elb| elb.register(@properties['instance_id']) }
45
+ end
46
+
47
+ def remove_packages(*packages)
48
+ Awsome::Debian.remove_debian_packages(@properties['public_dns_name'], *packages)
49
+ end
50
+
51
+ def install_packages(*packages)
52
+ Awsome::Debian.install_debian_packages(@properties['public_dns_name'], *packages)
53
+ end
54
+
55
+ def terminate
56
+ Awsome::Ec2.terminate_instances(@properties['instance_id'])
57
+ end
58
+
59
+ private
60
+ def reload!
61
+ instance = Awsome::Ec2.describe_instances('instance-id' => @properties['instance_id']).first
62
+ raise "instance #{@properties['instance_id']} not found" if instance.nil?
63
+ @properties = instance.properties.clone
64
+ end
65
+
66
+ def has_ssh?
67
+ Awsome::Ssh.has_ssh?(@properties['public_dns_name'])
68
+ end
69
+
70
+ def elbs
71
+ Awsome::Elb.describe_lbs.select { |elb| elb.instances.include?(@properties['instance_id']) }
72
+ end
73
+
74
+ end
75
+ end
76
+ end
data/lib/awsome/elb.rb ADDED
@@ -0,0 +1,66 @@
1
+ module Awsome
2
+ module Elb
3
+ @@delimiter = " OH YEAH BANANAS "
4
+
5
+ def self.config
6
+ Awsome.config
7
+ end
8
+
9
+ def self.command(*cmd)
10
+ args = cmd.last.is_a?(Hash) && cmd.pop
11
+ options = cmd
12
+ options << "--region #{config.region}"
13
+ # options << "--url #{config.url}" # explicitly setting the url this way breaks the elb tools
14
+ options << "--access-key-id #{config.aws_access_key}"
15
+ options << "--secret-key #{config.aws_secret_key}"
16
+ options << "--show-long"
17
+ options << "--delimiter \"#{@@delimiter}\""
18
+ options << "--show-request" if config.show_request
19
+ options << "--show-empty-fields" if config.show_empty_fields
20
+ options << "--connection-timeout #{config.connection_timeout}" if config.connection_timeout
21
+ args && args.each { |k,v| options << "--#{k} #{v}" }
22
+ options.join(' ')
23
+ end
24
+
25
+ @@describe_lbs_columns = %w(
26
+ identifier
27
+ name
28
+ dns_name
29
+ canonical_hosted_zone_name
30
+ canonical_hosted_zone_name_id
31
+ health_check
32
+ availability_zones
33
+ subnets
34
+ vpc_id
35
+ instance_ids
36
+ listener_descriptions
37
+ backend_server_descriptions
38
+ app_cookie_stickiness_policies
39
+ lb_cookie_stickiness_policies
40
+ other_policies
41
+ source_security_group
42
+ security_groups
43
+ created_time
44
+ scheme
45
+ pagination_marker
46
+ )
47
+
48
+ def self.describe_lbs(*load_balancer_names)
49
+ cmd = Awsome::Elb.command("elb-describe-lbs #{load_balancer_names.join(' ')}")
50
+ properties = Awsome.execute(cmd, columns: @@describe_lbs_columns, delimiter: @@delimiter)
51
+ properties.collect { |p| Awsome::Elb::LoadBalancer.new(p) }
52
+ end
53
+
54
+ def self.deregister_instance_from_lb(load_balancer_name, instance_id)
55
+ cmd = Awsome::Elb.command('elb-deregister-instances-from-lb', load_balancer_name, instances: instance_id, delimiter: @@delimiter)
56
+ Awsome.execute(cmd)
57
+ end
58
+
59
+ def self.register_instance_with_lb(load_balancer_name, instance_id)
60
+ cmd = Awsome::Elb.command('elb-register-instances-with-lb', load_balancer_name, instances: instance_id, delimiter: @@delimiter)
61
+ Awsome.execute(cmd)
62
+ end
63
+ end
64
+ end
65
+
66
+ require 'awsome/elb/load_balancer.rb'
@@ -0,0 +1,30 @@
1
+ module Awsome
2
+ module Elb
3
+ class LoadBalancer
4
+ attr_reader :properties
5
+
6
+ def initialize(property_hash)
7
+ @properties = property_hash.clone
8
+ end
9
+
10
+ def instances
11
+ @properties['instance_ids'].gsub('"', '').split(',').collect(&:strip).to_set
12
+ end
13
+
14
+ def deregister(instance_id)
15
+ Awsome::Elb.deregister_instance_from_lb(@properties['name'], instance_id)
16
+ end
17
+
18
+ def register(instance_id)
19
+ Awsome::Elb.register_instance_with_lb(@properties['name'], instance_id)
20
+ end
21
+
22
+ private
23
+ def reload!
24
+ elb = Awsome::Elb.describe_lbs(@properties['name']).first
25
+ raise "elb #{@properties['name']} not found" if elb.nil?
26
+ @properties = elb.properties.clone
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,66 @@
1
+ module Awsome
2
+ class Executor
3
+ def initialize(matches)
4
+ @matches = matches
5
+ end
6
+
7
+ def execute
8
+ @matches.each { |s, m| execute_match(s, m) }
9
+ end
10
+
11
+ private
12
+
13
+ def execute_match(signature, match)
14
+ @i_pool = match[:i_pool]
15
+ @r_pool = match[:r_pool]
16
+
17
+ puts "instance pool:"
18
+ ap @i_pool
19
+
20
+ puts "requirement pool:"
21
+ ap @r_pool
22
+
23
+ run
24
+ wait_for_ssh
25
+ reattach_volumes
26
+ deploy
27
+ terminate
28
+ end
29
+
30
+ def run
31
+ @i_pool.each_with_index do |instance, i|
32
+ @i_pool[i] = Awsome::Ec2.run_instance(@r_pool[i].properties) if instance.nil?
33
+ end
34
+ end
35
+
36
+ def wait_for_ssh
37
+ @i_pool.each do |i|
38
+ i.wait_until_running!
39
+ i.wait_for_ssh!
40
+ end
41
+ end
42
+
43
+ def reattach_volumes
44
+ @i_pool.each_with_index do |instance, i|
45
+ instance.reattach_volumes(*@r_pool[i].volumes_to_attach(instance))
46
+ end
47
+ end
48
+
49
+ def deploy
50
+ @i_pool.each_with_index do |instance, i|
51
+ instance.deregister_from_elbs
52
+ instance.remove_packages(*@r_pool[i].packages_to_remove(instance))
53
+ instance.install_packages(*@r_pool[i].packages_to_install(instance))
54
+ instance.register_with_elbs(*@r_pool[i].elbs)
55
+ end
56
+ end
57
+
58
+ def terminate
59
+ @i_pool.each_with_index do |instance, i|
60
+ next if i < @r_pool.length
61
+ instance.deregister_from_elbs
62
+ instance.terminate
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,56 @@
1
+ module Awsome
2
+ class InstanceRequirement
3
+
4
+ attr_reader :properties
5
+
6
+ def initialize(properties, options)
7
+ @properties = properties.clone
8
+ @options = options
9
+ end
10
+
11
+ def elbs
12
+ @properties['elbs']
13
+ end
14
+
15
+ def volumes_to_attach(instance)
16
+ (volumes - volumes_attached_to(instance)).collect { |v| @options.find_volume(v) }
17
+ end
18
+
19
+ def volumes_to_detach(instance)
20
+ (volumes_attached_to(instance) - volumes).collect { |v| @options.find_volume(v) }
21
+ end
22
+
23
+ def volume_change_count(instance)
24
+ volumes_to_attach(instance).size + volumes_to_detach(instance).size
25
+ end
26
+
27
+ def packages_to_install(instance)
28
+ packages - packages_installed_on(instance)
29
+ end
30
+
31
+ def packages_to_remove(instance)
32
+ packages_installed_on(instance) - packages
33
+ end
34
+
35
+ def package_change_count(instance)
36
+ packages_to_install(instance).size + packages_to_remove(instance).size
37
+ end
38
+
39
+ private
40
+ def packages
41
+ @properties['packages'].to_set
42
+ end
43
+
44
+ def volumes
45
+ @options.filter_volume_ids(@properties['volumes'])
46
+ end
47
+
48
+ def packages_installed_on(instance)
49
+ instance ? instance.packages : Set[]
50
+ end
51
+
52
+ def volumes_attached_to(instance)
53
+ instance ? @options.filter_volume_ids(instance.volumes) : Set[]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,96 @@
1
+ module Awsome
2
+ class Matchmaker
3
+ def initialize(instances, requirements)
4
+ @requirement_pools = requirements.instances.reject do |i|
5
+ requirements.options.except_instance_ids.include?(i.properties['instance_id'])
6
+ end.group_by { |i| signature_for(i) }
7
+
8
+ @instance_pools = instances.reject do |i|
9
+ requirements.options.except_instance_ids.include?(i.properties['instance_id'])
10
+ end.group_by { |i| signature_for(i) }
11
+
12
+ @signatures = @requirement_pools.keys.to_set + @instance_pools.keys.to_set
13
+
14
+ @signatures.each do |s|
15
+ @requirement_pools[s] ||= []
16
+ @instance_pools[s] ||= []
17
+
18
+ # nil indicates new instance will be brought up
19
+ shortage = @requirement_pools[s].size - @instance_pools[s].size
20
+ @instance_pools[s] += [nil]*shortage if shortage > 0
21
+ end
22
+ end
23
+
24
+ @@signature_fields = %w( ami_id key instance_type availability_zone security_group_ids )
25
+
26
+ def signature_for(instance)
27
+ @@signature_fields.collect { |k| instance.properties[k] }.join(',')
28
+ end
29
+
30
+ def matches
31
+ @signatures.reduce({}) { |memo, s| memo.merge(s => best_match(s)) }
32
+ end
33
+
34
+ private
35
+
36
+ def best_match(signature)
37
+ i_pool = @instance_pools[signature]
38
+ r_pool = @requirement_pools[signature]
39
+
40
+ best = nil
41
+
42
+ permute i_pool do |i_pool_perm|
43
+ best = score_match(i_pool_perm, r_pool, best)
44
+ end
45
+
46
+ best
47
+ end
48
+
49
+ def score_match(i_pool, r_pool, best)
50
+ v_delta = 0
51
+ p_delta = 0
52
+
53
+ i_pool.each_with_index do |i, index|
54
+ r = r_pool[index]
55
+ if r
56
+ v_delta += r.volume_change_count(i)
57
+ p_delta += r.package_change_count(i)
58
+ end
59
+ end
60
+
61
+ top_score({
62
+ v_delta: v_delta,
63
+ p_delta: p_delta,
64
+ i_pool: i_pool,
65
+ r_pool: r_pool
66
+ }, best)
67
+ end
68
+
69
+ def top_score(*scores)
70
+ scores.sort_by do |s1, s2|
71
+ case
72
+ when s1.nil? && s2.nil? then 0
73
+ when s2.nil? then -1
74
+ when s1.nil? then 1
75
+ when s1[:v_delta] < s2[:v_delta] then -1
76
+ when s1[:v_delta] > s2[:v_delta] then 1
77
+ when s1[:p_delta] < s2[:p_delta] then -1
78
+ when s1[:p_delta] > s2[:p_delta] then 1
79
+ else 0
80
+ end
81
+ end.first
82
+ end
83
+
84
+ def permute(array, permutation=[], &block)
85
+ if array.empty?
86
+ yield(permutation.clone)
87
+ else
88
+ 0.upto(array.length - 1) do |i|
89
+ permutation << array.slice!(i)
90
+ permute(array, permutation, &block)
91
+ array.insert(i, permutation.pop)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,20 @@
1
+ require 'yaml'
2
+
3
+ module Awsome
4
+ class Requirements
5
+ attr_reader :options
6
+ def initialize(requirements_hash)
7
+ @requirements = requirements_hash.clone
8
+ @options = Awsome::RequirementsOptions.new(@requirements)
9
+ end
10
+ def self.from_yaml_file(filename)
11
+ new(YAML::load(File.open(filename, 'r').read))
12
+ end
13
+ def instances
14
+ @requirements['instances'].collect do |instance_req|
15
+ Awsome::InstanceRequirement.new(instance_req, @options)
16
+ end
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,20 @@
1
+ module Awsome
2
+ class RequirementsOptions
3
+ def initialize(requirements)
4
+ @options = (requirements['options'] || {}).clone
5
+ end
6
+ def only_volume_ids
7
+ @options['volumes'].collect { |v| v['id'] }.to_set
8
+ end
9
+ def except_instance_ids
10
+ (@options['except_instance_ids'] || []).to_set
11
+ end
12
+ def filter_volume_ids(ids)
13
+ ids = ids.to_set unless ids.is_a?(Set)
14
+ only_volume_ids.any? ? only_volume_ids & ids : ids
15
+ end
16
+ def find_volume(volume_id)
17
+ @options['volumes'].find { |v| v['id'] == volume_id }
18
+ end
19
+ end
20
+ end
data/lib/awsome/ssh.rb ADDED
@@ -0,0 +1,27 @@
1
+ module Awsome
2
+ module Ssh
3
+ def self.ensure_ssh_env_vars!
4
+ raise 'SSH_KEY environment variable not set' if ENV['SSH_KEY'].nil?
5
+ raise 'SSH_USER environment varibale not set' if ENV['SSH_USER'].nil?
6
+ end
7
+
8
+ def self.ssh(host, *scripts)
9
+ ensure_ssh_env_vars!
10
+ Awsome.execute("ssh -i #{ENV['SSH_KEY']} #{ENV['SSH_USER']}@#{host} \"#{scripts.join(' && ')}\"")
11
+ end
12
+
13
+ def self.scp(from, to)
14
+ ensure_ssh_env_vars!
15
+ if File.exists?(from)
16
+ to = "#{ENV['SSH_USER']}@#{to}"
17
+ else
18
+ from = "#{ENV['SSH_USER']}@#{from}"
19
+ end
20
+ Awsome.execute("scp -i #{ENV['SSH_KEY']} #{from} #{to}", system: true)
21
+ end
22
+
23
+ def self.has_ssh?(host)
24
+ Awsome.execute("nc -zw 2 #{host} 22 < /dev/null", system: true)
25
+ end
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awsome
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sebastian Goodman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: awesome_print
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: AWS library targeted specifically for continuous integration.
31
+ email: sebastian@foodocs.com
32
+ executables:
33
+ - awsome
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - lib/awsome.rb
38
+ - lib/awsome/matchmaker.rb
39
+ - lib/awsome/elb/load_balancer.rb
40
+ - lib/awsome/requirements.rb
41
+ - lib/awsome/ec2.rb
42
+ - lib/awsome/executor.rb
43
+ - lib/awsome/ssh.rb
44
+ - lib/awsome/requirements_options.rb
45
+ - lib/awsome/elb.rb
46
+ - lib/awsome/debian.rb
47
+ - lib/awsome/ec2/instance.rb
48
+ - lib/awsome/instance_requirement.rb
49
+ - bin/awsome
50
+ homepage: http://github.com/0x0539/awsome
51
+ licenses: []
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 1.8.23
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Intelligently plan automated, incremental deployments.
74
+ test_files: []