rsh2 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -2,8 +2,8 @@ require 'rake_ext'
2
2
 
3
3
  project(
4
4
  name: "rsh2",
5
- version: "0.0.2",
6
- summary: "Tiny wrapper over Net::SSH and Net::SFTP",
5
+ version: "0.0.3",
6
+ summary: "Tiny wrapper over Net::SSH/SFTP + small rake addon for cluster configuration management",
7
7
 
8
8
  author: "Alexey Petrushin",
9
9
  homepage: "http://github.com/alexeypetrushin/rssh"
data/lib/ros/rake.rb ADDED
@@ -0,0 +1,9 @@
1
+ def package *a, &b
2
+ task *a do |task, *args|
3
+ Ros.each_box_cached do |box|
4
+ package = Ros::Package.new task.name
5
+ package.configure_with &b
6
+ package.apply_to box
7
+ end
8
+ end
9
+ end
data/lib/ros/ros.rb ADDED
@@ -0,0 +1,57 @@
1
+ module Ros
2
+ class Dsl
3
+ attr_reader :package
4
+
5
+ def initialize package
6
+ @package = package
7
+ end
8
+
9
+ def applied? &b
10
+ package.applied = b
11
+ end
12
+
13
+ def apply &b
14
+ package.apply = b
15
+ end
16
+ end
17
+
18
+ class Package
19
+ attr_accessor :applied, :apply, :name
20
+
21
+ def initialize name
22
+ @name = name
23
+ end
24
+
25
+ def configure_with &b
26
+ dsl = Dsl.new self
27
+ dsl.instance_eval &b
28
+ end
29
+
30
+ def apply_to box
31
+ unless applied and applied.call(box)
32
+ print "applying '#{name}' to '#{box.options[:host]}'\n"
33
+ apply.call box
34
+ print "done\n"
35
+ end
36
+ end
37
+ end
38
+
39
+ class << self
40
+ def each_box_cached &b
41
+ unless @each_box_cached
42
+ unless Object.private_instance_methods(false).include?(:each_box)
43
+ raise "you must define 'each_box' method!"
44
+ end
45
+
46
+ @each_box_cached = []
47
+ each_box do |box|
48
+ @each_box_cached << box
49
+
50
+ # cache ssh connection
51
+ box.open_connection
52
+ end
53
+ end
54
+ @each_box_cached.each &b
55
+ end
56
+ end
57
+ end
data/lib/ros.rb ADDED
@@ -0,0 +1,4 @@
1
+ %w(
2
+ ros
3
+ rake
4
+ ).each{|f| require "ros/#{f}"}
data/lib/rsh/box.rb CHANGED
@@ -142,7 +142,33 @@ module Rsh
142
142
  driver.exec cmd
143
143
  end
144
144
 
145
+ def home path = nil
146
+ @home ||= bash('cd ~; pwd').gsub("\n", '')
147
+ "#{@home}#{path}"
148
+ end
149
+
150
+ def mark key
151
+ ensure_mark_requrements!
152
+ bash "touch #{marks_dir}/#{key}"
153
+ end
154
+
155
+ def has_mark? key
156
+ ensure_mark_requrements!
157
+ file_exist? "#{marks_dir}/#{key}"
158
+ end
159
+
145
160
  protected
161
+ def marks_dir
162
+ home "/.marks"
163
+ end
164
+
165
+ def ensure_mark_requrements!
166
+ unless @ensure_mark_requrements
167
+ create_directory marks_dir unless directory_exist? marks_dir
168
+ @ensure_mark_requrements = true
169
+ end
170
+ end
171
+
146
172
  def method_missing m, *a, &b
147
173
  driver.send m, *a, &b
148
174
  end
@@ -9,14 +9,14 @@ module Rsh
9
9
 
10
10
  def upload_file from_local_path, to_remote_path
11
11
  remote do |ssh, sftp|
12
- sftp.upload! from_local_path, to_remote_path
12
+ sftp.upload! from_local_path, fix_path(to_remote_path)
13
13
  end
14
14
  end
15
15
 
16
16
  def download_file from_remote_path, to_local_path
17
17
  File.open to_local_path, "w" do |out|
18
18
  remote do |ssh, sftp|
19
- sftp.download! from_remote_path, out #, :recursive => true
19
+ sftp.download! fix_path(from_remote_path), out #, :recursive => true
20
20
  end
21
21
  end
22
22
  end
@@ -24,7 +24,7 @@ module Rsh
24
24
  def exist? remote_file_path
25
25
  remote do |ssh, sftp|
26
26
  begin
27
- fattrs = sftp.stat! remote_file_path
27
+ fattrs = sftp.stat! fix_path(remote_file_path)
28
28
  fattrs.directory? or fattrs.file? or fattrs.symlink?
29
29
  rescue Net::SFTP::StatusException
30
30
  false
@@ -36,7 +36,7 @@ module Rsh
36
36
 
37
37
  def remove_file remote_file_path
38
38
  remote do |ssh, sftp|
39
- sftp.remove! remote_file_path
39
+ sftp.remove! fix_path(remote_file_path)
40
40
  end
41
41
  end
42
42
 
@@ -82,17 +82,31 @@ module Rsh
82
82
 
83
83
  def upload_directory from_local_path, to_remote_path
84
84
  remote do |ssh, sftp|
85
- sftp.upload! from_local_path, to_remote_path
85
+ sftp.upload! from_local_path, fix_path(to_remote_path)
86
86
  end
87
87
  end
88
88
 
89
89
  def download_directory from_remote_path, to_local_path
90
90
  remote do |ssh, sftp|
91
- sftp.download! from_remote_path, to_local_path, :recursive => true
91
+ sftp.download! fix_path(from_remote_path), to_local_path, :recursive => true
92
92
  end
93
93
  end
94
94
 
95
95
  protected
96
+ def fix_path path
97
+ path.sub(/^\~/, home)
98
+ end
99
+
100
+ def home
101
+ unless @home
102
+ command = 'cd ~; pwd'
103
+ code, stdout, stderr = exec command
104
+ raise "can't execute '#{command}'!" unless code == 0
105
+ @home = stdout.gsub("\n", '')
106
+ end
107
+ @home
108
+ end
109
+
96
110
  # taken from here http://stackoverflow.com/questions/3386233/how-to-get-exit-status-with-rubys-netssh-library/3386375#3386375
97
111
  def hacked_exec!(ssh, command, &block)
98
112
  stdout_data = ""
data/readme.md CHANGED
@@ -1,12 +1,9 @@
1
- # Tiny wrapper over Net::SSH and Net::SFTP
1
+ # Rsh - Tiny wrapper over Net::SSH/SFTP
2
2
 
3
3
  Because they are too hard to use and have terrible API design.
4
4
 
5
5
  box = Rsh::Box.new host: 'webapp.com', ssh: {user: 'root', password: 'secret'}
6
6
 
7
- stdout = box.bash 'ls /'
8
- code, stdout, stderr = box.exec 'ls /'
9
-
10
7
  box.upload_directory '/my_project', '/apps/my_project'
11
8
  box.bash 'nohup /apps/my_project/server_start'
12
9
 
@@ -14,6 +11,49 @@ Honestly my wrapper also not very good. I would like to make API looks like the
14
11
  but it requires a lots of time, maybe I'll do it later.
15
12
  So, for now it's just a small wrapper to do ssh/io operations not so painfull.
16
13
 
14
+ # Ros - Small rake addon for configuration/depoyment management and automation
15
+
16
+ It may be **usefull if Your claster has about 1-10 boxes**, and tools like Chef, Puppet, Capistrano are too complex and proprietary for your needs.
17
+ **It's extremely easy**, there are only 3 methods.
18
+
19
+ Define your packages, they are just rake tasks, so you probably know how to work with them:
20
+
21
+ namespace :os do
22
+ package :ruby do
23
+ applied?{|box| box.has_mark? :ruby}
24
+ apply do |box|
25
+ box.bash 'apt-get install ruby'
26
+ box.mark :ruby
27
+ end
28
+ end
29
+
30
+ package :rails => :ruby do
31
+ applied?{|box| box.has_mark? :rails}
32
+ apply do |box|
33
+ box.bash 'gem install rails'
34
+ box.mark :rails
35
+ end
36
+ end
37
+ end
38
+
39
+ Define to what it should be applied:
40
+
41
+ def each_box &b
42
+ host = ENV['host'] || raise(":host not defined!")
43
+ box = Rsh::Box.new host: host, ssh: {user: 'root', password: 'secret'}
44
+ b.call box
45
+ end
46
+
47
+ Run it:
48
+
49
+ $ rake os:rails host=webapp.com
50
+
51
+ **You can use it also for deployment**, exactly the same way, configure it the way you like, it's just rake
52
+ tasks. And by the way, the *box.mark ...* is just an example check, you can use anything there.
53
+
54
+ It checks if the package already has been applied to box, so you can evolve your configuration and apply
55
+ it multiple times, it will apply only missing packages (or drop the *applied?* clause and it will be applied every run).
56
+
17
57
  ## TODO
18
58
 
19
59
  - introduce Entity/Dir/File (the same as in Rush)
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Alexey Petrushin
@@ -30,6 +30,9 @@ files:
30
30
  - Rakefile
31
31
  - readme.md
32
32
  - lib/old/ssh.rb
33
+ - lib/ros/rake.rb
34
+ - lib/ros/ros.rb
35
+ - lib/ros.rb
33
36
  - lib/rsh/box.rb
34
37
  - lib/rsh/drivers/abstract.rb
35
38
  - lib/rsh/drivers/local.rb
@@ -79,6 +82,6 @@ rubyforge_project:
79
82
  rubygems_version: 1.3.7
80
83
  signing_key:
81
84
  specification_version: 3
82
- summary: Tiny wrapper over Net::SSH and Net::SFTP
85
+ summary: Tiny wrapper over Net::SSH/SFTP + small rake addon for cluster configuration management
83
86
  test_files: []
84
87