judo 0.3.1 → 0.3.2

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/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