management 1.1 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,10 +2,18 @@
2
2
 
3
3
  Minimalist EC2 configuration & deployment tool.
4
4
 
5
- - Version: **1.1**
5
+ - Version: **1.2**
6
6
 
7
7
  ![build status](https://travis-ci.org/sdegutis/management.svg?branch=master)
8
8
 
9
+ #### Install
10
+
11
+ `gem install management`
12
+
13
+ #### Intro
14
+
15
+ Read [this short blog post](http://sdegutis.github.io/2014/06/09/announcing-management/) for a brief summary of this project.
16
+
9
17
  #### Usage
10
18
 
11
19
  ```
data/lib/management.rb CHANGED
@@ -5,8 +5,11 @@ require_relative 'management/helper'
5
5
  require_relative 'management/command'
6
6
  require_relative 'management/commands/create_server'
7
7
  require_relative 'management/commands/list_servers'
8
- require_relative 'management/commands/destroy_server'
8
+ require_relative 'management/commands/destroy_servers'
9
9
  require_relative 'management/commands/start_server'
10
10
  require_relative 'management/commands/stop_server'
11
11
  require_relative 'management/commands/run_script'
12
12
  require_relative 'management/commands/ssh_server'
13
+ require_relative 'management/commands/list_addresses'
14
+ require_relative 'management/commands/attach_address'
15
+ require_relative 'management/commands/open_console'
@@ -18,23 +18,33 @@ module Management
18
18
  self.class.name.split('::').last.
19
19
  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
20
20
  gsub(/([a-z\d])([A-Z])/,'\1_\2').
21
- tr("_", "-").
21
+ tr('_', '-').
22
22
  downcase
23
23
  end
24
24
 
25
25
  def help_string
26
26
  return sprintf("%20s ", self.command_name) + fn.parameters.map do |req, name|
27
- name = "<#{name.to_s.sub('_name', '')}>"
28
- req == :opt ? "[#{name}]" : name
27
+ name = '<' + name.to_s.sub(/_names?/, '') + '>'
28
+ case req
29
+ when :opt then '[' + name + ']'
30
+ when :rest then name + ' [...]'
31
+ else name
32
+ end
29
33
  end.join(' ')
30
34
  end
31
35
 
36
+ def true_arity
37
+ min = fn.parameters.take_while{|req, name| req == :req}.count
38
+ max = fn.parameters.count
39
+ max = Float::INFINITY if max > 0 && fn.parameters.last.first == :rest
40
+ min..max
41
+ end
42
+
32
43
  def call_with(args, error_handler)
33
- num_all_args = fn.parameters.count
34
- num_req_args = fn.arity
44
+ arity = self.true_arity
35
45
 
36
- error_handler.call "not enough arguments" if args.count < num_req_args
37
- error_handler.call "too many arguments" if args.count > num_all_args
46
+ error_handler.call "not enough arguments" if args.count < arity.begin
47
+ error_handler.call "too many arguments" if args.count > arity.end
38
48
 
39
49
  fn.call *args
40
50
  end
@@ -0,0 +1,20 @@
1
+ require_relative '../command'
2
+
3
+ module Management
4
+
5
+ class AttachAddress < Management::Command
6
+
7
+ include Management::Helper
8
+
9
+ def run(address_name, server_name)
10
+ address = get_address(address_name)
11
+ server = get_server(server_name)
12
+
13
+ puts "Attaching #{address_name} to #{server_name}..."
14
+ address.server = server
15
+ puts "Done."
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../command'
2
+
3
+ module Management
4
+
5
+ class DestroyServers < Management::Command
6
+
7
+ include Management::Helper
8
+
9
+ def run(*server_names)
10
+ servers = server_names.map{|server_name| get_server(server_name)}
11
+
12
+ puts "You are about to delete the following servers:"
13
+ puts ['', *servers.map{ |server| " - #{server.name}" }, '', ''].join("\n")
14
+
15
+ print "Are you sure you want to do this? Type 'Yes' to continue, or anything else to abort: "
16
+ abort "Aborted." if $stdin.gets.chomp != 'Yes'
17
+
18
+ servers.each do |server|
19
+ puts "Destroying #{server.name}..."
20
+ server.destroy
21
+ puts "Done."
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,31 @@
1
+ require_relative '../command'
2
+
3
+ module Management
4
+
5
+ class ListAddresses < Management::Command
6
+
7
+ include Management::Helper
8
+
9
+ def run()
10
+ servers = live_servers
11
+
12
+ cols = [
13
+ {size: 20, title: "IP", fn: ->(addr){ addr.public_ip } },
14
+ {size: 20, title: "Server", fn: ->(addr){ s = servers.find{|server| server.id == addr.server_id }; s ? s.name : "n/a" } },
15
+ {size: 30, title: "Name", fn: ->(addr){ a = config[:addresses].find{|k, v| v == addr.public_ip}; a ? a.first : "n/a" } },
16
+ {size: 15, title: "Status", fn: ->(addr){ s = servers.find{|server| server.id == addr.server_id }; s ? s.state : "n/a" } },
17
+ ]
18
+
19
+ format = cols.map{|c| "%-#{c[:size]}s"}.join(" ") + "\n"
20
+
21
+ send :printf, *([format].concat(cols.map{|c|c[:title]}))
22
+ send :printf, *([format].concat(cols.map{|c|'-' * c[:size]}))
23
+
24
+ cloud.addresses.each do |address|
25
+ send :printf, *([format].concat(cols.map{|c|c[:fn].call address}))
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,16 @@
1
+ require_relative '../command'
2
+
3
+ module Management
4
+
5
+ class OpenConsole < Management::Command
6
+
7
+ include Management::Helper
8
+
9
+ def run()
10
+ require 'pry'
11
+ binding.pry
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -24,21 +24,28 @@ module Management
24
24
 
25
25
  case type.to_sym
26
26
  when :copy
27
- copy_file(server, *data)
27
+ local_path, remote_path, opts = *data
28
+ puts "############ Copying #{local_path} -> #{remote_path}"
29
+
30
+ copy_file(server, local_path, remote_path, opts)
28
31
  when :run
29
- run_remote_command(server, data)
30
- end
32
+ cmd = data
33
+ puts "############ Running #{cmd}"
31
34
 
35
+ code = run_remote_command(server, cmd)
36
+ if code != 0
37
+ abort "Failed. Exit code: #{code}"
38
+ end
39
+ end
32
40
  end
33
41
 
42
+ puts "############ Success!"
34
43
  end
35
44
 
36
45
  def copy_file(server, local_path, remote_path, opts = nil)
37
46
  should_template = opts && opts[:template]
38
47
  custom_chown = opts && opts[:chown]
39
48
 
40
- puts "Copying #{local_path} -> #{remote_path}"
41
-
42
49
  Dir.mktmpdir('management-file-dir') do |file_tmpdir|
43
50
 
44
51
  # copy to the fake "remote" path locally
@@ -63,27 +70,14 @@ module Management
63
70
  server.copy_file(local_tar_path, remote_tar_path)
64
71
  server.extract_tar(remote_tar_path)
65
72
  server.chown_r(remote_path, custom_chown) if custom_chown
66
-
67
73
  end
68
-
69
74
  end
70
-
71
75
  end
72
76
 
77
+ # returns error code
73
78
  def run_remote_command(server, cmd)
74
- puts "Running #{cmd}"
75
-
76
79
  result = server.ssh("#{cmd}").first
77
-
78
- if result.respond_to?(:status)
79
- puts
80
- puts "---------------------------"
81
- if result.status == 0
82
- puts "Success!"
83
- else
84
- puts "Failed. Exit code: #{result.status}"
85
- end
86
- end
80
+ return result.status
87
81
  end
88
82
 
89
83
  def missing_local_files(script)
@@ -8,8 +8,9 @@ module Management
8
8
 
9
9
  def run(server_name)
10
10
  server = get_server(server_name)
11
+ puts "Starting #{server_name}..."
11
12
  server.start
12
- puts "Started #{server_name}."
13
+ puts "Done."
13
14
  end
14
15
 
15
16
  end
@@ -8,8 +8,9 @@ module Management
8
8
 
9
9
  def run(server_name)
10
10
  server = get_server(server_name)
11
+ puts "Stopping #{server_name}..."
11
12
  server.stop
12
- puts "Stopped #{server_name}."
13
+ puts "Done."
13
14
  end
14
15
 
15
16
  end
@@ -25,8 +25,14 @@ module Management
25
25
  server
26
26
  end
27
27
 
28
+ def get_address(name)
29
+ addresses = cloud.addresses
30
+ ip = config[:addresses][name.to_sym] or invalid_selection "Invalid address: #{name}", config[:addresses].map(&:first)
31
+ addresses.find{|a| a.public_ip == ip} or abort "Could not find an address with the IP #{ip} (#{name})"
32
+ end
33
+
28
34
  def live_servers
29
- cloud.servers.reject{ |s| s.state == 'terminated' }
35
+ cloud.servers.reject{ |s| s.state == 'terminated' || s.state == 'shutting-down' }
30
36
  end
31
37
 
32
38
  def config
@@ -6,7 +6,7 @@ module Management
6
6
  commands = Management::Command.all
7
7
 
8
8
  parser = OptionParser.new do |opts|
9
- opts.banner = "Usage: management [command] [args*]"
9
+ opts.banner = "Usage: management [command [arg ...]]"
10
10
  opts.separator('')
11
11
  opts.separator('Commands:')
12
12
  commands.each { |command| opts.separator command.help_string }
@@ -1,3 +1,3 @@
1
1
  module Management
2
- VERSION = "1.1"
2
+ VERSION = "1.2"
3
3
  end
data/management.gemspec CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |s|
18
18
 
19
19
  s.add_dependency 'fog'
20
20
  s.add_dependency 'unf' # just to shut up the warnings
21
+ s.add_dependency 'pry'
21
22
 
22
23
  s.add_development_dependency 'rake'
23
- s.add_development_dependency 'pry'
24
24
  s.add_development_dependency 'fakefs'
25
25
  s.add_development_dependency 'rspec', '~> 3.0.0'
26
26
  s.add_development_dependency 'guard-rspec'
data/spec/main_spec.rb CHANGED
@@ -40,6 +40,41 @@ describe 'management' do
40
40
 
41
41
  before { subject.define_singleton_method(:raw_yaml) { YAML.load(SampleConfig) } }
42
42
 
43
+ describe Management::Command do
44
+
45
+ describe "true arity" do
46
+
47
+ around(:each) { |example| timeout(0.05, &example) }
48
+
49
+ it "considers 1 required arg to have 1..1 arity" do
50
+ subject.define_singleton_method(:run){|x|}
51
+ expect(subject.true_arity).to eq 1..1
52
+ end
53
+
54
+ it "considers 2 required args to have 2..2 arity" do
55
+ subject.define_singleton_method(:run){|x, y|}
56
+ expect(subject.true_arity).to eq 2..2
57
+ end
58
+
59
+ it "considers 2 required args and one optinal arg to have 2..3 arity" do
60
+ subject.define_singleton_method(:run){|x, y, z = nil|}
61
+ expect(subject.true_arity).to eq 2..3
62
+ end
63
+
64
+ it "considers 2 required args and a final rest arg to have 2..Float::INFINITY arity" do
65
+ subject.define_singleton_method(:run){|x, y, *z|}
66
+ expect(subject.true_arity).to eq 2..Float::INFINITY
67
+ end
68
+
69
+ it "considers 1 required arg, one optional arg, and a final rest arg to have 1..Float::INFINITY arity" do
70
+ subject.define_singleton_method(:run){|x, y = nil, *z|}
71
+ expect(subject.true_arity).to eq 1..Float::INFINITY
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
43
78
  describe Management::Helper do
44
79
 
45
80
  subject { Object.new.extend Management::Helper }
@@ -217,9 +252,9 @@ describe 'management' do
217
252
 
218
253
  end
219
254
 
220
- describe Management::DestroyServer do
255
+ describe Management::DestroyServers do
221
256
 
222
- let(:server) { double "server" }
257
+ let(:server) { double "server", name: "server-1" }
223
258
  before { allow(subject).to receive(:get_server).with("server-1").and_return(server) }
224
259
 
225
260
  it "destroys the given server if you type 'Yes' verbatim" do
@@ -230,13 +265,13 @@ describe 'management' do
230
265
  it "does not destroy the given server if you don't type 'Yes' verbatim" do
231
266
  expect(server).not_to receive(:destroy)
232
267
  without_stdout do
233
- with_stdin("yes\n") { subject.run("server-1") }
234
- with_stdin("Y\n") { subject.run("server-1") }
235
- with_stdin("y\n") { subject.run("server-1") }
236
- with_stdin("yep\n") { subject.run("server-1") }
237
- with_stdin("\n") { subject.run("server-1") }
238
- with_stdin("YES\n") { subject.run("server-1") }
239
- with_stdin("Yes.\n") { subject.run("server-1") }
268
+ expect{with_stdin("yes\n" ) { subject.run("server-1") }}.to raise_error SystemExit
269
+ expect{with_stdin("Y\n" ) { subject.run("server-1") }}.to raise_error SystemExit
270
+ expect{with_stdin("y\n" ) { subject.run("server-1") }}.to raise_error SystemExit
271
+ expect{with_stdin("yep\n" ) { subject.run("server-1") }}.to raise_error SystemExit
272
+ expect{with_stdin("\n" ) { subject.run("server-1") }}.to raise_error SystemExit
273
+ expect{with_stdin("YES\n" ) { subject.run("server-1") }}.to raise_error SystemExit
274
+ expect{with_stdin("Yes.\n") { subject.run("server-1") }}.to raise_error SystemExit
240
275
  end
241
276
  end
242
277
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: management
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.1'
4
+ version: '1.2'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-06-09 00:00:00.000000000 Z
12
+ date: 2014-06-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog
@@ -44,14 +44,14 @@ dependencies:
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
46
  - !ruby/object:Gem::Dependency
47
- name: rake
47
+ name: pry
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
51
  - - ! '>='
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
- type: :development
54
+ type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
@@ -60,7 +60,7 @@ dependencies:
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  - !ruby/object:Gem::Dependency
63
- name: pry
63
+ name: rake
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
@@ -140,9 +140,12 @@ files:
140
140
  - lib/ext/fog.rb
141
141
  - lib/management.rb
142
142
  - lib/management/command.rb
143
+ - lib/management/commands/attach_address.rb
143
144
  - lib/management/commands/create_server.rb
144
- - lib/management/commands/destroy_server.rb
145
+ - lib/management/commands/destroy_servers.rb
146
+ - lib/management/commands/list_addresses.rb
145
147
  - lib/management/commands/list_servers.rb
148
+ - lib/management/commands/open_console.rb
146
149
  - lib/management/commands/run_script.rb
147
150
  - lib/management/commands/ssh_server.rb
148
151
  - lib/management/commands/start_server.rb
@@ -1,25 +0,0 @@
1
- require_relative '../command'
2
-
3
- module Management
4
-
5
- class DestroyServer < Management::Command
6
-
7
- include Management::Helper
8
-
9
- def run(server_name)
10
- server = get_server(server_name)
11
-
12
- print "Are you sure you want to do this? Type 'Yes' to continue, or anything else to abort: "
13
- answer = $stdin.gets.chomp
14
-
15
- if answer == 'Yes'
16
- server.destroy
17
- puts "Destroyed."
18
- else
19
- puts "Aborted."
20
- end
21
- end
22
-
23
- end
24
-
25
- end