ec2launcher 1.0.10 → 1.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,67 @@
1
+ #
2
+ # Copyright (c) 2012 Sean Laurent
3
+ #
4
+
5
+ module EC2Launcher
6
+ module DSL
7
+ module EmailNotifications
8
+ attr_reader :email_notifications
9
+
10
+ def email_notification(&block)
11
+ notifications = EC2Launcher::DSL::EmailNotification.new
12
+ notifications.instance_exec(&block)
13
+ @email_notifications = notifications
14
+ end
15
+ end
16
+
17
+ class EmailNotification
18
+ def initialize()
19
+ end
20
+
21
+ def from(*from)
22
+ if from.empty?
23
+ @from
24
+ else
25
+ @from = from[0]
26
+ self
27
+ end
28
+ end
29
+
30
+ def to(*to)
31
+ if to.empty?
32
+ @to
33
+ else
34
+ @to = to[0]
35
+ self
36
+ end
37
+ end
38
+
39
+ def ses_access_key(*ses_access_key)
40
+ if ses_access_key.empty?
41
+ @ses_access_key
42
+ else
43
+ @ses_access_key = ses_access_key[0]
44
+ self
45
+ end
46
+ end
47
+
48
+ def ses_secret_key(*ses_secret_key)
49
+ if ses_secret_key.empty?
50
+ @ses_secret_key
51
+ else
52
+ @ses_secret_key = ses_secret_key[0]
53
+ self
54
+ end
55
+ end
56
+
57
+ def to_json(*a)
58
+ {
59
+ "from" => @from,
60
+ "to" => @to,
61
+ "ses_access_key" => @ses_access_key,
62
+ "ses_secret_key" => @ses_secret_key
63
+ }.to_json(*a)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,221 @@
1
+ #
2
+ # Copyright (c) 2012 Sean Laurent
3
+ #
4
+ require 'ec2launcher/dsl/email_notification'
5
+ require 'ec2launcher/security_group_handler'
6
+
7
+ module EC2Launcher
8
+ module DSL
9
+ class Environment
10
+ include EC2Launcher::DSL::EmailNotifications
11
+ include EC2Launcher::SecurityGroupHandler
12
+
13
+ attr_reader :name
14
+ attr_reader :precommands
15
+ attr_reader :postcommands
16
+
17
+ def initialize()
18
+ @aliases = []
19
+ @email_notifications = nil
20
+ @gems = []
21
+ @packages = []
22
+ @precommands = []
23
+ @postcommands = []
24
+ @roles = []
25
+ @security_groups = {}
26
+ end
27
+
28
+ def environment(name)
29
+ @name = name
30
+ yield self
31
+ self
32
+ end
33
+
34
+ def aws_keyfile(*aws_keyfile)
35
+ if aws_keyfile.empty?
36
+ @aws_keyfile
37
+ else
38
+ @aws_keyfile = aws_keyfile[0]
39
+ self
40
+ end
41
+ end
42
+
43
+ def aliases(*aliases)
44
+ if aliases.empty?
45
+ @aliases
46
+ else
47
+ if aliases[0].kind_of? String
48
+ @aliases = [ aliases[0] ]
49
+ else
50
+ @aliases = aliases[0]
51
+ end
52
+ end
53
+ end
54
+
55
+ def ami_name(*ami_name)
56
+ if ami_name.empty?
57
+ @ami_name
58
+ else
59
+ if ami_name[0].kind_of? String
60
+ @ami_name = /#{ami_name[0]}/
61
+ else
62
+ @ami_name = ami_name[0]
63
+ end
64
+ self
65
+ end
66
+ end
67
+
68
+ def availability_zone(*zone)
69
+ if zone.empty?
70
+ @availability_zone
71
+ else
72
+ @availability_zone = zone[0].to_s
73
+ self
74
+ end
75
+ end
76
+
77
+ def chef_server_url(*server_url)
78
+ if server_url.empty?
79
+ @chef_server_url
80
+ else
81
+ @chef_server_url = server_url[0]
82
+ self
83
+ end
84
+ end
85
+
86
+ def chef_validation_pem_url(*chef_validation_pem_url)
87
+ if chef_validation_pem_url.empty?
88
+ @chef_validation_pem_url
89
+ else
90
+ @chef_validation_pem_url = chef_validation_pem_url[0]
91
+ self
92
+ end
93
+ end
94
+
95
+ def domain_name(*domain_name)
96
+ if domain_name.empty?
97
+ @domain_name
98
+ else
99
+ @domain_name = domain_name[0]
100
+ self
101
+ end
102
+ end
103
+
104
+ def gems(*gems)
105
+ if gems.empty?
106
+ @gems
107
+ else
108
+ @gems = gems[0]
109
+ self
110
+ end
111
+ end
112
+
113
+ def inherit(*inherit_type)
114
+ if inherit_type.empty?
115
+ @inherit_type
116
+ else
117
+ @inherit_type = inherit_type[0]
118
+ end
119
+ end
120
+
121
+ def key_name(*key)
122
+ if key.empty?
123
+ @key_name
124
+ else
125
+ @key_name = key[0]
126
+ self
127
+ end
128
+ end
129
+
130
+ def packages(*packages)
131
+ if packages.empty?
132
+ @packages
133
+ else
134
+ @packages = packages[0]
135
+ self
136
+ end
137
+ end
138
+
139
+ def precommand(*command)
140
+ @precommands << command[0]
141
+ end
142
+
143
+ def postcommand(*command)
144
+ @postcommands << command[0]
145
+ end
146
+
147
+ def roles(*roles)
148
+ if roles.empty?
149
+ @roles
150
+ else
151
+ @roles = [] if @roles.nil?
152
+ if roles[0].kind_of? Array
153
+ @roles += roles[0]
154
+ else
155
+ @roles = []
156
+ @roles << roles[0]
157
+ end
158
+ self
159
+ end
160
+ end
161
+
162
+ def short_name(*short_name)
163
+ if short_name.empty?
164
+ @short_name
165
+ else
166
+ @short_name = short_name[0]
167
+ self
168
+ end
169
+ end
170
+
171
+ def subnet(*subnet)
172
+ if subnet.empty?
173
+ @subnet
174
+ else
175
+ @subnet = subnet[0]
176
+ self
177
+ end
178
+ end
179
+
180
+ # Takes values from the other environment and merges them into this one
181
+ def merge(other_env)
182
+ @name =other_env.name
183
+
184
+ @gems += other_env.gems unless other_env.gems.nil?
185
+ @packages += other_env.packages unless other_env.packages.nil?
186
+ @roles += other_env.roles unless other_env.roles.nil?
187
+ @precommands += other_env.precommands unless other_env.precommands.nil?
188
+ @postcommands += other_env.postcommands unless other_env.postcommands.nil?
189
+ unless other_env.security_groups.nil?
190
+ other_env.security_groups.keys.each do |key|
191
+ @security_groups[key] = [] if @security_groups[key].nil?
192
+ @security_groups[key] += other_env.security_groups[key]
193
+ end
194
+ end
195
+
196
+ @aliases = other_env.aliases.nil? ? nil : other_env.aliases
197
+
198
+ @ami_name = other_env.ami_name unless other_env.ami_name.nil?
199
+ @aws_keyfile = other_env.aws_keyfile unless other_env.aws_keyfile.nil?
200
+ @availability_zone = other_env.availability_zone unless other_env.availability_zone.nil?
201
+ @chef_server_url = other_env.chef_server_url unless other_env.chef_server_url.nil?
202
+ @chef_validation_pem_url = other_env.chef_validation_pem_url unless other_env.chef_validation_pem_url.nil?
203
+ @domain_name = other_env.domain_name unless other_env.domain_name.nil?
204
+ @email_notifications = other_env.email_notifications unless other_env.email_notifications.nil?
205
+ @key_name = other_env.key_name unless other_env.key_name.nil?
206
+ @subnet = other_env.subnet unless other_env.subnet.nil?
207
+ @short_name = other_env.short_name unless other_env.short_name.nil?
208
+ end
209
+
210
+ def load(dsl)
211
+ self.instance_eval(dsl)
212
+ self
213
+ end
214
+
215
+ def self.load(dsl)
216
+ env = EC2Launcher::DSL::Environment.new.instance_eval(dsl)
217
+ env
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,117 @@
1
+ #
2
+ # Copyright (c) 2012 Sean Laurent
3
+ #
4
+ require 'rubygems'
5
+ require 'aws-sdk'
6
+
7
+ module EC2Launcher
8
+ # Helper class to generate sequential, numbered host names
9
+ class HostnameGenerator
10
+ #
11
+ # @param [AWS::EC2] ec2 EC2 object used to query for existing instances
12
+ # @param [EC2Launcher::Environment] environment Environment to use for generating host names
13
+ # @param [EC2Launcher::Application] application Application to use for generating hostn ames
14
+ def initialize(ec2, environment, application)
15
+ @ec2 = ec2
16
+ @server_name_cache = nil
17
+
18
+ @prefix = application.basename
19
+ @prefix ||= application.name
20
+
21
+ @env_suffix = environment.short_name
22
+ @env_suffix ||= environment.name
23
+
24
+ @suffix = @env_suffix
25
+ unless application.name_suffix.nil?
26
+ @suffix = "#{application.name_suffix}.#{@env_suffix}"
27
+ end
28
+
29
+ @host_number_regex = Regexp.new("#{@prefix}(\\d+)[.]#{@suffix.gsub(/[.]/, "[.]")}.*")
30
+
31
+ # Load and cache instance names
32
+ load_instances(@prefix, @suffix)
33
+ end
34
+
35
+ # Generates a new host name and automatically caches it
36
+ # so that future requests don't use the same name.
37
+ def generate_hostname()
38
+ # Find next host number
39
+ host_number = get_next_host_number()
40
+
41
+ # Build short host name
42
+ short_name = "#{@prefix}#{host_number}.#{@suffix}"
43
+
44
+ # Cache the new hostname
45
+ @server_name_cache << short_name
46
+
47
+ short_name
48
+ end
49
+
50
+ def generate_long_name(short_hostname, domain_name = nil)
51
+ hostname = short_hostname
52
+ unless domain_name.nil?
53
+ hostname += ".#{domain_name}"
54
+ end
55
+
56
+ hostname
57
+ end
58
+
59
+ def generate_short_name(long_name, domain_name = nil)
60
+ short_hostname = long_name
61
+ unless domain_name.nil?
62
+ short_hostname = long_name.gsub(/.#{domain_name}/, '')
63
+ end
64
+ short_hostname
65
+ end
66
+
67
+ private
68
+
69
+ # Loads and caches instance host names
70
+ def load_instances(prefix, suffix)
71
+ @server_name_cache = []
72
+ AWS.memoize do
73
+ server_instances = @ec2.instances.filter("tag:Name", "#{prefix}*#{suffix}*")
74
+ server_instances.each do |i|
75
+ next if i.status == :terminated
76
+ @server_name_cache << i.tags[:Name]
77
+ end
78
+ end
79
+ end
80
+
81
+ # Determines the next available number for a host name
82
+ def get_next_host_number()
83
+ highest_server_number = 0
84
+ lowest_server_number = 32768
85
+
86
+ server_numbers = []
87
+
88
+ @server_name_cache.each do |server_name|
89
+ unless @host_number_regex.match(server_name).nil?
90
+ server_num = $1.to_i
91
+ server_numbers << server_num
92
+ end
93
+ end
94
+ highest_server_number = server_numbers.max
95
+
96
+ # If the highest number server is less than 10, just add
97
+ # 1 to it. Otherwise, find the first available
98
+ # server number starting at 1.
99
+ host_number = 0
100
+ if highest_server_number.nil?
101
+ host_number = 1
102
+ elsif highest_server_number < 10
103
+ host_number = highest_server_number + 1
104
+ else
105
+ # Try to start over with 1 and find the
106
+ # first available host number
107
+ server_number_set = Set.new(server_numbers)
108
+ host_number = 1
109
+ while server_number_set.include?(host_number) do
110
+ host_number += 1
111
+ end
112
+ end
113
+
114
+ host_number
115
+ end
116
+ end
117
+ end
@@ -51,26 +51,30 @@ module EC2Launcher
51
51
  opts.separator ""
52
52
  opts.separator "Additional launch options:"
53
53
 
54
- opts.on("--command [CMD]", "Additional command to run during launch sequence.") do |command|
54
+ opts.on("--command [CMD]", String, "Additional command to run during launch sequence.") do |command|
55
55
  @options.commands << command
56
56
  end
57
57
 
58
- opts.on("-c", "--clone HOST", "Clone the latest snapshots from a specific host.") do |clone_host|
58
+ opts.on("--clone HOST", String, "Clone the latest snapshots from a specific host.") do |clone_host|
59
59
  @options.clone_host = clone_host
60
60
  end
61
61
 
62
+ opts.on("-c", "--count COUNT", Integer, "Number of new instances to launch.") do |count|
63
+ @options.count = count
64
+ end
65
+
62
66
  opts.separator ""
63
67
  opts.separator "Overrides:"
64
68
 
65
- opts.on("-d", "--directory DIRECTORY", "Location of configuration directory. Defaults to current directory.") do |directory|
69
+ opts.on("-d", "--directory DIRECTORY", String, "Location of configuration directory. Defaults to current directory.") do |directory|
66
70
  @options.directory = directory
67
71
  end
68
72
 
69
- opts.on("-h", "--hostname NAME", "The name for the new server.") do |hostname|
73
+ opts.on("-h", "--hostname NAME", String, "The name for the new server.") do |hostname|
70
74
  @options.hostname = hostname
71
75
  end
72
76
 
73
- opts.on("-u", "--chef-validation-url", "URL for the Chef validation pem file.") do |chef_validation_url|
77
+ opts.on("-u", "--chef-validation-url", String, "URL for the Chef validation pem file.") do |chef_validation_url|
74
78
  @options.chef_validation_url = chef_validation_url
75
79
  end
76
80
 
@@ -93,11 +97,11 @@ module EC2Launcher
93
97
  opts.separator ""
94
98
  opts.separator "AWS Security Options:"
95
99
 
96
- opts.on("--access-key KEY", "Amazon access key. Overrides AWS_ACCESS_KEY environment variable.") do |access_key|
100
+ opts.on("--access-key KEY", String, "Amazon access key. Overrides AWS_ACCESS_KEY environment variable.") do |access_key|
97
101
  @options.access_key = access_key
98
102
  end
99
103
 
100
- opts.on("--secret SECRET", "Amazon secret access key. Overrides AWS_SECRET_ACCESS_KEY environment variable.") do |secret|
104
+ opts.on("--secret SECRET", String, "Amazon secret access key. Overrides AWS_SECRET_ACCESS_KEY environment variable.") do |secret|
101
105
  @options.secret = secret
102
106
  end
103
107
 
@@ -130,6 +134,7 @@ module EC2Launcher
130
134
  @options.application = nil
131
135
  @options.commands = []
132
136
  @options.clone_host = nil
137
+ @options.count = 1
133
138
 
134
139
  @options.ami_id = nil
135
140
  @options.hostname = nil
@@ -156,6 +161,12 @@ module EC2Launcher
156
161
  help
157
162
  exit 1
158
163
  end
164
+
165
+ if ! @options.hostname.nil? && @options.count > 1
166
+ puts "Cannot specify both a hostname ['#{@options.hostname}'] and multiple instances [#{@options.count}]."
167
+ puts
168
+ exit 1
169
+ end
159
170
  end
160
171
 
161
172
  @options
@@ -2,5 +2,5 @@
2
2
  # Copyright (c) 2012 Sean Laurent
3
3
  #
4
4
  module Ec2launcher
5
- VERSION = "1.0.10"
5
+ VERSION = "1.0.11"
6
6
  end