judo 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.3.2
data/bin/judo CHANGED
@@ -35,7 +35,7 @@ Usage: judo launch [options] SERVER ...
35
35
  judo animate [options] SNAPSHOT SERVER ## create a new server from a snapshot
36
36
  judo erase [options] SNAPSHOT ## erase an old snapshot
37
37
 
38
- judo swapip [options] SERVER SERVER ## swap elastic IP's on the two servers
38
+ judo swap [options] SERVER SERVER ## swap elastic IP's and names on the two servers
39
39
 
40
40
  judo info [options] [SERVER ...]
41
41
  judo console [options] [SERVER ...] ## shows AWS console output
@@ -124,13 +124,18 @@ begin
124
124
  when "start" then find_servers(judo, ARGV) { |s| s.start(options) }
125
125
  when "restart" then find_servers(judo, ARGV) { |s| s.restart(options) }
126
126
  when "stop" then find_servers(judo, ARGV) { |s| s.stop(options) }
127
- when "create" then mk_servers(judo, ARGV) { |s| s.create(options) }
128
- when "launch" then mk_servers(judo, ARGV) { |s| s.create(options); s.start(options) }
127
+ when "create" then mk_servers(judo, options, ARGV)
128
+ when "launch" then mk_servers(judo, options, ARGV) { |s| s.start(options) }
129
129
  when "snapshots" then do_snapshots(judo, ARGV)
130
- when "swapip" then
130
+ when "rename" then
131
+ raise JudoError, "usage: judo rename SERVER SERVER" unless ARGV.size == 2
132
+ old,new = ARGV
133
+ server = find_servers(judo, [old]).first
134
+ server.rename(new)
135
+ when "swap" then
131
136
  servers = find_servers(judo, ARGV)
132
137
  raise JudoError, "usage: judo swapip SERVER SERVER" unless servers.size == 2
133
- servers[0].swapip(servers[1])
138
+ servers[0].swap(servers[1])
134
139
  when "erase" then
135
140
  raise JudoError, "usage: judo erase SNAPSHOT" unless ARGV.size == 1
136
141
  snapshot_name = ARGV.shift
@@ -150,7 +155,7 @@ begin
150
155
  raise JudoError, "You must specify a new server name" unless new_server
151
156
  snapshot = judo.snapshots.detect { |s| s.name == snapshot_name }
152
157
  raise JudoError, "No such snapshot #{snapshot_name}" unless snapshot
153
- snapshot.animate(new_server,options[:version])
158
+ snapshot.animate(new_server).start(options)
154
159
  when "destroy" then
155
160
  raise JudoError, "You must specify what servers to destroy" if ARGV.empty?
156
161
  find_either(judo, ARGV) do |i|
data/lib/judo.rb CHANGED
@@ -6,6 +6,7 @@ require 'fileutils'
6
6
  require 'yaml'
7
7
  require 'json'
8
8
  require 'pp'
9
+ require 'tempfile'
9
10
 
10
11
  raise "Judo Currently Requires Ruby 1.8.7" unless RUBY_VERSION == "1.8.7"
11
12
 
data/lib/judo/base.rb CHANGED
@@ -152,12 +152,22 @@ module Judo
152
152
  end
153
153
 
154
154
  def servers
155
- @servers ||= servers_state.map { |name,data| Judo::Server.new(self, name, data["group"].first) }
155
+ @servers ||= servers_state.map { |id,data| Judo::Server.new(self, id, data["group"].first) }
156
156
  end
157
157
 
158
- def new_server(name, group)
159
- s = Judo::Server.new(self, name, group)
158
+ def new_server_id
159
+ rand(2**32).to_s(36)
160
+ end
161
+
162
+ def mk_server_name(group)
163
+ index = servers.map { |s| (s.name =~ /^#{s.group.name}.(\d*)$/); $1.to_i }.sort.last.to_i + 1
164
+ "#{group.name}.#{index}"
165
+ end
166
+
167
+ def create_server(name, group, options)
168
+ s = Judo::Server.new(self, new_server_id, group)
160
169
  servers << s
170
+ s.create(name, options)
161
171
  s
162
172
  end
163
173
 
@@ -217,6 +227,19 @@ module Judo
217
227
  @group_version ||= sdb.get_attributes(base_domain, "group_versions")[:attributes]
218
228
  end
219
229
 
230
+ def set_keypair(key_name, material)
231
+ s3_put("#{key_name}.pem", material)
232
+ update "key_name" => key_name
233
+ end
234
+
235
+ def key_name
236
+ get("key_name")
237
+ end
238
+
239
+ def key_material
240
+ s3_get("#{key_name}.pem")
241
+ end
242
+
220
243
  def ip_to_judo(ip)
221
244
  servers.detect { |s| s.elastic_ip == ip }
222
245
  end
@@ -267,8 +290,14 @@ module Judo
267
290
  @access_secret || (raise JudoError, "no AWS Secret Key specified")
268
291
  end
269
292
 
293
+ ## this is a little funny - does not work like the others - can specify bucket on cmdline or env - but if not takes from judo state
270
294
  def bucket_name
271
- @bucket_name || (raise JudoError, "no S3 bucket name specified")
295
+ (@bucket_name ||= get("bucket")) || (raise JudoError, "no S3 bucket name specified")
296
+ end
297
+
298
+ def set_bucket_name(new_name)
299
+ @bucket_name = new_name
300
+ update "bucket" => @bucket_name
272
301
  end
273
302
 
274
303
  def db_version
@@ -295,12 +324,25 @@ module Judo
295
324
  end
296
325
 
297
326
  def set_db_version(new_version)
298
- @db_version = new_version
299
- sdb.put_attributes(base_domain, "judo", { "dbversion" => new_version }, :replace)
327
+ update "dbversion" => new_version
300
328
  end
301
329
 
302
330
  def get_db_version
303
- @db_version ||= (sdb.get_attributes(base_domain, "judo")[:attributes]["dbversion"] || []).first.to_i
331
+ get("dbversion").to_i
332
+ end
333
+
334
+ def get(key)
335
+ state[key] && [state[key]].flatten.first
336
+ end
337
+
338
+ ## i'm copy pasting code from server - this needs to be its own module
339
+ def update(attrs)
340
+ sdb.put_attributes(base_domain, "judo", attrs, :replace)
341
+ state.merge! attrs
342
+ end
343
+
344
+ def state
345
+ @state ||= sdb.get_attributes(base_domain, "judo")[:attributes]
304
346
  end
305
347
 
306
348
  def check_version
@@ -311,15 +353,14 @@ module Judo
311
353
  end
312
354
 
313
355
  def setup
314
- ## no need to setup bucket
315
-
316
356
  @repo ||= "." ## use cwd as default repo dir
317
357
 
318
358
  setup_sdb
359
+ setup_keypair
360
+ setup_bucket
319
361
  setup_security_group
320
362
  setup_judo_config
321
363
  setup_repo
322
- get_group("default").compile
323
364
  end
324
365
 
325
366
  def setup_sdb
@@ -345,9 +386,13 @@ module Judo
345
386
  raise JudoError, "You must specify a repo dir" unless repo
346
387
  task("writing .judo/config.yml") do
347
388
  Dir.chdir(repo) do
348
- system "mkdir .judo"
349
- File.open(".judo/config.yml","w") do |f|
350
- f.write({ "access_id" => access_id, "access_secret" => access_secret, "s3_bucket" => bucket_name }.to_yaml)
389
+ if File.exists?(".judo/config.yml")
390
+ puts ".judo folder already exists"
391
+ else
392
+ system "mkdir .judo"
393
+ File.open(".judo/config.yml","w") do |f|
394
+ f.write({ "access_id" => access_id, "access_secret" => access_secret, "s3_bucket" => bucket_name }.to_yaml)
395
+ end
351
396
  end
352
397
  end
353
398
  end
@@ -360,14 +405,34 @@ module Judo
360
405
  end
361
406
  task("Setting up default group") do
362
407
  Dir.chdir(repo) do
363
- system "mkdir -p default/keypairs"
408
+ File.open("default/config.json","w") { |f| f.write default_config }
409
+ end
410
+ get_group("default").compile
411
+ end
412
+ end
364
413
 
365
- @keypair = "judo#{ec2.describe_key_pairs.map { |k| k[:aws_key_name] }.map { |k| k =~ /^judo(\d*)/; $1.to_i }.sort.last.to_i + 1}"
366
- material = ec2.create_key_pair(@keypair)[:aws_material]
414
+ def keypair_file(&blk)
415
+ Tempfile.open("judo_pem") do |file|
416
+ file.write key_material
417
+ file.flush
418
+ blk.call(file.path)
419
+ end
420
+ end
367
421
 
368
- File.open("default/keypairs/#{@keypair}.pem", 'w') { |f| f.write material }
369
- File.chmod 0600, "default/keypairs/#{@keypair}.pem"
370
- File.open("default/config.json","w") { |f| f.write default_config }
422
+ def setup_bucket
423
+ if name = get("bucket_name")
424
+ puts "Bucket #{name} already set"
425
+ else
426
+ set_bucket_name(bucket_name)
427
+ end
428
+ end
429
+
430
+ def setup_keypair
431
+ unless key_name
432
+ task("Generating an ssl keyapir") do
433
+ name = "judo#{ec2.describe_key_pairs.map { |k| k[:aws_key_name] }.map { |k| k =~ /^judo(\d*)/; $1.to_i }.sort.last.to_i + 1}"
434
+ material = ec2.create_key_pair(name)[:aws_material]
435
+ set_keypair(name, material)
371
436
  end
372
437
  end
373
438
  end
@@ -375,7 +440,6 @@ module Judo
375
440
  def default_config
376
441
  <<DEFAULT
377
442
  {
378
- "key_name":"#{@keypair}",
379
443
  "instance_type":"m1.small",
380
444
  "ami32":"ami-bb709dd2", // public ubuntu 9.10 ami - 32 bit
381
445
  "ami64":"ami-55739e3c", // public ubuntu 9.10 ami - 64 bit
@@ -29,7 +29,8 @@ module JudoCommandLineHelpers
29
29
  groups.each { |group| judo_yield(group, blk) if blk }
30
30
  end
31
31
 
32
- def mk_servers(judo, args, &blk)
32
+ ## I dont like the way this is working anymore - needs refactor
33
+ def mk_servers(judo, options, args, &blk)
33
34
  servers = args.map do |arg|
34
35
  name,group = split(arg)
35
36
  group ||= judo.group
@@ -37,9 +38,9 @@ module JudoCommandLineHelpers
37
38
  if name =~ /^\+(\d+)/
38
39
  count = $1.to_i
39
40
  raise JudoError, "You can batch-create between 1 and 5 servers" if count < 1 or count > 5
40
- (1..count).map { judo.new_server(nil, group) }
41
+ (1..count).map { judo.create_server( judo.mk_server_name(group), group, options) }
41
42
  else
42
- judo.new_server(name, group)
43
+ judo.create_server(name, group, options)
43
44
  end
44
45
  end
45
46
  servers.flatten.each { |s| judo_yield(s, blk) if blk }
@@ -150,6 +151,7 @@ module JudoCommandLineHelpers
150
151
 
151
152
  def do_info(judo, server)
152
153
  puts "[ #{server} ]"
154
+ printf " %-24s: %s\n", "ID", server.id
153
155
  printf " %-24s: %s\n", "Group", server.group.name
154
156
  printf " %-24s: %s\n", "Note", server.note if server.note
155
157
  printf " %-24s: %s\n", "Animated From", server.clone if server.clone
data/lib/judo/group.rb CHANGED
@@ -16,12 +16,12 @@ module Judo
16
16
  @build_config ||= all_configs.reverse.inject({}) { |sum,conf| sum.merge(conf) }
17
17
  end
18
18
 
19
- def server_names
20
- @server_names ||= (@base.groups_config[@name] || [])
19
+ def server_ids
20
+ @server_ids ||= (@base.groups_config[@name] || [])
21
21
  end
22
22
 
23
23
  def servers
24
- @base.servers.select { |s| server_names.include?(s.name) }
24
+ @base.servers.select { |s| server_ids.include?(s.name) }
25
25
  end
26
26
 
27
27
  def load_config
@@ -123,10 +123,6 @@ module Judo
123
123
  files
124
124
  end
125
125
 
126
- def keypair_file
127
- extract_file(:keypair, config["key_name"] + ".pem" , {}).first
128
- end
129
-
130
126
  def attachments(c = config)
131
127
  extract(c, {})
132
128
  end
@@ -169,7 +165,7 @@ module Judo
169
165
  end
170
166
 
171
167
  def delete_server(server)
172
- sdb.delete_attributes(@base.base_domain, "groups", name => server.name)
168
+ sdb.delete_attributes(@base.base_domain, "groups", name => server.id)
173
169
  end
174
170
 
175
171
  def to_s
data/lib/judo/server.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  module Judo
2
2
  class Server
3
- attr_accessor :name, :group_name
3
+ attr_accessor :id,:group_name
4
4
 
5
- def initialize(base, name, group, version = nil)
5
+ def initialize(base, id, group, version = nil)
6
6
  @base = base
7
- @name = name
7
+ @id = id
8
8
  @group_name = group
9
9
  end
10
10
 
11
- def create(options)
11
+ def create(name, options)
12
12
  raise JudoError, "no group specified" unless group_name
13
13
 
14
14
  options[:virgin] = true if options[:virgin].nil?
@@ -18,23 +18,21 @@ module Judo
18
18
  data = options[:data] ## instance specific data passed in JUDO_DATA
19
19
  ip = options[:elastic_ip] ## if the ip was allocated beforehand
20
20
  virgin = options[:virgin] ## should the server init?
21
+ clone = options[:clone] ## if it was cloned from a snapshot
21
22
 
22
23
  version = options[:version]
23
24
  version ||= group.version
24
25
 
25
- if @name.nil?
26
- index = @base.servers.map { |s| (s.name =~ /^#{s.group.name}.(\d*)$/); $1.to_i }.sort.last.to_i + 1
27
- @name = "#{group.name}.#{index}"
28
- end
29
-
30
- raise JudoError, "there is already a server named #{name}" if @base.servers.detect { |s| s.name == @name and s != self}
26
+ raise JudoError, "there is already a server named #{name}" if @base.servers.detect { |s| s.name == name and s != self}
27
+ raise JudoError, "there is already a server with id #{id}" if @base.servers.detect { |s| s.id == id and s != self}
31
28
 
32
29
  task("Creating server #{name}") do
33
30
  update "name" => name, "group" => group_name,
34
31
  "note" => note, "virgin" => virgin,
35
32
  "secret" => new_secret, "version" => version,
36
- "data" => data, "elastic_ip" => ip
37
- @base.sdb.put_attributes(@base.base_domain, "groups", group_name => name)
33
+ "data" => data, "elastic_ip" => ip,
34
+ "clone" => clone, "created_at" => Time.now.to_i
35
+ @base.sdb.put_attributes(@base.base_domain, "groups", group_name => id)
38
36
  end
39
37
 
40
38
  allocate_disk(snapshots)
@@ -48,17 +46,33 @@ module Judo
48
46
  end
49
47
 
50
48
  def fetch_state
51
- @base.sdb.get_attributes(@base.server_domain, name)[:attributes]
49
+ @base.sdb.get_attributes(@base.server_domain, id)[:attributes]
52
50
  end
53
51
 
54
52
  def state
55
- @base.servers_state[name] ||= fetch_state
53
+ @base.servers_state[id] ||= fetch_state
56
54
  end
57
55
 
58
56
  def get(key)
59
57
  state[key] && [state[key]].flatten.first
60
58
  end
61
59
 
60
+ def created_at
61
+ Time.at(get("created_at").to_i)
62
+ end
63
+
64
+ def started_at
65
+ Time.at(get("started_at").to_i)
66
+ end
67
+
68
+ def stopped_at
69
+ Time.at(get("stopped_at").to_i)
70
+ end
71
+
72
+ def name
73
+ get "name"
74
+ end
75
+
62
76
  def data
63
77
  get "data"
64
78
  end
@@ -128,28 +142,28 @@ module Judo
128
142
  end
129
143
 
130
144
  def update(attrs)
131
- @base.sdb.put_attributes(@base.server_domain, name, attrs, :replace)
145
+ @base.sdb.put_attributes(@base.server_domain, id, attrs, :replace)
132
146
  state.merge! attrs
133
147
  end
134
148
 
135
149
  def add(key, value)
136
- @base.sdb.put_attributes(@base.server_domain, name, { key => value })
150
+ @base.sdb.put_attributes(@base.server_domain, id, { key => value })
137
151
  (state[key] ||= []) << value
138
152
  end
139
153
 
140
154
  def remove(key, value = nil)
141
155
  if value
142
- @base.sdb.delete_attributes(@base.server_domain, name, key => value)
156
+ @base.sdb.delete_attributes(@base.server_domain, id, key => value)
143
157
  state[key] - [value]
144
158
  else
145
- @base.sdb.delete_attributes(@base.server_domain, name, [ key ])
159
+ @base.sdb.delete_attributes(@base.server_domain, id, [ key ])
146
160
  state.delete(key)
147
161
  end
148
162
  end
149
163
 
150
164
  def delete
151
165
  group.delete_server(self) if group
152
- @base.sdb.delete_attributes(@base.server_domain, name)
166
+ @base.sdb.delete_attributes(@base.server_domain, id)
153
167
  end
154
168
 
155
169
  ######## end simple DB access #######
@@ -339,7 +353,7 @@ module Judo
339
353
  result = @base.ec2.launch_instances(ami,
340
354
  :instance_type => instance_type,
341
355
  :availability_zone => config["availability_zone"],
342
- :key_name => config["key_name"],
356
+ :key_name => @base.key_name,
343
357
  :group_ids => security_groups,
344
358
  :user_data => ud).first
345
359
  update "instance_id" => result[:aws_instance_id], "virgin" => false, "started_at" => Time.now.to_i
@@ -474,8 +488,9 @@ module Judo
474
488
 
475
489
  def connect_ssh
476
490
  wait_for_ssh
477
- system "chmod 600 #{group.keypair_file}"
478
- system "ssh -i #{group.keypair_file} #{config["user"]}@#{hostname}"
491
+ @base.keypair_file do |file|
492
+ system "ssh -i #{file} #{config["user"]}@#{hostname}"
493
+ end
479
494
  end
480
495
 
481
496
  def ec2_instance_type
@@ -488,7 +503,7 @@ module Judo
488
503
 
489
504
  def reload
490
505
  @base.reload_ec2_instances
491
- @base.servers_state.delete(name)
506
+ @base.servers_state.delete(id)
492
507
  end
493
508
 
494
509
  def user_data(judo_boot = nil)
@@ -497,7 +512,8 @@ module Judo
497
512
 
498
513
  export DEBIAN_FRONTEND="noninteractive"
499
514
  export DEBIAN_PRIORITY="critical"
500
- export JUDO_ID='#{name}'
515
+ export JUDO_ID='#{id}'
516
+ export JUDO_NAME='#{name}'
501
517
  export JUDO_DOMAIN='#{@base.domain}'
502
518
  export JUDO_BOOT='#{judo_boot}'
503
519
  export JUDO_DATA='#{data}'
@@ -532,13 +548,22 @@ USER_DATA
532
548
  end
533
549
 
534
550
  def snapshot(name)
535
- snap = @base.new_snapshot(name, self.name)
551
+ snap = @base.new_snapshot(name, id)
536
552
  snap.create
553
+ snap
554
+ end
555
+
556
+ def rename(newname)
557
+ raise JudoError, "Already a server with that name" if @base.servers.detect { |s| s.name == newname }
558
+ task("Renaming to #{newname}") do
559
+ update "name" => newname
560
+ end
537
561
  end
538
562
 
539
- def swapip(other)
563
+ def swap(other)
540
564
  ip1 = elastic_ip
541
565
  ip2 = other.elastic_ip
566
+
542
567
  raise JudoError, "Server must have an elastic IP to swap" unless ip1 and ip2
543
568
 
544
569
  task("Swapping Ip Addresses") do
@@ -551,6 +576,13 @@ USER_DATA
551
576
  update "elastic_ip" => ip2
552
577
  other.update "elastic_ip" => ip1
553
578
  end
579
+
580
+ task("Swapping Names") do
581
+ name1 = name
582
+ name2 = other.name
583
+ update "name" => name2
584
+ other.update "name" => name1
585
+ end
554
586
  end
555
587
 
556
588
  def <=>(s)
data/lib/judo/snapshot.rb CHANGED
@@ -1,25 +1,29 @@
1
1
  module Judo
2
- ### sdb
3
- ### name {
4
- ### "version" => [ server.version ],
2
+ ### sdb
3
+ ### name {
4
+ ### "version" => [ server.version ],
5
5
  ### "devs" => [ "/dev/sde1:snap-abc123", "/dev/sde2:snap-abc456" ],
6
- ### "server" => server.name
6
+ ### "server" => server.id
7
7
  ### "group" => server.group.name
8
8
  ### "virgin" => server.virgin
9
9
  ### "note" => server.note
10
10
  ### "data" => server.data
11
11
  ### "created_at" => unixtime
12
12
  class Snapshot
13
- attr_accessor :name, :server_name
13
+ attr_accessor :name, :server_id
14
14
 
15
- def initialize(base, name, server_name)
15
+ def initialize(base, name, server_id)
16
16
  @base = base
17
17
  @name = name
18
- @server_name = server_name
18
+ @server_id = server_id
19
+ end
20
+
21
+ def server_name
22
+ server.name rescue '(deleted)'
19
23
  end
20
24
 
21
25
  def server
22
- @server ||= @base.servers.detect { |s| s.name == @server_name }
26
+ @server ||= @base.servers.detect { |s| s.id == server_id }
23
27
  end
24
28
 
25
29
  def fetch_state
@@ -35,7 +39,7 @@ module Judo
35
39
  end
36
40
 
37
41
  def created_at
38
- Time.at(get("time").to_i)
42
+ Time.at(get("created_at").to_i)
39
43
  end
40
44
 
41
45
  def version
@@ -65,13 +69,13 @@ module Judo
65
69
  devs = server.volumes.map do |dev,vol|
66
70
  "#{dev}:#{@base.ec2.create_snapshot(vol)[:aws_id]}"
67
71
  end
68
- @base.sdb.put_attributes(@base.snapshot_domain, name, {
69
- "version" => server.version,
70
- "virgin" => server.virgin?,
71
- "note" => server.note,
72
- "data" => server.data,
73
- "devs" => devs,
74
- "server" => server.name,
72
+ @base.sdb.put_attributes(@base.snapshot_domain, name, {
73
+ "version" => server.version,
74
+ "virgin" => server.virgin?,
75
+ "note" => server.note,
76
+ "data" => server.data,
77
+ "devs" => devs,
78
+ "server" => server.id,
75
79
  "group" => server.group.name,
76
80
  "created_at" => Time.now.to_i.to_s
77
81
  }, :replace)
@@ -79,17 +83,14 @@ module Judo
79
83
  end
80
84
  end
81
85
 
82
- def animate(new_server, version = self.version)
86
+ def animate(new_server)
83
87
  raise JudoError, "cannot animate, snapshotting not complete" unless completed?
84
- server = @base.new_server(new_server, group_name)
85
- server.create( :version => version, :snapshots => devs, :virgin => virgin, :note => note, :data => data )
86
- server.update "clone" => name ##, "secret" => rand(2 ** 128).to_s(36) ## cant change this till kuzushi knows about a post-clone operation
87
- server
88
+ @base.create_server(new_server, group_name, :version => version, :snapshots => devs, :virgin => virgin, :note => note, :data => data , :clone => name)
88
89
  end
89
90
 
90
91
  def delete
91
92
  @base.sdb.delete_attributes(@base.snapshot_domain, name)
92
- server.remove "snapshots", name
93
+ server.remove("snapshots", name) if server
93
94
  end
94
95
 
95
96
  def get(key)
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 3
8
- - 1
9
- version: 0.3.1
8
+ - 2
9
+ version: 0.3.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Orion Henry
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-20 00:00:00 -04:00
17
+ date: 2010-05-21 00:00:00 -04:00
18
18
  default_executable: judo
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency