LanGrove 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.watchr +11 -3
- data/Rakefile +12 -5
- data/functional/.gitignore +1 -0
- data/{bin/datagram_example → functional/bin/datagram} +2 -0
- data/{config/environments/development.rb → functional/config/.gitignore} +0 -0
- data/{config → functional/config}/boot.rb +0 -0
- data/functional/config/daemons.yml +12 -0
- data/{config → functional/config}/environment.rb +0 -0
- data/{config/environments/production.rb → functional/config/environments/development.rb} +0 -0
- data/{config/environments/test.rb → functional/config/environments/production.rb} +0 -0
- data/{lib/jobs/Rakefile → functional/config/environments/test.rb} +0 -0
- data/functional/lib/daemon/datagram.rb +23 -0
- data/functional/lib/handler/socket_to_file.rb +36 -0
- data/functional/lib/protocol/socket_to_file.rb +55 -0
- data/{libexec → functional/libexec}/daemon.rb +14 -3
- data/functional/log/.gitignore +3 -0
- data/functional/tmp/README +1 -0
- data/lib/langrove.rb +1 -0
- data/lib/langrove/_base.rb +26 -0
- data/lib/langrove/adaptor/base.rb +3 -0
- data/lib/langrove/adaptor/datagram.rb +27 -0
- data/lib/langrove/adaptor_base.rb +89 -0
- data/lib/langrove/client/base.rb +2 -0
- data/lib/langrove/client/datagram.rb +28 -0
- data/lib/langrove/client_base.rb +114 -0
- data/lib/langrove/daemon/base.rb +2 -0
- data/lib/{daemon_base.rb → langrove/daemon_base.rb} +30 -23
- data/lib/langrove/ext.rb +7 -0
- data/lib/langrove/ext/class_loader.rb +146 -0
- data/lib/{ext → langrove/ext}/config_item.rb +4 -5
- data/lib/{ext → langrove/ext}/config_loader.rb +2 -2
- data/lib/langrove/ext/fake_logger.rb +8 -0
- data/lib/{ext → langrove/ext}/persistable.rb +2 -2
- data/lib/{ext → langrove/ext}/string.rb +0 -0
- data/lib/langrove/handler/base.rb +2 -0
- data/lib/{handler_base.rb → langrove/handler_base.rb} +25 -9
- data/lib/langrove/protocol/base.rb +2 -0
- data/lib/langrove/protocol/syslog.rb +32 -0
- data/lib/langrove/protocol_base.rb +32 -0
- data/lib/langrove/version.rb +3 -0
- data/spec/functional/daemon/datagram_spec.rb +115 -0
- data/spec/langrove/adaptor/datagram_spec.rb +6 -0
- data/spec/langrove/adaptor_base_spec.rb +48 -0
- data/spec/langrove/client/datagram_spec.rb +1 -0
- data/spec/langrove/client_base_spec.rb +5 -0
- data/spec/langrove/daemon_base_spec.rb +101 -0
- data/spec/langrove/ext/class_loader_spec.rb +83 -0
- data/spec/langrove/ext/config_item_spec.rb +81 -0
- data/spec/langrove/ext/config_loader_spec.rb +5 -0
- data/{tmp/TMP → spec/langrove/ext/fake_logger_spec.rb} +0 -0
- data/spec/{ext → langrove/ext}/persistable_spec.rb +8 -9
- data/spec/{ext → langrove/ext}/string_spec.rb +1 -1
- data/spec/langrove/handler_base_spec.rb +57 -0
- data/spec/langrove/protocol/syslog_spec.rb +45 -0
- data/spec/langrove/protocol_base_spec.rb +6 -0
- data/spec/todo_spec.rb +1 -2
- data/tmp/README +2 -0
- metadata +150 -46
- data/config/daemons.yml.tmpl +0 -78
- data/lib/adaptor/base.rb +0 -1
- data/lib/adaptor/datagram.rb +0 -20
- data/lib/adaptor/socket_handler.rb +0 -27
- data/lib/adaptor_base.rb +0 -39
- data/lib/client/base.rb +0 -1
- data/lib/client/puppet_state.rb +0 -74
- data/lib/client/radio_state.rb +0 -81
- data/lib/client_base.rb +0 -24
- data/lib/daemon/base.rb +0 -1
- data/lib/daemon/datagram_example.rb +0 -12
- data/lib/handler/base.rb +0 -1
- data/lib/handler/socket_to_file.rb +0 -30
- data/lib/jobs/jobs.rb +0 -1
- data/lib/jobs/updated_puppet_state.rb +0 -17
- data/lib/protocol_base.rb +0 -5
- data/spec/adaptor/datagram_spec.rb +0 -6
- data/spec/adaptor/socket_handler_spec.rb +0 -5
- data/spec/adaptor_base_spec.rb +0 -45
- data/spec/client_base_spec.rb +0 -5
- data/spec/daemon_base_spec.rb +0 -97
- data/spec/ext/config_item_spec.rb +0 -77
- data/spec/ext/config_loader_spec.rb +0 -5
- data/spec/functional/datagram_spec.rb +0 -122
- data/spec/handler_base_spec.rb +0 -71
- data/spec/protocol_base_spec.rb +0 -6
data/.watchr
CHANGED
@@ -13,7 +13,15 @@ watch("spec/.*/*_spec.rb") do |match|
|
|
13
13
|
run_spec match[0]
|
14
14
|
end
|
15
15
|
|
16
|
-
watch("
|
17
|
-
|
18
|
-
|
16
|
+
watch("(.*/*).rb") do |match|
|
17
|
+
file = match[1]
|
18
|
+
file.gsub!('lib/','')
|
19
|
+
file.gsub!('spec/','')
|
20
|
+
file.sub!('_spec','')
|
21
|
+
puts "====#{file}==="
|
22
|
+
if /demo/.match(match[0]) then
|
23
|
+
run_spec %{spec/#{file}_spec.rb}
|
24
|
+
next
|
25
|
+
end
|
26
|
+
run_spec %{spec/#{file}_spec.rb}
|
19
27
|
end
|
data/Rakefile
CHANGED
@@ -3,15 +3,22 @@ $LOAD_PATH.unshift 'lib'
|
|
3
3
|
desc "Publish a new version to ruby-gems.org"
|
4
4
|
task :publish do
|
5
5
|
require 'langrove/version'
|
6
|
-
|
6
|
+
|
7
7
|
sh "gem build langrove.gemspec"
|
8
8
|
sh "gem push langrove-#{LanGrove::Version}.gem"
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
sh "git tag v#{LanGrove::Version}"
|
11
|
+
sh "git push origin v#{LanGrove::Version}"
|
12
|
+
sh "git push origin master"
|
13
|
+
sh "git clean -fd"
|
14
14
|
|
15
15
|
# exec "rake documentation"
|
16
16
|
|
17
17
|
end
|
18
|
+
|
19
|
+
desc "Push to github"
|
20
|
+
task :push_world do
|
21
|
+
|
22
|
+
puts "TODO"
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
tmp/*.*
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'langrove/daemon/base'
|
2
|
+
|
3
|
+
class Datagram < LanGrove::Daemon::Base
|
4
|
+
|
5
|
+
#
|
6
|
+
# Consider tossing this dependancy.
|
7
|
+
#
|
8
|
+
# Not entirely certain this layer in the abstraction
|
9
|
+
# will be useful.
|
10
|
+
#
|
11
|
+
# Except, by
|
12
|
+
#
|
13
|
+
# << using this layer in the abstraction >>
|
14
|
+
#
|
15
|
+
#
|
16
|
+
# the eval "require 'module/class_name.rb'" in the
|
17
|
+
# langrove/ext/class_loader could possibly be avoided
|
18
|
+
# if the implementation requires all necessary modules
|
19
|
+
# ahead of starting the daemon.
|
20
|
+
#
|
21
|
+
#
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# Define a Handler by extending LanGrove::Handler::Base
|
3
|
+
# and extending the functions:
|
4
|
+
#
|
5
|
+
# 1. <YourClass>.receive( data )
|
6
|
+
#
|
7
|
+
# Data arriving from the Adaptor will arrive into
|
8
|
+
# this function having already been decoded by the
|
9
|
+
# configured Protocol for this Handler
|
10
|
+
#
|
11
|
+
# # 2. <YourClass>.transmit
|
12
|
+
# #
|
13
|
+
|
14
|
+
require 'langrove'
|
15
|
+
|
16
|
+
module Handler
|
17
|
+
|
18
|
+
class SocketToFile < LanGrove::Handler::Base
|
19
|
+
|
20
|
+
def receive( data )
|
21
|
+
|
22
|
+
@logger.info( "#{self}.receive: #{data}" )
|
23
|
+
|
24
|
+
File.open( data[:filename], 'w' ) do |f|
|
25
|
+
|
26
|
+
f.write( data[:content] )
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
@logger.info "Wrote data: '#{data[ :content ]}' to file: '#{ data[ :filename ]}'"
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#
|
2
|
+
# Define a Protocol by extending LanGrove::Protocol::Base
|
3
|
+
# and extending the functions:
|
4
|
+
#
|
5
|
+
# 1. <YourClass>.decode( data )
|
6
|
+
#
|
7
|
+
# Data arriving from the Adaptor will be passed to
|
8
|
+
# the config assigned protocol. The Handler will
|
9
|
+
# be expecting decoded data in the form of a Hash
|
10
|
+
#
|
11
|
+
# SPECIFICALLY: One of the keys should correspond
|
12
|
+
# to the :route_by in the config.
|
13
|
+
#
|
14
|
+
# # 2. <YourClass>.encode( .. )
|
15
|
+
# #
|
16
|
+
|
17
|
+
|
18
|
+
require 'langrove'
|
19
|
+
|
20
|
+
module Protocol
|
21
|
+
|
22
|
+
#
|
23
|
+
# Module is only necessary if you choose to
|
24
|
+
# structure associations of class by name.
|
25
|
+
#
|
26
|
+
# eg.
|
27
|
+
#
|
28
|
+
# Protocol::SocketToFile
|
29
|
+
# Handler::SocketToFile
|
30
|
+
#
|
31
|
+
|
32
|
+
class SocketToFile < LanGrove::Protocol::Base
|
33
|
+
|
34
|
+
def decode( data )
|
35
|
+
|
36
|
+
#
|
37
|
+
# OVERRIDE
|
38
|
+
#
|
39
|
+
# Becasuse your protocol
|
40
|
+
#
|
41
|
+
|
42
|
+
@logger.info( "#{self}.decode: #{data}" ) unless @logger.nil?
|
43
|
+
|
44
|
+
{
|
45
|
+
|
46
|
+
:filename => data.split('|')[0],
|
47
|
+
:content => data.split('|',2)[1]
|
48
|
+
|
49
|
+
}
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -1,9 +1,8 @@
|
|
1
|
-
require '
|
2
|
-
require 'ext/config_loader'
|
1
|
+
require 'langrove'
|
3
2
|
|
4
3
|
CLASS_NAME = DAEMON_NAME.camelize
|
5
4
|
CONFIG_FILE = "#{DAEMON_ROOT}/config/daemons.yml"
|
6
|
-
CONFIG_HASH = ConfigLoader.yaml( CONFIG_FILE )
|
5
|
+
CONFIG_HASH = LanGrove::ConfigLoader.yaml( CONFIG_FILE )
|
7
6
|
|
8
7
|
daemon = nil
|
9
8
|
|
@@ -50,6 +49,18 @@ DaemonKit::Application.running! do |config|
|
|
50
49
|
#
|
51
50
|
# Latebind the daemon class
|
52
51
|
#
|
52
|
+
# TODO: see about tossing the libexec
|
53
|
+
# or modifying class loader to enable
|
54
|
+
# alternate load path to allow this pattern:
|
55
|
+
#
|
56
|
+
# daemon = LanGrove::ClassLoader.create( {
|
57
|
+
#
|
58
|
+
# :module => 'Daemon',
|
59
|
+
# :class => DAEMON_NAME.camelize
|
60
|
+
#
|
61
|
+
# } ).new( CONFIG_HASH, DAEMON_NAME, DaemonKit.logger )
|
62
|
+
#
|
63
|
+
|
53
64
|
require "daemon/#{DAEMON_NAME}"
|
54
65
|
daemon = Object.const_get( CLASS_NAME ).new( CONFIG_HASH, DAEMON_NAME, DaemonKit.logger )
|
55
66
|
daemon.run
|
@@ -0,0 +1 @@
|
|
1
|
+
Certain test write files into here
|
data/lib/langrove.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'langrove/_base'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#$LOAD_PATH.unshift 'langrove' unless $LOAD_PATH.include?( 'langrove' )
|
2
|
+
|
3
|
+
#$LOAD_PATH.inspect
|
4
|
+
|
5
|
+
#
|
6
|
+
# For the implementation client
|
7
|
+
#
|
8
|
+
module Adaptor; end
|
9
|
+
module Client; end
|
10
|
+
module Daemon; end
|
11
|
+
module Handler; end
|
12
|
+
module Protocol; end
|
13
|
+
|
14
|
+
module LanGrove
|
15
|
+
|
16
|
+
class DaemonConfigException < Exception; end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'langrove/ext'
|
21
|
+
|
22
|
+
require 'langrove/daemon/base'
|
23
|
+
require 'langrove/adaptor/base'
|
24
|
+
require 'langrove/handler/base'
|
25
|
+
require 'langrove/protocol/base'
|
26
|
+
require 'langrove/client/base'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'langrove/adaptor/base'
|
2
|
+
|
3
|
+
module LanGrove::Adaptor
|
4
|
+
|
5
|
+
class Datagram < Base
|
6
|
+
|
7
|
+
def listen( handler, protocol )
|
8
|
+
|
9
|
+
@logger.info "starting listen at UDP #{@iface}:#{@port}"
|
10
|
+
|
11
|
+
EventMachine::open_datagram_socket( @iface, @port,
|
12
|
+
|
13
|
+
@client ) do |client|
|
14
|
+
|
15
|
+
@logger.info "client assign handler: #{handler}"
|
16
|
+
client.handler = handler
|
17
|
+
|
18
|
+
@logger.info "client instanciate protocol: #{protocol}"
|
19
|
+
client.protocol = protocol.new( nil, @logger )
|
20
|
+
|
21
|
+
@logger.info "client assign config: #{@client_config}"
|
22
|
+
client.config = @client_config.clone
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
|
3
|
+
require 'langrove'
|
4
|
+
|
5
|
+
module LanGrove::Adaptor
|
6
|
+
|
7
|
+
class Base
|
8
|
+
|
9
|
+
def initialize( config, logger )
|
10
|
+
|
11
|
+
@config = config
|
12
|
+
@logger = logger
|
13
|
+
|
14
|
+
@iface = '127.0.0.1'
|
15
|
+
@port = 12701
|
16
|
+
|
17
|
+
@iface = @config[ :iface ] if @config.has_key? :iface
|
18
|
+
@port = @config[ :port ] if @config.has_key? :port
|
19
|
+
|
20
|
+
if @config.has_key? :connector then
|
21
|
+
|
22
|
+
#
|
23
|
+
# TODO: may need to override default connection handler
|
24
|
+
#
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# initialize the client specified in config
|
30
|
+
#
|
31
|
+
# daemons:
|
32
|
+
# name_of_daemon:
|
33
|
+
# adaptor:
|
34
|
+
# connection: TcpServer
|
35
|
+
# client:
|
36
|
+
# class: Client <---------
|
37
|
+
# handler:
|
38
|
+
# collection: CollectionOfClients
|
39
|
+
#
|
40
|
+
#
|
41
|
+
|
42
|
+
@logger.info "TODO: loading client is not tested"
|
43
|
+
|
44
|
+
client = nil
|
45
|
+
|
46
|
+
begin
|
47
|
+
|
48
|
+
#
|
49
|
+
# TODO: make this more informative on error
|
50
|
+
#
|
51
|
+
|
52
|
+
@client_config = @config[ :client ]
|
53
|
+
client = @client_config[ :class ]
|
54
|
+
|
55
|
+
rescue
|
56
|
+
|
57
|
+
error = "Missing config item(s) for adaptor: #{@config.inspect}"
|
58
|
+
|
59
|
+
@logger.error "EXIT: #{error}"
|
60
|
+
|
61
|
+
raise LanGrove::DaemonConfigException.new(
|
62
|
+
|
63
|
+
"Missing config item for daemon: #{@daemon_name}"
|
64
|
+
|
65
|
+
)
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
@logger.info "Load definition: Client::#{client}"
|
70
|
+
|
71
|
+
@client = LanGrove::ClassLoader.create( {
|
72
|
+
|
73
|
+
:module => 'Client',
|
74
|
+
:class => client
|
75
|
+
|
76
|
+
} )
|
77
|
+
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
def listen( handler, protocol )
|
82
|
+
|
83
|
+
raise LanGrove::DaemonConfigException.new( "NotYetExtended: undefined listen()" )
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'langrove'
|
3
|
+
|
4
|
+
module LanGrove
|
5
|
+
|
6
|
+
module Client
|
7
|
+
|
8
|
+
class Datagram < Base
|
9
|
+
|
10
|
+
def receive( data )
|
11
|
+
|
12
|
+
#
|
13
|
+
# Quick hack, datagram client routes
|
14
|
+
# data back to the Handler - to get
|
15
|
+
# back to friday position.
|
16
|
+
#
|
17
|
+
# But with the gem
|
18
|
+
#
|
19
|
+
|
20
|
+
@handler.receive( data )
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'langrove'
|
3
|
+
|
4
|
+
module LanGrove
|
5
|
+
|
6
|
+
module Client
|
7
|
+
|
8
|
+
class Base < EventMachine::Connection
|
9
|
+
|
10
|
+
#
|
11
|
+
# Misnomer.
|
12
|
+
#
|
13
|
+
#
|
14
|
+
# This is not the client,
|
15
|
+
#
|
16
|
+
#
|
17
|
+
# It is the server's perspective of the client,
|
18
|
+
#
|
19
|
+
# These are generally stored in the daemon's
|
20
|
+
# handler collection,
|
21
|
+
#
|
22
|
+
# Which contains this and all similar clients,
|
23
|
+
#
|
24
|
+
# Each bonded through the daemon's connection
|
25
|
+
# adaptor to the socket that couples them to
|
26
|
+
# their actual client..
|
27
|
+
#
|
28
|
+
|
29
|
+
#
|
30
|
+
# The handler collection specified in config
|
31
|
+
# is bound to this attribute after connect.
|
32
|
+
#
|
33
|
+
attr_accessor :handler
|
34
|
+
attr_accessor :protocol
|
35
|
+
attr_accessor :config
|
36
|
+
|
37
|
+
#
|
38
|
+
# Data arriving through the Adaptor is passed
|
39
|
+
# through the config assigned protocol and
|
40
|
+
# then arrives here in whatever format the
|
41
|
+
# <Protocol>.decode() method returned.
|
42
|
+
#
|
43
|
+
#
|
44
|
+
def receive( decoded_data )
|
45
|
+
|
46
|
+
#
|
47
|
+
# OVERRIDE
|
48
|
+
#
|
49
|
+
# - Inbound data arrived at the adaptor
|
50
|
+
#
|
51
|
+
# - It has passed through the protocol as
|
52
|
+
# defined in config.
|
53
|
+
#
|
54
|
+
# The protocol arranged the data into
|
55
|
+
# a Hash of:
|
56
|
+
#
|
57
|
+
# - key and value pairs
|
58
|
+
#
|
59
|
+
# - key and more_complicated_thing pairs.
|
60
|
+
#
|
61
|
+
# - The decoded data was then passed into
|
62
|
+
# this function.
|
63
|
+
#
|
64
|
+
#
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
def receive_data( data )
|
69
|
+
|
70
|
+
#
|
71
|
+
# Note: The protocol currently lives on the Handler
|
72
|
+
#
|
73
|
+
# It MIG( ...in progress... )HT move,
|
74
|
+
#
|
75
|
+
# To a separate instance of the protocol object
|
76
|
+
# residing in each Client::ClientType instance
|
77
|
+
# in the Handler::Base.client collection.
|
78
|
+
#
|
79
|
+
# Pending examining the logical barrier of having
|
80
|
+
# the Handler route to the Cleint per a key value
|
81
|
+
# extracted from the decoded data - as decoded by
|
82
|
+
# the client's instance of the protocol not yet
|
83
|
+
# accessable within the as yet undeterminable
|
84
|
+
# instance in the Handlers collection.
|
85
|
+
#
|
86
|
+
# Catch22(ish)
|
87
|
+
#
|
88
|
+
# But that was suitable as a pettern for the
|
89
|
+
# datagram server.
|
90
|
+
#
|
91
|
+
# Perhaps after implementing Adapter::TcpServer
|
92
|
+
#
|
93
|
+
# And gaining a more knowsome notion of the
|
94
|
+
# intricacies of the application layer, esp
|
95
|
+
# ACKing and NAKing.
|
96
|
+
#
|
97
|
+
# Then the possibilities of the Client::ClientType
|
98
|
+
# being a decendant of <self> --
|
99
|
+
#
|
100
|
+
# ie. The EM::Connection as instanciated upon each
|
101
|
+
# socket connect.
|
102
|
+
#
|
103
|
+
# -- will likely resolve.
|
104
|
+
#
|
105
|
+
#
|
106
|
+
receive( @protocol.decode( data ) )
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|