thor-ssh 0.1.7 → 0.1.8

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 CHANGED
@@ -4,6 +4,9 @@ ThorSsh takes thor and allows it to run from local to remote.
4
4
  It assumes that the sources are always local and the remotes
5
5
  are always remote.
6
6
 
7
+ ## ThorSsh Assumptions
8
+ For running as_user('other_user') the assumption is that your connection is logged in either as 1) root, or 2) a user who can sudo to root
9
+
7
10
  ## Use
8
11
  gem 'thor-ssh'
9
12
 
@@ -24,7 +27,7 @@ This is still a work in progress. The main issue is that calling #inside or any
24
27
  TODO: Get #inside working
25
28
  TODO: Add other features needed for provisioning system
26
29
  TODO: Make way to copy remote to remote
27
- TODO: Make local #run and #exec work
30
+ TODO: Update method blacklist
28
31
 
29
32
  ## Running Tests
30
33
  The test run through vagrant, which seemed logical since we want to test ssh stuff.
@@ -26,9 +26,9 @@ module ThorSsh
26
26
  # it is assumed to be local and a normal File class is returned
27
27
  def destination_files
28
28
  if self.destination_connection
29
- return @destination_files ||= RemoteFile.new(self.destination_connection)
29
+ return @destination_files ||= RemoteFile.new(self, self.destination_connection)
30
30
  else
31
- return @destination_files ||= LocalFile.new
31
+ return @destination_files ||= LocalFile.new(self)
32
32
  end
33
33
  end
34
34
 
@@ -37,12 +37,34 @@ module ThorSsh
37
37
  # the destination.
38
38
  def destination_server
39
39
  if self.destination_connection
40
- return @destination_server ||= RemoteServer.new(self.destination_connection)
40
+ return @destination_server ||= RemoteServer.new(self, self.destination_connection)
41
41
  else
42
- return @destination_server ||= LocalServer.new
42
+ return @destination_server ||= LocalServer.new(self)
43
43
  end
44
44
  end
45
45
 
46
+
47
+ # As user takes a block and runs the code inside the block as the
48
+ # specified user. All actions are run as the user
49
+ #
50
+ # === Parameters
51
+ # username<String>:: Who to run as
52
+ # options<String>:: A hash of options for how to get to this user
53
+ #
54
+ # === Options
55
+ # :shell - Boolean, should this be invoked in the shell for the user
56
+ def as_user(username, options={})
57
+ old_run_as_user = @run_as_user
58
+ @run_as_user = username
59
+ yield
60
+ @run_as_user = old_run_as_user
61
+ end
62
+
63
+ # The user commands should be run as as the moment
64
+ def run_as_user
65
+ @run_as_user
66
+ end
67
+
46
68
  def inside(dir='', config={}, &block)
47
69
  raise "inside is not implemented in thor-ssh, please use full paths"
48
70
  end
@@ -2,6 +2,12 @@ require 'fileutils'
2
2
 
3
3
  module ThorSsh
4
4
  class LocalFile
5
+ attr_reader :base
6
+
7
+ def initialize(base)
8
+ @base = base
9
+ end
10
+
5
11
  def exists?(path)
6
12
  File.exists?(path)
7
13
  end
@@ -2,6 +2,12 @@ require 'popen4'
2
2
 
3
3
  module ThorSsh
4
4
  class LocalServer
5
+ attr_reader :base
6
+
7
+ def initialize(base)
8
+ @base = base
9
+ end
10
+
5
11
  def run_with_codes(command)
6
12
  # pid, stdin, stdout, stderr = Open4::popen4(command)
7
13
  # ignored, status = Process::waitpid2 pid
@@ -2,29 +2,13 @@ require 'net/ssh'
2
2
  require 'net/sftp'
3
3
  require 'stringio'
4
4
 
5
- module ThorSsh
6
- class RemoteFileWriter
7
- def initialize(connection, file)
8
- @connection = connection
9
- @file = file
10
- @offset = 0
11
- end
12
-
13
- def write(data)
14
- puts "WRITE: #{data.size} @ #{@offset}"
15
- # io = StringIO.new(data)
16
- @connection.sftp.write!(@file, @offset, data)
17
-
18
- puts "WROTE1"
19
-
20
- @offset += data.size
21
- end
22
- end
23
-
5
+ module ThorSsh
24
6
  class RemoteFile
25
7
  attr_reader :connection
8
+ attr_reader :base
26
9
 
27
- def initialize(connection)
10
+ def initialize(base, connection)
11
+ @base = base
28
12
  @connection = connection
29
13
  end
30
14
 
@@ -39,7 +23,7 @@ module ThorSsh
39
23
  end
40
24
 
41
25
  def run(command)
42
- return connection.exec!(command)
26
+ return base.exec(command)
43
27
  end
44
28
 
45
29
  # Creates the directory at the path on the remote server
@@ -62,45 +46,27 @@ module ThorSsh
62
46
  end
63
47
 
64
48
  def binread(path)
65
- data = nil
66
- connection.sftp.file.open(path, "rb") do |f|
67
- data = f.read
49
+ # If we first logged in as the running user
50
+ if base.destination_server.running_as_current_user?
51
+ data = nil
52
+ connection.sftp.file.open(path, "rb") do |f|
53
+ data = f.read
54
+ end
55
+ else
56
+ # We just run this as root, when reading we don't need to go back
57
+ # down to the user
58
+ data = @remote_test.destination_server.run("cat \"#{path}\"")
68
59
  end
69
-
60
+
70
61
  return data
71
62
  end
72
63
 
73
64
  # TODO: we should just move this to a more standard thing
74
65
  def binwrite(path, data)
75
- # puts "DATA: #{data.size}"
76
- # file = connection.sftp.open!(path, 'wb')
77
- #
78
- # # Write
79
- # connection.sftp.write!(file, 0, data)
80
- #
81
- # # Close
82
- # connection.sftp.close!(file)
83
-
84
66
  io = StringIO.new(data)
85
67
  connection.sftp.upload!(io, path)
86
68
  end
87
69
 
88
- def open(file_name, mode, &block)
89
- # Open file
90
- file = connection.sftp.open(file_name, 'wb', &method(:file_opened))#, {:chunk_size => 4096})
91
-
92
- file_writer = RemoteFileWriter.new(connection, file)
93
-
94
- yield(file_writer)
95
-
96
- # Close
97
- connection.sftp.close(file)
98
-
99
- # , {:chunk_size => 4096}
100
- # connection.sftp.file.open(file_name, mode, &block)
101
-
102
- end
103
-
104
70
  def chmod(mode, file_name)
105
71
  if mode.is_a?(Integer)
106
72
  # Mode is an integer, convert to octal
@@ -4,8 +4,10 @@ require 'net/sftp'
4
4
  module ThorSsh
5
5
  class RemoteServer
6
6
  attr_reader :connection
7
+ attr_reader :base
7
8
 
8
- def initialize(connection)
9
+ def initialize(base, connection)
10
+ @base = base
9
11
  @connection = connection
10
12
  end
11
13
 
@@ -41,12 +43,29 @@ module ThorSsh
41
43
 
42
44
  return stdout_data, stderr_data, exit_code, exit_signal
43
45
  end
46
+
47
+ def running_as_current_user?
48
+ base.run_as_user && connection.options[:user] != base.run_as_user
49
+ end
44
50
 
45
51
  def run(command, with_codes=false)
52
+ if running_as_current_user?
53
+ # We need to change to a different user
54
+ if base.run_as_user == 'root'
55
+ # We need to go up to root
56
+ command = "sudo #{command}"
57
+ else
58
+ # We need to go up to root, then down to this user
59
+ # This involves running sudo (to go up to root), then running
60
+ # sudo again as the new user, then running the command
61
+ command = "sudo sudo -u #{base.run_as_user} #{command}"
62
+ end
63
+ end
64
+ results = run_with_codes(command)
46
65
  if with_codes
47
- return run_with_codes(command)
66
+ return results
48
67
  else
49
- return connection.exec!(command)
68
+ return results.first
50
69
  end
51
70
  end
52
71
 
@@ -1,3 +1,3 @@
1
1
  module ThorSsh
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.8"
3
3
  end
data/spec/actions_spec.rb CHANGED
@@ -182,7 +182,6 @@ describe ThorSsh do
182
182
  stdout, stderr, exit_code, exit_signal = @local_test.exec('true', true)
183
183
  exit_code.should == 0
184
184
  end
185
-
186
185
  end
187
186
 
188
187
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thor-ssh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
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: 2012-05-25 00:00:00.000000000 Z
12
+ date: 2012-05-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -205,7 +205,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
205
205
  version: '0'
206
206
  segments:
207
207
  - 0
208
- hash: 1900233715508289127
208
+ hash: 1762345843444454679
209
209
  required_rubygems_version: !ruby/object:Gem::Requirement
210
210
  none: false
211
211
  requirements:
@@ -214,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
214
  version: '0'
215
215
  segments:
216
216
  - 0
217
- hash: 1900233715508289127
217
+ hash: 1762345843444454679
218
218
  requirements: []
219
219
  rubyforge_project:
220
220
  rubygems_version: 1.8.22