dployr 0.0.8 → 0.0.9

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 304f9d5d7f79de110215c48e59f5c3dc39bbe29c
4
- data.tar.gz: 3fa3639b3f5058161d5fb1b318d217dcfa1c4a78
3
+ metadata.gz: ccf10af60294e8d7c5e2edbe34f4bc1b2c2c3ea4
4
+ data.tar.gz: d1d72ea9459501658813c121fb4c3f05450d3d29
5
5
  SHA512:
6
- metadata.gz: 6eaaaf925b1c8e8ef30519a4c664577359cc33266cc8db708979f32f903ac5bd0bf58bcf13d624c6059ba0b0c19846914f65d0e07690036004b91d0b016ab79b
7
- data.tar.gz: 51a0d39c49c4ce149003d5acd1807879f4a0878f5fb159f8c086d3b7d09a900076f2a153c3db348217a00acd5dfe388a49957505aa8c73e4fda3ee701e26d2ca
6
+ metadata.gz: 89d38a44d6797a60ae5e8593ca958244648dbeff3e33926c2e6e5f689626e05ea2b59f6a0922e26fd83ae1aeb3f73eec6a397b38e0098ab5cf38ed9a8d1c9284
7
+ data.tar.gz: 6ee5b85aef80f2a1c915ea3195139e9312bdcca676721ae37c843c578a452a8fd6d6b9777e6058bf9a789af6b49ebe4311cb2100d75009b17ccc24ef65cd7560
data/README.md CHANGED
@@ -15,13 +15,17 @@
15
15
 
16
16
  ## About
17
17
 
18
- **Dployr** is a Ruby utility that simplifies cloud management
19
- and deployment across different providers
18
+ **Dployr** is a Ruby utility that **simplifies cloud management
19
+ and deployment** across different providers
20
20
 
21
- You can setup your project cloud infraestructure from a
22
- simple configuration file which support built-in rich features
21
+ You can setup all your project cloud infraestructure from a
22
+ simple configuration file and deploy it into multiple clouds easily
23
23
 
24
- Dployr provides a featured [command-line interface](#command-line-interface) and [programmatic API](#programmatic-api)
24
+ Through Dployr you can take full control about the multiple stages phases
25
+ which covers the full deployment infrastructure workflow,
26
+ such as instances creation, network configuration, provisioning, testing and halting
27
+
28
+ It provides a featured [command-line interface](#command-line-interface) and [programmatic API](#programmatic-api)
25
29
 
26
30
  ## Installation
27
31
 
@@ -38,25 +42,34 @@ spec.add_dependency 'dployr', '~> 0.0.1'
38
42
  gem 'dployr', '>= 0.0.1'
39
43
  ```
40
44
 
41
- Requires Ruby 1.9.3+
45
+ It requires Ruby `1.9.3+`
42
46
 
43
47
  ## Features
44
48
 
45
- - Fully configurable from Ruby or YAML file with rich features like templating
46
- - Supports deployment to multiple cloud providers
49
+ - Fully configurable from Ruby or YAML file with built-in rich features like templating
50
+ - Simplifies deployment to multiple cloud providers
51
+ - Allows to create the same infraestructe into multiple cloud providers from one command
47
52
  - Supports default instances and inherited configuration values
48
53
  - Full control of virtual instances (start, restart, stop, test, provision)
49
- - Local and remote scripts execution per stage phase (start, test, provision, update, stop...)
54
+ - Allows to run local and remote scripts execution per stage with pre and post hooks
50
55
  - Featured command-line and programmatic API
51
56
 
52
57
  ## Supported providers
53
58
 
54
- Note that as Dployr is still in alpha stage, there are only a few providers supported
59
+ Dployr is still a alpha project, so there are only a few providers supported
55
60
 
56
61
  - Amazon Web Services (`aws`)
57
62
  - Google Compute Engine (`gce`)
58
63
  - Baremetal
59
64
 
65
+ Upcoming supported providers by priority
66
+
67
+ - OpenStack
68
+ - Verizon
69
+ - Azure
70
+ - Rackspace
71
+ - XenServer
72
+
60
73
  ## Configuration
61
74
 
62
75
  Configuration file must be called `Dployrfile`. It can be also a standard Ruby file
@@ -69,13 +82,16 @@ Each configuration level supports the followings members:
69
82
  - **attributes** `Object` Custom attributes to apply to the current template
70
83
  - **scripts** `Object` Scripts hooks per phase to run (start, stop, test...)
71
84
  - **providers** `Object` Nested configuration provider-specific (aws, gce...)
72
- - **extends** `String|Array` Allows to inherits the current template from other templates
85
+ - **extends** `String|Array` Allows to inherits from other template
73
86
 
74
87
  #### Templating
75
88
 
76
- Dployr allows templating features inside configuration values, in order
77
- to provide an easy and clean way to dynamically replace values and self-referenced variables
78
- inside the same configuration
89
+ Dployr allows templating powerful features inside configuration values, in order
90
+ to provide an easy, non-redundant and clean way to dynamically replace values for different usage contexts,
91
+ such as specific context cloud provider, deployment region or environment variables
92
+
93
+ Configuration templates can inherits from others templates,
94
+ so you can reuse environments for multiple projects or environments
79
95
 
80
96
  Supported template values notations
81
97
 
@@ -251,14 +267,15 @@ Dployr API documentation is available from [RubyDoc][rubydoc]
251
267
 
252
268
  ### Configuration
253
269
 
270
+ Example Dployrfile in Ruby which uses the API to configure your project
254
271
  ```ruby
255
272
  Dployr::configure do |dployr|
256
273
 
257
- dployr.config.add_instance({
274
+ dployr.config.add_instance(:zeus, {
258
275
  attributes: {
259
- name: "example",
260
276
  instance_type: "m1.small",
261
- version: "${VERSION}"
277
+ version: "${VERSION}",
278
+ env: 'dev'
262
279
  },
263
280
  scripts: [
264
281
  { path: "configure.sh" }
@@ -266,18 +283,29 @@ Dployr::configure do |dployr|
266
283
  providers: {
267
284
  aws: {
268
285
  attributes: {
269
- network_id: "be457fca",
270
- instance_type: "m1.small",
271
- "type-%{name}" => "small"
286
+ ami: 'ami-370daf2a', # centos-base-v7
287
+ keypair: 'vagrant-aws-saopaulo',
288
+ security_groups: ['sg-3cf3e45e'],
289
+ subnet_id: 'subnet-1eebe07c'
290
+ public_ip: 'new'
272
291
  },
273
292
  regions: {
274
293
  "eu-west-1a" => {
275
294
  attributes: {
295
+ instance_type: "m1.medium",
276
296
  keypair: "vagrant-aws-ireland"
277
297
  },
278
- scripts: [
279
- { path: "router.sh", args: ["%{name}", "${region}", "${provider}"] }
280
- ]
298
+ scripts: {
299
+ start: [
300
+ { path: "router.sh", args: ["${name}", "${region}", "${provider}"] }
301
+ ]
302
+ provision: [
303
+ { path: "puppet.sh", args: ["${name}", "${region}", "${provider}", '--env %{env}'] }
304
+ ]
305
+ post-provision: [
306
+ { path: "clean.sh" }
307
+ ]
308
+ }
281
309
  }
282
310
  }
283
311
  }
@@ -322,9 +350,9 @@ To build a new version of the gem:
322
350
  $ rake build
323
351
  ````
324
352
 
325
- To publish the new version to Rubygems:
353
+ Publish the new version to Rubygems:
326
354
  ```
327
- $ rake release
355
+ $ gem push pkg/dployr-0.1.0.gem
328
356
  ```
329
357
 
330
358
  ## Contributors
data/lib/dployr/cli.rb CHANGED
@@ -5,6 +5,22 @@ require 'dployr/version'
5
5
  command = ARGV[0]
6
6
  options = {}
7
7
 
8
+ def run(command, options, arg = nil)
9
+ begin
10
+ cmd = Dployr::Commands.const_get command
11
+ raise "Command not supported: #{command}" unless cmd
12
+ if arg
13
+ cmd.new options, arg
14
+ else
15
+ cmd.new options
16
+ end
17
+ rescue => e
18
+ puts "Error: #{e}".red
19
+ puts e.backtrace if e.backtrace and options[:debug]
20
+ exit 1
21
+ end
22
+ end
23
+
8
24
  opt_parser = OptionParser.new do |opt|
9
25
  opt.banner = "\n Usage: dployr <command> [options]"
10
26
  opt.separator ""
@@ -69,22 +85,6 @@ end
69
85
 
70
86
  opt_parser.parse!
71
87
 
72
- def run(command, options, arg = nil)
73
- begin
74
- cmd = Dployr::Commands.const_get command
75
- raise "Command not supported: #{command}" unless cmd
76
- if arg
77
- cmd.new options, arg
78
- else
79
- cmd.new options
80
- end
81
- rescue => e
82
- puts "Error: #{e}".red
83
- puts e.backtrace if e.backtrace and options[:debug]
84
- exit 1
85
- end
86
- end
87
-
88
88
  case command
89
89
  when "start"
90
90
  run :Start, options
@@ -78,6 +78,29 @@ module Dployr
78
78
  wait_ssh @attrs, server, @options[:public_ip]
79
79
  end
80
80
 
81
+ def create_network(network_name, network_range, firewalls, routes)
82
+ # Routes not used in AWS
83
+ create_vpc(network_range) # VPC + INTERNET GATEWAY
84
+ create_subnet(network_range) # SUBNET + ROUTE TABLE
85
+ configure_security_group(firewalls) # SECURITY GROUP
86
+ end
87
+
88
+ def delete_network(network_name, network_range, firewalls, routes)
89
+ # Network_name, firewalls and routes not used. We only need "vpc_id"
90
+ if exist_vpc network_range
91
+ vpcId = get_vpcId(network_range)
92
+
93
+ delete_route_tables(vpcId)
94
+ delete_subnets(vpcId)
95
+ delete_network_acls(vpcId)
96
+ delete_internet_gateways(vpcId)
97
+ delete_security_groups(vpcId)
98
+ delete_vpc(vpcId)
99
+ else
100
+ puts "\tNetwork #{network_range} not found. Nothing to delete!"
101
+ end
102
+ end
103
+
81
104
  private
82
105
 
83
106
  def get_instance(states)
@@ -107,6 +130,222 @@ module Dployr
107
130
  end
108
131
  end
109
132
 
133
+ def create_vpc(network_range)
134
+ if ! exist_vpc(network_range)
135
+ # Internet Gateway
136
+ ig = @compute.create_internet_gateway
137
+ igId = ig.body["internetGatewaySet"][0]["internetGatewayId"]
138
+ puts "\tInternet Gateway #{igId} created!"
139
+
140
+ @attrs["internetGatewayId"] = igId
141
+
142
+ # VPC
143
+ vpc = @compute.create_vpc(network_range)
144
+ vpcId = vpc.body["vpcSet"][0]["vpcId"]
145
+ puts "\tVPC #{vpcId} (#{network_range}) created!"
146
+
147
+ # Associate both
148
+ @compute.attach_internet_gateway(igId, vpcId)
149
+ puts "\t\tBoth associated!"
150
+ else
151
+ puts "\tVPC #{network_range} already exists"
152
+ vpcId = get_vpcId(network_range)
153
+ end
154
+
155
+ @attrs["vpcId"] = vpcId
156
+ end
157
+
158
+ def create_subnet(network_range)
159
+ if ! exist_subnet(network_range)
160
+ vpcId = @attrs["vpcId"]
161
+
162
+ # SUBNET
163
+ sn = @compute.create_subnet(vpcId, network_range)
164
+ snId = sn.body["subnet"]["subnetId"]
165
+ puts "\tSubnet #{snId} created!"
166
+
167
+ @attrs["subnetId"] = snId
168
+
169
+ # ROUTE TABLE
170
+ rt = @compute.create_route_table(vpcId)
171
+ rtId = rt.body["routeTable"][0]["routeTableId"]
172
+ puts "\tRoute table #{rtId} created!"
173
+
174
+ @attrs["routeTableId"] = rtId
175
+
176
+ # Add route for internet gateway
177
+ igId = @attrs["internetGatewayId"]
178
+ @compute.create_route(rtId, "0.0.0.0/0", igId, instance_id = nil, network_interface_id = nil)
179
+
180
+ # Associate both
181
+ @compute.associate_route_table(rtId, snId)
182
+ puts "\t\tBoth associated!"
183
+ else
184
+ puts "\tSubnet #{network_range} already exists"
185
+ end
186
+ end
187
+
188
+ def configure_security_group(firewalls)
189
+
190
+ timestamp = Time.now.to_i
191
+ @attrs["securityGroupName"] = "SG-#{timestamp}"
192
+ puts "\tConfiguring Security Group: #{@attrs["securityGroupName"]}"
193
+
194
+ vpcId = @attrs["vpcId"]
195
+
196
+ # Create Security Group
197
+ sg = @compute.create_security_group( @attrs["securityGroupName"], "dployr", vpcId)
198
+ @attrs["securityGroupId"] = sg.body["groupId"]
199
+ puts "\t\tSecurity Group #{@attrs["securityGroupId"]} created!"
200
+
201
+ # Create rules
202
+ if firewalls.respond_to?("each")
203
+ firewalls.each do |key, value|
204
+ add_firewall( @attrs["securityGroupId"] , key, value["address"][0], value["protocol"], value["port"])
205
+ end
206
+ end
207
+
208
+ puts "\tSecurity Group #{@attrs["securityGroupId"]} configured!"
209
+ end
210
+
211
+ def add_firewall(sgId, name, cidrIp, protocol, ports)
212
+ # Split ports into "from" and "to"
213
+ words = ports.split("-")
214
+ if words.length > 1
215
+ from = words[0].to_i
216
+ to = words[1].to_i
217
+ else
218
+ from = to = words[0].to_i
219
+ end
220
+
221
+ group_name = "SG-plumbing"
222
+ options = {}
223
+ options["GroupId"] = "#{sgId}"
224
+ options["CidrIp"] = "#{cidrIp}"
225
+ options["FromPort"] = from
226
+ options["IpProtocol"] = "#{protocol}"
227
+ options["ToPort"] = to
228
+
229
+ # Add rule
230
+ asg = @compute.authorize_security_group_ingress(group_name, options)
231
+ puts "\t\tRule #{name} added!"
232
+ end
233
+
234
+ def exist_vpc(name)
235
+ list = @compute.describe_vpcs.data[:body]
236
+ items = list["vpcSet"]
237
+ if items.respond_to?("each")
238
+ items.each do |item|
239
+ if item["cidrBlock"] == name
240
+ return true
241
+ end
242
+ end
243
+ end
244
+ return false
245
+ end
246
+
247
+ def exist_subnet(name)
248
+ list = @compute.describe_subnets.data[:body]
249
+ items = list["subnetSet"]
250
+ if items.respond_to?("each")
251
+ items.each do |item|
252
+ if item["cidrBlock"] == name
253
+ return true
254
+ end
255
+ end
256
+ end
257
+ return false
258
+ end
259
+
260
+ def get_vpcId(private_net)
261
+ list = @compute.describe_vpcs.data[:body]
262
+ items = list["vpcSet"]
263
+ if items.respond_to?("each")
264
+ items.each do |item|
265
+ if item["cidrBlock"] == private_net
266
+ return item["vpcId"]
267
+ end
268
+ end
269
+ end
270
+ return ""
271
+ end
272
+
273
+ # Route Tables
274
+ # Delete non-default route tables from VPC. Default tables NOT allowed
275
+ def delete_route_tables(vpcId)
276
+ rts = @compute.describe_route_tables('vpc-id' => "#{vpcId}").body["routeTableSet"]
277
+ if rts.respond_to?("each")
278
+ rts.each do |rt|
279
+ if ! rt["associationSet"][0]["main"] # non-default
280
+ @compute.disassociate_route_table( rt["associationSet"][0]["routeTableAssociationId"] )
281
+ @compute.delete_route_table( rt["routeTableId"] )
282
+ puts "\tRoute table #{rt["routeTableId"]} deleted!"
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ # Subnets
289
+ # Delete subnets from VPC.
290
+ def delete_subnets(vpcId)
291
+ subnets = @compute.describe_subnets('vpc-id' => "#{vpcId}").body["subnetSet"]
292
+ if subnets.respond_to?("each")
293
+ subnets.each do |sn|
294
+ @compute.delete_subnet( sn["subnetId"] )
295
+ puts "\tSubnet #{sn["subnetId"]} deleted!"
296
+ end
297
+ end
298
+ end
299
+
300
+ # Network ACLs
301
+ # Delete non-default network ACLs from VPC. Defaul ACLs NOT allowed
302
+ def delete_network_acls(vpcId)
303
+ acls = @compute.describe_network_acls('vpc-id' => "#{vpcId}").body["networkAclSet"]
304
+ if acls.respond_to?("each")
305
+ acls.each do |acl|
306
+ if ! acl["default"] # non-default
307
+ @compute.delete_network_acl( acl["networkAclId"] )
308
+ puts "\tNetwork ACL #{acl["networkAclId"]} deleted!"
309
+ end
310
+ end
311
+ end
312
+ end
313
+
314
+ # Internet Gateway
315
+ # Delete internet gateways from VPC.
316
+ def delete_internet_gateways(vpcId)
317
+ igws = @compute.describe_internet_gateways('attachment.vpc-id' => "#{vpcId}").body["internetGatewaySet"]
318
+ if igws.respond_to?("each")
319
+ igws.each do |igw|
320
+ @compute.detach_internet_gateway( igw["internetGatewayId"], vpcId )
321
+ @compute.delete_internet_gateway( igw["internetGatewayId"] )
322
+ puts "\tInternet gateway #{igw["internetGatewayId"]} deleted!"
323
+ end
324
+ end
325
+ end
326
+
327
+ # Security Group
328
+ # Delete non-default security group from VPC. Default SG NOT allowed
329
+ def delete_security_groups(vpcId)
330
+ sgs = @compute.describe_security_groups('vpc-id' => "#{vpcId}").body["securityGroupInfo"]
331
+ if sgs.respond_to?("each")
332
+ sgs.each do |sg|
333
+ if sg["groupName"] != "default" # non-default
334
+ @compute.delete_security_group( nil, sg["groupId"] )
335
+ puts "\tSecurity Group #{sg["groupId"]} deleted!"
336
+ end
337
+ end
338
+ end
339
+ end
340
+
341
+ def delete_vpc(vpcId)
342
+ if @compute.delete_vpc(vpcId)
343
+ puts "\tVPC #{vpcId} deleted!"
344
+ else
345
+ puts "\tError deleting VPC #{vpcId}!"
346
+ end
347
+ end
348
+
110
349
  end
111
350
  end
112
351
  end
@@ -48,13 +48,11 @@ module Dployr
48
48
  end
49
49
  channel.on_data do |ch,data|
50
50
  stdout_data+=data
51
- #print "[#{@host}] #{data}".green
52
51
  print "#{data}".green
53
52
  end
54
53
 
55
54
  channel.on_extended_data do |ch,type,data|
56
55
  stderr_data += data
57
- #print "[#{@host}] #{data}".red
58
56
  print "#{data}".red
59
57
  end
60
58
 
@@ -1,3 +1,3 @@
1
1
  module Dployr
2
- VERSION = '0.0.8'
2
+ VERSION = '0.0.9'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dployr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomas Aparicio
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-07 00:00:00.000000000 Z
12
+ date: 2014-05-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog
@@ -149,7 +149,6 @@ files:
149
149
  - lib/dployr/config/instance.rb
150
150
  - lib/dployr/configuration.rb
151
151
  - lib/dployr/init.rb
152
- - lib/dployr/logger.rb
153
152
  - lib/dployr/scripts/default_hooks.rb
154
153
  - lib/dployr/scripts/hook.rb
155
154
  - lib/dployr/scripts/local_shell.rb
data/lib/dployr/logger.rb DELETED
@@ -1,11 +0,0 @@
1
- module Dployr
2
- module Logger
3
-
4
- module_function
5
-
6
- def log(*msg)
7
- msg.each { |msg| puts msg }
8
- end
9
-
10
- end
11
- end