jzimmek-ec2-dsl 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +329 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/ec2-dsl.gemspec +51 -0
- data/lib/ec2/dsl/cloud.rb +49 -0
- data/lib/ec2/dsl/container.rb +42 -0
- data/lib/ec2/dsl/group.rb +44 -0
- data/lib/ec2/dsl/instance.rb +44 -0
- data/lib/ec2-dsl.rb +10 -0
- data/test/ec2-dsl_test.rb +198 -0
- data/test/test_helper.rb +11 -0
- metadata +68 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Jan Zimmek
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,329 @@
|
|
1
|
+
= EC2 DSL
|
2
|
+
|
3
|
+
A DSL to model your EC2 cloud written in ruby.
|
4
|
+
|
5
|
+
The purpose of this project to provide a simple but flexible foundation for upcoming ec2 related projects.
|
6
|
+
|
7
|
+
== Quickstart
|
8
|
+
|
9
|
+
cloud "my_network" do
|
10
|
+
|
11
|
+
keypair "my_keypair"
|
12
|
+
domain "ec.my_domain.com"
|
13
|
+
|
14
|
+
group "loadbalancer" do
|
15
|
+
ami "ami-ad7678aXX"
|
16
|
+
instance "lb01"
|
17
|
+
instance "lb02"
|
18
|
+
end
|
19
|
+
|
20
|
+
group "webserver" do
|
21
|
+
ami "ami-ad7678aYY"
|
22
|
+
instance "web01"
|
23
|
+
instance "web02"
|
24
|
+
instance "web03"
|
25
|
+
end
|
26
|
+
|
27
|
+
group "database" do
|
28
|
+
ami "ami-ad7678aZZ"
|
29
|
+
instance "master" do
|
30
|
+
elastic_ip "80.xx.yy.zz"
|
31
|
+
end
|
32
|
+
instance "slave"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
== Install
|
38
|
+
|
39
|
+
sudo gem install jzimmek-ec2-dsl
|
40
|
+
|
41
|
+
== Building Blocks
|
42
|
+
|
43
|
+
The EC2 DSL consists of the three major blocks "cloud", "instance" and "group". These blocks can be used to build your EC2 network model. Each block have a name and a handful of attributes. Once you have build your cloud model, you can reference it as ruby object and operate on it as you wish.
|
44
|
+
|
45
|
+
=== instance
|
46
|
+
|
47
|
+
An instance is the 1:1 definition of an EC2 instance. All instances have a name which will also be the used as the default hostname of the instance. The instance requires at least the "keypair" and "ami" attributes. You can define several attributes on your instance (See Attributes for details) - most of them can be inherited from the surronding group and cloud block.
|
48
|
+
|
49
|
+
=== cloud
|
50
|
+
|
51
|
+
A cloud block is the root block of your DSL definition and can be best understood as your entire "network" inside the EC2 world. The cloud has one or multiple groups.
|
52
|
+
|
53
|
+
=== group
|
54
|
+
|
55
|
+
Having more than one instance in your cloud and you will duplicate parts (ami, keypair, security_group etc.) of your instance configuration - sooner or later. Groups come to the rescue to avoid this and have DRY definition. A group has no direct counterpart in the EC2 world, but is simply a container around one or multiple instance definitions. Defining an attribute on the group will automatically be inherited by the instances within this group. (See Examples for details.)
|
56
|
+
|
57
|
+
== Examples
|
58
|
+
|
59
|
+
=== Cloud containing a single EC2 instance
|
60
|
+
|
61
|
+
cloud "my_network" do
|
62
|
+
group "default" do
|
63
|
+
instance "my_instance" do
|
64
|
+
ami "ami-ad7678as6"
|
65
|
+
keypair "my_keypair"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
=== Cloud containing multiple EC2 instance of same type
|
71
|
+
|
72
|
+
cloud "my_network" do
|
73
|
+
keypair "my_keypair"
|
74
|
+
|
75
|
+
group "webserver" do
|
76
|
+
ami "ami-ad7678as6"
|
77
|
+
instance "web01"
|
78
|
+
instance "web02"
|
79
|
+
instance "web03"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
=== Cloud containing multiple EC2 instance of different type
|
84
|
+
|
85
|
+
cloud "my_network" do
|
86
|
+
keypair "my_keypair"
|
87
|
+
|
88
|
+
group "webserver" do
|
89
|
+
ami "ami-ad7678aXX"
|
90
|
+
instance "web01"
|
91
|
+
instance "web02"
|
92
|
+
instance "web03"
|
93
|
+
end
|
94
|
+
|
95
|
+
group "database" do
|
96
|
+
ami "ami-ad7678YY"
|
97
|
+
instance "db01"
|
98
|
+
instance "db02"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
=== Cloud containing some more complex EC2 instance setup
|
103
|
+
|
104
|
+
cloud "my_network" do
|
105
|
+
keypair "my_keypair"
|
106
|
+
|
107
|
+
group "webserver" do
|
108
|
+
ami "ami-ad7678aXX"
|
109
|
+
instance "web01"
|
110
|
+
instance "web02" do
|
111
|
+
aki "custom_aki"
|
112
|
+
security_group "custom_security_group"
|
113
|
+
end
|
114
|
+
instance "web03" do
|
115
|
+
keypair "custom_keypair"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
group "database" do
|
120
|
+
ami "ami-ad7678YY"
|
121
|
+
instance "db01" do
|
122
|
+
elastic_ip "80.xx.yy.zz"
|
123
|
+
end
|
124
|
+
instance "db02"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
=== Instance with mount
|
129
|
+
|
130
|
+
cloud "my_network" do
|
131
|
+
group "default" do
|
132
|
+
instance "my_instance" do
|
133
|
+
ami "ami-ad7678as6"
|
134
|
+
keypair "my_keypair"
|
135
|
+
mount "some_volume_id", "/dev/sdh"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
=== Referencing a cloud model
|
142
|
+
|
143
|
+
cloud "my_network" do
|
144
|
+
keypair "my_keypair"
|
145
|
+
|
146
|
+
group "webserver" do
|
147
|
+
ami "ami-ad7678aXX"
|
148
|
+
instance "web01"
|
149
|
+
instance "web02"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# reference instance variable of cloud model
|
154
|
+
my_network = @my_network
|
155
|
+
|
156
|
+
# print groups of cloud "my_network"
|
157
|
+
my_network.groups.each_pair do |name, group|
|
158
|
+
puts "name: #{name}"
|
159
|
+
puts "group: #{group}"
|
160
|
+
end
|
161
|
+
|
162
|
+
# print instances of group "webserver"
|
163
|
+
|
164
|
+
my_network.groups["webserver"].instances.each_pair do |name, instance|
|
165
|
+
puts "name: #{name}"
|
166
|
+
puts "instance: #{instance}"
|
167
|
+
end
|
168
|
+
|
169
|
+
# print some attribute values
|
170
|
+
|
171
|
+
puts my_network.groups["webserver"].keypair
|
172
|
+
puts my_network.groups["webserver"].ami
|
173
|
+
puts my_network.groups["webserver"].instances["web01"].hostname
|
174
|
+
puts my_network.groups["webserver"].instances["web01"].elastic_ip
|
175
|
+
puts my_network.groups["webserver"].instances["web01"].keypair
|
176
|
+
puts my_network.groups["webserver"].instances["web01"].ami
|
177
|
+
puts my_network.groups["webserver"].instances["web02"].region
|
178
|
+
puts my_network.groups["webserver"].instances["web02"].security_group
|
179
|
+
|
180
|
+
== Attributes
|
181
|
+
|
182
|
+
Each building block can have several attributes to define things like (domain, hostname, elastic_ip, etc.). The attribute value of a building block will be inherited from its parent building. Inherited attributes can always be overwritten.
|
183
|
+
|
184
|
+
=== hostname
|
185
|
+
|
186
|
+
The hostname attribute describes the `hostname` value of your instance. Defaults to the name of your instance. Can only be applied to an "instance" block.
|
187
|
+
|
188
|
+
...
|
189
|
+
instance "web01"
|
190
|
+
...
|
191
|
+
|
192
|
+
# HOSTNAME = "web01"
|
193
|
+
|
194
|
+
...
|
195
|
+
instance "web01" do
|
196
|
+
hostname "some_other_domain"
|
197
|
+
end
|
198
|
+
...
|
199
|
+
|
200
|
+
HOSTNAME = "some_other_domain"
|
201
|
+
|
202
|
+
=== elastic_ip
|
203
|
+
|
204
|
+
The elastic_ip attribute describes the `elastic_ip` value of your instance. Can only be applied to an "instance" block.
|
205
|
+
|
206
|
+
...
|
207
|
+
instance "web01" do
|
208
|
+
elastic_ip "80.xx.yy.zz"
|
209
|
+
end
|
210
|
+
...
|
211
|
+
|
212
|
+
=== domain
|
213
|
+
|
214
|
+
The domain attribute describes the `domain` value of your instance. Can be applied to a "cloud", "group" and "instance" block.
|
215
|
+
|
216
|
+
...
|
217
|
+
cloud "my_network" do
|
218
|
+
domain "my_domain"
|
219
|
+
end
|
220
|
+
...
|
221
|
+
|
222
|
+
...
|
223
|
+
group "webserver" do
|
224
|
+
domain "my_webserver_domain"
|
225
|
+
end
|
226
|
+
...
|
227
|
+
|
228
|
+
...
|
229
|
+
instance "web01" do
|
230
|
+
domain "my_domain"
|
231
|
+
end
|
232
|
+
...
|
233
|
+
|
234
|
+
=== region
|
235
|
+
|
236
|
+
The region attribute describes the `region` value of your instance. Defaults to eu-west-1. Can be applied to a "cloud", "group" and "instance" block.
|
237
|
+
|
238
|
+
...
|
239
|
+
cloud "my_network" do
|
240
|
+
region "eu-west-1"
|
241
|
+
end
|
242
|
+
...
|
243
|
+
|
244
|
+
...
|
245
|
+
group "webserver" do
|
246
|
+
domain "us-east-1"
|
247
|
+
end
|
248
|
+
...
|
249
|
+
|
250
|
+
...
|
251
|
+
instance "web01" do
|
252
|
+
domain "eu-west-1"
|
253
|
+
end
|
254
|
+
...
|
255
|
+
|
256
|
+
|
257
|
+
=== security_group
|
258
|
+
|
259
|
+
The security_group attribute describes the `security_group` value of your instance. Can be applied to a "cloud", "group" and "instance" block.
|
260
|
+
|
261
|
+
...
|
262
|
+
cloud "my_network" do
|
263
|
+
security_group "default"
|
264
|
+
end
|
265
|
+
...
|
266
|
+
|
267
|
+
...
|
268
|
+
group "webserver" do
|
269
|
+
security_group "default"
|
270
|
+
end
|
271
|
+
...
|
272
|
+
|
273
|
+
...
|
274
|
+
instance "web01" do
|
275
|
+
security_group "some_custom_security_group"
|
276
|
+
end
|
277
|
+
...
|
278
|
+
|
279
|
+
=== keypair
|
280
|
+
|
281
|
+
The keypair attribute describes the `keypair` value of your instance. Can be applied to a "cloud", "group" and "instance" block.
|
282
|
+
|
283
|
+
...
|
284
|
+
cloud "my_network" do
|
285
|
+
keypair "my_keypair"
|
286
|
+
end
|
287
|
+
...
|
288
|
+
|
289
|
+
...
|
290
|
+
group "webserver" do
|
291
|
+
keypair "my_webserver_keypair"
|
292
|
+
end
|
293
|
+
...
|
294
|
+
|
295
|
+
...
|
296
|
+
instance "web01" do
|
297
|
+
keypair "my_web01_keypair"
|
298
|
+
end
|
299
|
+
...
|
300
|
+
|
301
|
+
=== ami, ari and aki
|
302
|
+
|
303
|
+
The ami, ari and aki attribute describes the 1:1 EC2 counterparts of your instance. Can be applied to a "group" and "instance" block.
|
304
|
+
|
305
|
+
...
|
306
|
+
group "webserver" do
|
307
|
+
|
308
|
+
# default ami for all instances in this group
|
309
|
+
ami "ami-ad7678as6"
|
310
|
+
|
311
|
+
# use default ami of group
|
312
|
+
instance "web01"
|
313
|
+
|
314
|
+
# runs some other ami
|
315
|
+
instance "web02" do
|
316
|
+
ami "ami-ad7678as6_beta"
|
317
|
+
end
|
318
|
+
|
319
|
+
# use default ami of group but other aki
|
320
|
+
instance "web03" do
|
321
|
+
aki "aki-ad7678as6_beta"
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
325
|
+
...
|
326
|
+
|
327
|
+
== Copyright
|
328
|
+
|
329
|
+
Copyright (c) 2009 Jan Zimmek. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "ec2-dsl"
|
8
|
+
gem.summary = "A DSL for EC2."
|
9
|
+
gem.description = "A DSL to model your EC2 cloud written in ruby."
|
10
|
+
gem.email = "jan.zimmek@web.de"
|
11
|
+
gem.homepage = "http://github.com/jzimmek/ec2-dsl"
|
12
|
+
gem.authors = ["Jan Zimmek"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/*_test.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/*_test.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
task :default => :test
|
42
|
+
|
43
|
+
require 'rake/rdoctask'
|
44
|
+
Rake::RDocTask.new do |rdoc|
|
45
|
+
if File.exist?('VERSION.yml')
|
46
|
+
config = YAML.load(File.read('VERSION.yml'))
|
47
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
48
|
+
else
|
49
|
+
version = ""
|
50
|
+
end
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "ec2-dsl #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
57
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/ec2-dsl.gemspec
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{ec2-dsl}
|
5
|
+
s.version = "0.2.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Jan Zimmek"]
|
9
|
+
s.date = %q{2009-06-13}
|
10
|
+
s.description = %q{A DSL to model your EC2 cloud written in ruby.}
|
11
|
+
s.email = %q{jan.zimmek@web.de}
|
12
|
+
s.extra_rdoc_files = [
|
13
|
+
"LICENSE",
|
14
|
+
"README.rdoc"
|
15
|
+
]
|
16
|
+
s.files = [
|
17
|
+
".document",
|
18
|
+
".gitignore",
|
19
|
+
"LICENSE",
|
20
|
+
"README.rdoc",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"ec2-dsl.gemspec",
|
24
|
+
"lib/ec2-dsl.rb",
|
25
|
+
"lib/ec2/dsl/cloud.rb",
|
26
|
+
"lib/ec2/dsl/container.rb",
|
27
|
+
"lib/ec2/dsl/group.rb",
|
28
|
+
"lib/ec2/dsl/instance.rb",
|
29
|
+
"test/ec2-dsl_test.rb",
|
30
|
+
"test/test_helper.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/jzimmek/ec2-dsl}
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.4}
|
36
|
+
s.summary = %q{A DSL for EC2.}
|
37
|
+
s.test_files = [
|
38
|
+
"test/ec2-dsl_test.rb",
|
39
|
+
"test/test_helper.rb"
|
40
|
+
]
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
44
|
+
s.specification_version = 3
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
47
|
+
else
|
48
|
+
end
|
49
|
+
else
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'ec2/dsl/container'
|
2
|
+
require 'ec2/dsl/group'
|
3
|
+
|
4
|
+
module Ec2
|
5
|
+
module Dsl
|
6
|
+
class Cloud < Container
|
7
|
+
|
8
|
+
define_attribute :keypair
|
9
|
+
define_attribute :security_group
|
10
|
+
define_attribute :region
|
11
|
+
define_attribute :domain
|
12
|
+
|
13
|
+
attr_accessor :groups
|
14
|
+
|
15
|
+
def initialize(name)
|
16
|
+
@groups = {}
|
17
|
+
security_group("default")
|
18
|
+
region("eu-west-1")
|
19
|
+
super(name, nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
def group(name, &block)
|
23
|
+
name = name.to_s
|
24
|
+
|
25
|
+
raise "group '#{name}' already defined in '#{self.name}'" if @groups.key?(name)
|
26
|
+
|
27
|
+
group = Group.new(name, self)
|
28
|
+
group.instance_eval(&block)
|
29
|
+
|
30
|
+
@groups[name] = group
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate
|
34
|
+
groups.each_pair do |key, value|
|
35
|
+
value.validate
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def instances
|
40
|
+
instances = []
|
41
|
+
@groups.each_value do |group|
|
42
|
+
group.instances.each_value { |instance| instances << instance }
|
43
|
+
end
|
44
|
+
instances
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Ec2
|
2
|
+
module Dsl
|
3
|
+
class Container
|
4
|
+
attr_accessor :name
|
5
|
+
attr_accessor :container
|
6
|
+
|
7
|
+
def initialize(name, container)
|
8
|
+
@name = name
|
9
|
+
@container = container
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.define_attribute(*names)
|
13
|
+
names.each do |name|
|
14
|
+
|
15
|
+
define_method(name) do |value|
|
16
|
+
instance_variable_set("@#{name}", value)
|
17
|
+
end
|
18
|
+
|
19
|
+
getter_name = "#{name}_value".to_sym
|
20
|
+
|
21
|
+
define_method(getter_name) do
|
22
|
+
value = instance_variable_get("@#{name}")
|
23
|
+
|
24
|
+
if !value && @container.respond_to?(getter_name)
|
25
|
+
value = @container.send(getter_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_required_attribute(attribute)
|
34
|
+
raise "#{self.class} (#{self.name}) is invalid: attribute #{attribute} is required." unless self.send("#{attribute}_value".to_sym)
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ec2/dsl/container'
|
2
|
+
require 'ec2/dsl/instance'
|
3
|
+
|
4
|
+
module Ec2
|
5
|
+
module Dsl
|
6
|
+
class Group < Container
|
7
|
+
|
8
|
+
define_attribute :keypair
|
9
|
+
define_attribute :security_group
|
10
|
+
define_attribute :region
|
11
|
+
define_attribute :ami, :ari, :aki
|
12
|
+
define_attribute :domain
|
13
|
+
|
14
|
+
attr_accessor :instances
|
15
|
+
|
16
|
+
def initialize(name, container)
|
17
|
+
@instances = {}
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def instance(name, &block)
|
22
|
+
name = name.to_s
|
23
|
+
|
24
|
+
raise "instance '#{name}' already defined in '#{self.name}'" if @instances.key?(name)
|
25
|
+
|
26
|
+
instance = Instance.new(name, self)
|
27
|
+
instance.instance_eval(&block) if block_given?
|
28
|
+
|
29
|
+
@instances[name] = instance
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate
|
33
|
+
|
34
|
+
raise "group '#{self.name}' has no instances" if instances.empty?
|
35
|
+
|
36
|
+
instances.each_pair do |key, value|
|
37
|
+
value.validate
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ec2/dsl/container'
|
2
|
+
|
3
|
+
module Ec2
|
4
|
+
module Dsl
|
5
|
+
class Instance < Container
|
6
|
+
|
7
|
+
define_attribute :keypair
|
8
|
+
define_attribute :security_group
|
9
|
+
define_attribute :region
|
10
|
+
define_attribute :ami, :ari, :aki
|
11
|
+
define_attribute :hostname, :domain
|
12
|
+
define_attribute :elastic_ip
|
13
|
+
|
14
|
+
def initialize(name, container)
|
15
|
+
hostname(name)
|
16
|
+
@mounts = []
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate
|
21
|
+
validate_required_attribute(:keypair)
|
22
|
+
validate_required_attribute(:security_group)
|
23
|
+
validate_required_attribute(:region)
|
24
|
+
validate_required_attribute(:ami)
|
25
|
+
validate_required_attribute(:hostname)
|
26
|
+
|
27
|
+
@mounts.each do |mount|
|
28
|
+
raise "mounted volume_id in instance '#{self.name}' is empty" if mount[:volume_id].empty?
|
29
|
+
raise "mounted device in instance '#{self.name}' is empty" if mount[:device].empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def mount(volume_id, device)
|
35
|
+
@mounts << {:volume_id => volume_id, :device => device}
|
36
|
+
end
|
37
|
+
|
38
|
+
def mounts
|
39
|
+
@mounts
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/ec2-dsl.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Ec2DslTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "create a instance variable named by the name of the cloud" do
|
6
|
+
cloud "my_network" do
|
7
|
+
end
|
8
|
+
|
9
|
+
assert @my_network
|
10
|
+
end
|
11
|
+
|
12
|
+
should "create some groups in the cloud" do
|
13
|
+
|
14
|
+
cloud "my_network", false do
|
15
|
+
group "webserver" do
|
16
|
+
end
|
17
|
+
|
18
|
+
group "database" do
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
assert 2, @my_network.groups.length
|
24
|
+
assert "webserver", @my_network.groups["webserver"].name
|
25
|
+
assert "database", @my_network.groups["database"].name
|
26
|
+
end
|
27
|
+
|
28
|
+
should "name a container" do
|
29
|
+
|
30
|
+
cloud "my_network", false do
|
31
|
+
group "webserver" do
|
32
|
+
instance "web01"
|
33
|
+
end
|
34
|
+
group "database" do
|
35
|
+
instance "db01"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
assert_equal "my_network", @my_network.name
|
40
|
+
|
41
|
+
assert_equal "webserver", @my_network.groups["webserver"].name
|
42
|
+
assert_equal "database", @my_network.groups["database"].name
|
43
|
+
|
44
|
+
assert_equal "web01", @my_network.groups["webserver"].instances["web01"].name
|
45
|
+
assert_equal "db01", @my_network.groups["database"].instances["db01"].name
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
should "fail if no keypair/ami is given to an instance" do
|
50
|
+
|
51
|
+
assert_raise RuntimeError do
|
52
|
+
cloud "my_network" do
|
53
|
+
group "default" do
|
54
|
+
instance "app01"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
assert_raise RuntimeError do
|
60
|
+
cloud "my_network" do
|
61
|
+
group "default" do
|
62
|
+
instance "app01" do
|
63
|
+
ami "some_ami"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
assert_raise RuntimeError do
|
70
|
+
cloud "my_network" do
|
71
|
+
group "default" do
|
72
|
+
instance "app01" do
|
73
|
+
keypair "some_keypair"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
should "create some instances in the cloud" do
|
82
|
+
|
83
|
+
cloud "my_network", false do
|
84
|
+
group "default" do
|
85
|
+
instance "server01"
|
86
|
+
instance "server02"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
grp = @my_network.groups["default"]
|
91
|
+
|
92
|
+
assert 2, grp.instances.length
|
93
|
+
assert "server01", grp.instances["server01"].name
|
94
|
+
assert "server02", grp.instances["server02"].name
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
should "assign instance name as default hostname" do
|
99
|
+
cloud "my_network", false do
|
100
|
+
group "default" do
|
101
|
+
instance "server01"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
assert_equal "server01", @my_network.groups["default"].instances["server01"].hostname_value
|
106
|
+
end
|
107
|
+
|
108
|
+
should "fail if no instance found in group" do
|
109
|
+
|
110
|
+
assert_raise RuntimeError do
|
111
|
+
cloud "my_network" do
|
112
|
+
group "default" do
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
should "inherit attributes from container" do
|
120
|
+
|
121
|
+
cloud "my_network", false do
|
122
|
+
domain "some_domain"
|
123
|
+
group "default" do
|
124
|
+
instance "server01"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
assert_equal "some_domain", @my_network.groups["default"].domain_value
|
129
|
+
assert_equal "some_domain", @my_network.groups["default"].instances["server01"].domain_value
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
should "be able to overwrite inherited attributes from container" do
|
134
|
+
|
135
|
+
cloud "my_network", false do
|
136
|
+
domain "some_domain"
|
137
|
+
group "default" do
|
138
|
+
instance "server01"
|
139
|
+
instance "server02" do
|
140
|
+
domain "some_other_domain"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
assert_equal "some_domain", @my_network.groups["default"].instances["server01"].domain_value
|
146
|
+
assert_equal "some_other_domain", @my_network.groups["default"].instances["server02"].domain_value
|
147
|
+
end
|
148
|
+
|
149
|
+
should "collect all instances in the cloud" do
|
150
|
+
|
151
|
+
cloud "my_network", false do
|
152
|
+
group "grp1" do
|
153
|
+
instance "server01"
|
154
|
+
instance "server02"
|
155
|
+
end
|
156
|
+
group "grp2" do
|
157
|
+
instance "server03"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
instances = @my_network.instances
|
162
|
+
|
163
|
+
assert_equal 3, instances.length
|
164
|
+
assert_equal 1, instances.find_all{ |instance| instance.name == "server01" }.length
|
165
|
+
assert_equal 1, instances.find_all{ |instance| instance.name == "server02" }.length
|
166
|
+
assert_equal 1, instances.find_all{ |instance| instance.name == "server03" }.length
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
should "create an instance with some mounted volume" do
|
171
|
+
|
172
|
+
cloud "my_network", false do
|
173
|
+
group "default" do
|
174
|
+
instance "server01" do
|
175
|
+
mount "my_volume", "/dev/sdh"
|
176
|
+
end
|
177
|
+
instance "server02" do
|
178
|
+
mount "my_volume", "/dev/sdh"
|
179
|
+
mount "my_volume2", "/dev/sdi"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
server01 = @my_network.groups["default"].instances["server01"]
|
185
|
+
assert_equal 1, server01.mounts.length
|
186
|
+
assert_equal "my_volume", server01.mounts.first[:volume_id]
|
187
|
+
assert_equal "/dev/sdh", server01.mounts.first[:device]
|
188
|
+
|
189
|
+
server02 = @my_network.groups["default"].instances["server02"]
|
190
|
+
assert_equal 2, server02.mounts.length
|
191
|
+
assert_equal "my_volume", server02.mounts[0][:volume_id]
|
192
|
+
assert_equal "/dev/sdh", server02.mounts[0][:device]
|
193
|
+
assert_equal "my_volume2", server02.mounts[1][:volume_id]
|
194
|
+
assert_equal "/dev/sdi", server02.mounts[1][:device]
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jzimmek-ec2-dsl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jan Zimmek
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-13 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A DSL to model your EC2 cloud written in ruby.
|
17
|
+
email: jan.zimmek@web.de
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- .document
|
27
|
+
- .gitignore
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
- Rakefile
|
31
|
+
- VERSION
|
32
|
+
- ec2-dsl.gemspec
|
33
|
+
- lib/ec2-dsl.rb
|
34
|
+
- lib/ec2/dsl/cloud.rb
|
35
|
+
- lib/ec2/dsl/container.rb
|
36
|
+
- lib/ec2/dsl/group.rb
|
37
|
+
- lib/ec2/dsl/instance.rb
|
38
|
+
- test/ec2-dsl_test.rb
|
39
|
+
- test/test_helper.rb
|
40
|
+
has_rdoc: false
|
41
|
+
homepage: http://github.com/jzimmek/ec2-dsl
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options:
|
44
|
+
- --charset=UTF-8
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.2.0
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: A DSL for EC2.
|
66
|
+
test_files:
|
67
|
+
- test/ec2-dsl_test.rb
|
68
|
+
- test/test_helper.rb
|