tell 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Cyril David
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ Tell
2
+ ====
3
+
4
+ Dead simple SSH access using what's already available.
5
+
6
+ First...
7
+ --------
8
+
9
+ Did you know you can do this?
10
+
11
+ $ ssh server1 -- git pull
12
+
13
+ The command above will connect to server1 (assuming you have something like
14
+ that in your SSH config (~/.ssh/config) and execute git pull upon connecting.
15
+
16
+ What this does?
17
+ ---------------
18
+
19
+ It wraps that command and makes it convenient to execute mutiple commands at
20
+ once.
21
+
22
+ Example:
23
+ --------
24
+
25
+ $ tell server1 -c "git pull" -c "rake cdn:update" -c "thin restart"
26
+
27
+ You can also execute commands against multiple servers.
28
+
29
+ $ tell server1 server2 -c "ls"
30
+
31
+ Within Ruby?
32
+ ------------
33
+
34
+ require "tell"
35
+
36
+ tell = Tell.new(["server1"]) do
37
+ execute "git pull"
38
+ execute "rake cdn:update"
39
+ execute "thin restart"
40
+ end
41
+
42
+ tell.run
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path("../lib/tell", File.dirname(__FILE__))
4
+ require "clap"
5
+
6
+ servers = []
7
+ servers << ARGV.shift until ARGV.empty? or ARGV.first.start_with?("-")
8
+
9
+ if ARGV.empty?
10
+ puts 'Usage: tell host1 [host2 [host3 ...]] -c "COMMAND" [-c "COMMAND2"]'
11
+ exit
12
+ end
13
+
14
+ tell = Tell.new(servers)
15
+
16
+ Clap.run ARGV,
17
+ "-c" => tell.method(:execute)
18
+
19
+ tell.run
@@ -0,0 +1,52 @@
1
+ class Tell
2
+ VERSION = "0.0.1"
3
+
4
+ # ANSI Colors for a better user experience.
5
+ # 1;32m - Green
6
+ # 1;37m - White
7
+ FORMAT = "\e[1;32m %10s\e[1;37m %s"
8
+
9
+ attr :servers
10
+
11
+ def initialize(servers = [], &block)
12
+ @servers = servers
13
+ @commands = []
14
+
15
+ instance_eval(&block) if block_given?
16
+ end
17
+
18
+ def execute(command)
19
+ @commands << command
20
+ end
21
+
22
+ def run
23
+ silence!
24
+
25
+ servers.each do |server|
26
+ log :connect, server
27
+
28
+ @commands.each do |command|
29
+ log :run, command
30
+
31
+ display exec(server, command)
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+ def log(type, message)
38
+ puts FORMAT % [type, message]
39
+ end
40
+
41
+ def exec(server, command)
42
+ `ssh #{server} -- #{command}`
43
+ end
44
+
45
+ def display(str, margin = 13)
46
+ puts str.gsub(/^/, " " * margin)
47
+ end
48
+
49
+ def silence!
50
+ STDERR.reopen(File.open("/dev/null", "w"))
51
+ end
52
+ end
@@ -0,0 +1,15 @@
1
+ require "cutest"
2
+ require "stringio"
3
+
4
+ require File.expand_path("../lib/tell", File.dirname(__FILE__))
5
+
6
+ def capture
7
+ begin
8
+ out, $stdout = $stdout, StringIO.new
9
+ yield
10
+ ensure
11
+ out, $stdout = $stdout, out
12
+ end
13
+
14
+ return out.string
15
+ end
@@ -0,0 +1,101 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ # one server
4
+ scope do
5
+ setup do |t|
6
+ Tell.new(["server1"])
7
+ end
8
+
9
+ test "execute with one command" do |t|
10
+ def t.exec(*args); "file1\nfile2"; end
11
+
12
+ out = capture do
13
+ t.execute "ls"
14
+ t.run
15
+ end
16
+
17
+ lines = out.split("\n")
18
+ assert Tell::FORMAT % ["connect", "server1"] == lines[0]
19
+ assert Tell::FORMAT % ["run", "ls"] == lines[1]
20
+
21
+ assert " file1" == lines[2]
22
+ assert " file2" == lines[3]
23
+ end
24
+
25
+ test "execute with two commands" do |t|
26
+ def t.exec(server, cmd)
27
+ case cmd
28
+ when "ls"
29
+ "file1\nfile2"
30
+ when "git pull"
31
+ "Already up to date."
32
+ end
33
+ end
34
+
35
+ out = capture do
36
+ t.execute "ls"
37
+ t.execute "git pull"
38
+ t.run
39
+ end
40
+
41
+ lines = out.split("\n")
42
+ assert Tell::FORMAT % ["connect", "server1"] == lines[0]
43
+
44
+ assert Tell::FORMAT % ["run", "ls"] == lines[1]
45
+ assert " file1" == lines[2]
46
+ assert " file2" == lines[3]
47
+
48
+ assert Tell::FORMAT % ["run", "git pull"] == lines[4]
49
+ assert " Already up to date." == lines[5]
50
+ end
51
+ end
52
+
53
+ # two servers
54
+ scope do
55
+ setup do |t|
56
+ Tell.new(["server1", "server2"])
57
+ end
58
+
59
+ test "execute" do |t|
60
+ def t.exec(*args); "file1\nfile2"; end
61
+
62
+ out = capture do
63
+ t.execute "ls"
64
+ t.run
65
+ end
66
+
67
+ lines = out.split("\n")
68
+ assert Tell::FORMAT % ["connect", "server1"] == lines[0]
69
+ assert Tell::FORMAT % ["run", "ls"] == lines[1]
70
+
71
+ assert " file1" == lines[2]
72
+ assert " file2" == lines[3]
73
+
74
+ assert Tell::FORMAT % ["connect", "server2"] == lines[4]
75
+ assert Tell::FORMAT % ["run", "ls"] == lines[5]
76
+
77
+ assert " file1" == lines[6]
78
+ assert " file2" == lines[7]
79
+ end
80
+ end
81
+
82
+ # within ruby
83
+ scope do
84
+ test "execute with one command" do |t|
85
+ tell = Tell.new(["server1"]) do
86
+ execute "ls"
87
+ end
88
+ def tell.exec(*args); "file1\nfile2"; end
89
+
90
+ out = capture do
91
+ tell.run
92
+ end
93
+
94
+ lines = out.split("\n")
95
+ assert Tell::FORMAT % ["connect", "server1"] == lines[0]
96
+ assert Tell::FORMAT % ["run", "ls"] == lines[1]
97
+
98
+ assert " file1" == lines[2]
99
+ assert " file2" == lines[3]
100
+ end
101
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tell
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Cyril David
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-29 00:00:00 +08:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: clap
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: cutest
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :development
45
+ version_requirements: *id002
46
+ description:
47
+ email: cyx@pipetodevnull.com
48
+ executables:
49
+ - tell
50
+ extensions: []
51
+
52
+ extra_rdoc_files: []
53
+
54
+ files:
55
+ - lib/tell.rb
56
+ - README.markdown
57
+ - LICENSE
58
+ - test/helper.rb
59
+ - test/tell_test.rb
60
+ - bin/tell
61
+ has_rdoc: true
62
+ homepage: http://github.com/cyx/tell
63
+ licenses: []
64
+
65
+ post_install_message:
66
+ rdoc_options: []
67
+
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 0
85
+ version: "0"
86
+ requirements: []
87
+
88
+ rubyforge_project:
89
+ rubygems_version: 1.3.7
90
+ signing_key:
91
+ specification_version: 2
92
+ summary: (T)hin Ruby Secure Sh(ell).
93
+ test_files: []
94
+