management 1.1 → 1.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/README.md +9 -1
- data/lib/management.rb +4 -1
- data/lib/management/command.rb +17 -7
- data/lib/management/commands/attach_address.rb +20 -0
- data/lib/management/commands/destroy_servers.rb +27 -0
- data/lib/management/commands/list_addresses.rb +31 -0
- data/lib/management/commands/open_console.rb +16 -0
- data/lib/management/commands/run_script.rb +14 -20
- data/lib/management/commands/start_server.rb +2 -1
- data/lib/management/commands/stop_server.rb +2 -1
- data/lib/management/helper.rb +7 -1
- data/lib/management/interpreter.rb +1 -1
- data/lib/management/version.rb +1 -1
- data/management.gemspec +1 -1
- data/spec/main_spec.rb +44 -9
- metadata +9 -6
- data/lib/management/commands/destroy_server.rb +0 -25
data/README.md
CHANGED
@@ -2,10 +2,18 @@
|
|
2
2
|
|
3
3
|
Minimalist EC2 configuration & deployment tool.
|
4
4
|
|
5
|
-
- Version: **1.
|
5
|
+
- Version: **1.2**
|
6
6
|
|
7
7
|

|
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/
|
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'
|
data/lib/management/command.rb
CHANGED
@@ -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 =
|
28
|
-
req
|
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
|
-
|
34
|
-
num_req_args = fn.arity
|
44
|
+
arity = self.true_arity
|
35
45
|
|
36
|
-
error_handler.call "not enough arguments" if args.count <
|
37
|
-
error_handler.call "too many arguments" if args.count >
|
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
|
@@ -24,21 +24,28 @@ module Management
|
|
24
24
|
|
25
25
|
case type.to_sym
|
26
26
|
when :copy
|
27
|
-
|
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
|
-
|
30
|
-
|
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)
|
data/lib/management/helper.rb
CHANGED
@@ -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
|
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 }
|
data/lib/management/version.rb
CHANGED
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::
|
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.
|
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-
|
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:
|
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: :
|
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:
|
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/
|
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
|