frontier 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 +2 -0
- data/README.md +74 -0
- data/bin/frontier +6 -0
- data/lib/frontier/adapter.rb +55 -0
- data/lib/frontier/channel.rb +29 -0
- data/lib/frontier/mixin/filesystem.rb +10 -0
- data/lib/frontier/mixin/process.rb +10 -0
- data/lib/frontier/mixin.rb +11 -0
- data/lib/frontier/proxy.rb +19 -0
- data/lib/frontier/shell.rb +18 -0
- data/lib/frontier/version.rb +6 -0
- data/lib/frontier.rb +11 -0
- metadata +79 -0
data/LICENSE
ADDED
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
|
2
|
+
Ruby sans frontiers
|
3
|
+
-------------------
|
4
|
+
|
5
|
+
A cross-host ruby bridge. Allows you to create and operate on objects
|
6
|
+
created in ruby runtimes on remote hosts. Frontier uses an ssh connection
|
7
|
+
and tunnels serializes method calls and replies through it. It's inspired
|
8
|
+
by Rush, but without the limitation of needing a server process running on
|
9
|
+
the remote host.
|
10
|
+
|
11
|
+
In its pure form, the shell simply forwards all missing methods to the unix
|
12
|
+
shell (bash or whatever you use). But you can extend the shell through
|
13
|
+
a system of mixins. There's a few builtin mixins, and you can write your own.
|
14
|
+
|
15
|
+
|
16
|
+
Mixins
|
17
|
+
------
|
18
|
+
|
19
|
+
* Filesystem: the 'filesystem' mixin provides the method `#[](glob)` which
|
20
|
+
returns an array of Pathname objects.
|
21
|
+
|
22
|
+
* Process: the 'process' mixin provides the method 'process' which uses
|
23
|
+
PQL internally to enumerate or find processes.
|
24
|
+
|
25
|
+
|
26
|
+
Limitations
|
27
|
+
-----------
|
28
|
+
|
29
|
+
Frontier uses Marshal internally to serialize objects and Marshal has certain
|
30
|
+
limitations which objects it can serialize. For example it can't serialize
|
31
|
+
Proc objects, bindings or IO objects. So you need to pay attention where the
|
32
|
+
object you created lives, whether on the local or remote host.
|
33
|
+
|
34
|
+
For example this won't work:
|
35
|
+
|
36
|
+
server.process.where(:command => /ruby/).each {|p| puts p }
|
37
|
+
|
38
|
+
But this will
|
39
|
+
|
40
|
+
server.process.where(:command => /ruby/).all.each {|p| puts p }
|
41
|
+
|
42
|
+
This is because where() returns a Plucky::Query object which lives on the
|
43
|
+
server, so passing a proc to it doesn't work. but where().all() returns an
|
44
|
+
Array which is lives in the process space on the local host and you can treat
|
45
|
+
it just like any other array.
|
46
|
+
|
47
|
+
|
48
|
+
Example
|
49
|
+
-------
|
50
|
+
|
51
|
+
require 'frontier'
|
52
|
+
|
53
|
+
server = Frontier::Shell.new('user@server.tld')
|
54
|
+
|
55
|
+
puts server.uname
|
56
|
+
puts server.ls '*.rb'
|
57
|
+
|
58
|
+
server.load('filesystem')
|
59
|
+
puts server['*.rb'].last
|
60
|
+
|
61
|
+
server.load('process')
|
62
|
+
puts local.process.where(:command => /ruby/).fields(:pid, :rss).all
|
63
|
+
|
64
|
+
|
65
|
+
References
|
66
|
+
----------
|
67
|
+
|
68
|
+
* [Rush](http://rush.heroku.com/)
|
69
|
+
* [PQL](http://github.com/wereHamster/process-query-language)
|
70
|
+
|
71
|
+
License
|
72
|
+
-------
|
73
|
+
|
74
|
+
Copyright (c) 2010 by Tomas "wereHamster" Carnecky (tomas.carnecky@gmail.com)
|
data/bin/frontier
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
module Frontier
|
3
|
+
|
4
|
+
class Adapter
|
5
|
+
|
6
|
+
def self.wrap(object)
|
7
|
+
case object
|
8
|
+
when Numeric, String, Exception
|
9
|
+
return object
|
10
|
+
when Array
|
11
|
+
return object.map { |o| wrap(o) }
|
12
|
+
when Hash
|
13
|
+
return object.merge(object) { |k, v| wrap(v) }
|
14
|
+
else
|
15
|
+
return Proxy.new(object)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@cache = {}
|
22
|
+
|
23
|
+
while true do
|
24
|
+
begin
|
25
|
+
request = Marshal.load($stdin)
|
26
|
+
|
27
|
+
if request[:object]
|
28
|
+
object = ObjectSpace._id2ref(request[:object])
|
29
|
+
else
|
30
|
+
object = self
|
31
|
+
end
|
32
|
+
|
33
|
+
reply = object.send(request[:name], *request[:args])
|
34
|
+
@cache[reply.object_id] = reply
|
35
|
+
Marshal.dump(Adapter.wrap(reply), $stdout)
|
36
|
+
rescue Exception => e
|
37
|
+
Marshal.dump(e, $stdout)
|
38
|
+
end
|
39
|
+
$stdout.flush
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def load(*mixins)
|
44
|
+
[*mixins].each do |mixin|
|
45
|
+
self.class.class_eval("include Frontier::Mixin::#{mixin.capitalize}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def method_missing(name, *args)
|
50
|
+
%x[#{name} #{args.join(' ')}]
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
module Frontier
|
3
|
+
|
4
|
+
class Channel
|
5
|
+
|
6
|
+
def self.hydrate(channel, object)
|
7
|
+
case object
|
8
|
+
when Array, Hash
|
9
|
+
object.each { |o| Channel.hydrate(channel, o) }
|
10
|
+
when Proxy
|
11
|
+
object.channel = channel
|
12
|
+
end
|
13
|
+
|
14
|
+
return object
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def initialize(host, port)
|
19
|
+
@channel = IO.popen("ssh #{host} frontier", "r+")
|
20
|
+
end
|
21
|
+
|
22
|
+
def submit(request)
|
23
|
+
Marshal.dump(request, @channel)
|
24
|
+
return Channel.hydrate(self, Marshal.load(@channel))
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module Frontier
|
3
|
+
|
4
|
+
class Proxy
|
5
|
+
attr_accessor :channel
|
6
|
+
|
7
|
+
def initialize(object)
|
8
|
+
@typename = object.class.to_s
|
9
|
+
@object = object.object_id
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(name, *args)
|
13
|
+
request = { :object => @object, :name => name, :args => args }
|
14
|
+
return @channel.submit(request)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
module Frontier
|
3
|
+
|
4
|
+
class Shell
|
5
|
+
|
6
|
+
def initialize(host = 'localhost', port = 22)
|
7
|
+
@host = host
|
8
|
+
@port = port
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(name, *args)
|
12
|
+
@channel ||= Channel.new(@host, @port)
|
13
|
+
return @channel.submit({ :name => name, :args => args })
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/lib/frontier.rb
ADDED
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: frontier
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Tomas Carnecky
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-31 01:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description:
|
23
|
+
email:
|
24
|
+
- tomas.carnecky@gmail.com
|
25
|
+
executables:
|
26
|
+
- frontier
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- lib/frontier/adapter.rb
|
33
|
+
- lib/frontier/channel.rb
|
34
|
+
- lib/frontier/mixin/filesystem.rb
|
35
|
+
- lib/frontier/mixin/process.rb
|
36
|
+
- lib/frontier/mixin.rb
|
37
|
+
- lib/frontier/proxy.rb
|
38
|
+
- lib/frontier/shell.rb
|
39
|
+
- lib/frontier/version.rb
|
40
|
+
- lib/frontier.rb
|
41
|
+
- LICENSE
|
42
|
+
- README.md
|
43
|
+
- bin/frontier
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: http://github.com/wereHamster/frontier
|
46
|
+
licenses: []
|
47
|
+
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 3
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
hash: 3
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.3.7
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Ruby without borders
|
78
|
+
test_files: []
|
79
|
+
|