LanGrove 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/.watchr +11 -3
  2. data/Rakefile +12 -5
  3. data/functional/.gitignore +1 -0
  4. data/{bin/datagram_example → functional/bin/datagram} +2 -0
  5. data/{config/environments/development.rb → functional/config/.gitignore} +0 -0
  6. data/{config → functional/config}/boot.rb +0 -0
  7. data/functional/config/daemons.yml +12 -0
  8. data/{config → functional/config}/environment.rb +0 -0
  9. data/{config/environments/production.rb → functional/config/environments/development.rb} +0 -0
  10. data/{config/environments/test.rb → functional/config/environments/production.rb} +0 -0
  11. data/{lib/jobs/Rakefile → functional/config/environments/test.rb} +0 -0
  12. data/functional/lib/daemon/datagram.rb +23 -0
  13. data/functional/lib/handler/socket_to_file.rb +36 -0
  14. data/functional/lib/protocol/socket_to_file.rb +55 -0
  15. data/{libexec → functional/libexec}/daemon.rb +14 -3
  16. data/functional/log/.gitignore +3 -0
  17. data/functional/tmp/README +1 -0
  18. data/lib/langrove.rb +1 -0
  19. data/lib/langrove/_base.rb +26 -0
  20. data/lib/langrove/adaptor/base.rb +3 -0
  21. data/lib/langrove/adaptor/datagram.rb +27 -0
  22. data/lib/langrove/adaptor_base.rb +89 -0
  23. data/lib/langrove/client/base.rb +2 -0
  24. data/lib/langrove/client/datagram.rb +28 -0
  25. data/lib/langrove/client_base.rb +114 -0
  26. data/lib/langrove/daemon/base.rb +2 -0
  27. data/lib/{daemon_base.rb → langrove/daemon_base.rb} +30 -23
  28. data/lib/langrove/ext.rb +7 -0
  29. data/lib/langrove/ext/class_loader.rb +146 -0
  30. data/lib/{ext → langrove/ext}/config_item.rb +4 -5
  31. data/lib/{ext → langrove/ext}/config_loader.rb +2 -2
  32. data/lib/langrove/ext/fake_logger.rb +8 -0
  33. data/lib/{ext → langrove/ext}/persistable.rb +2 -2
  34. data/lib/{ext → langrove/ext}/string.rb +0 -0
  35. data/lib/langrove/handler/base.rb +2 -0
  36. data/lib/{handler_base.rb → langrove/handler_base.rb} +25 -9
  37. data/lib/langrove/protocol/base.rb +2 -0
  38. data/lib/langrove/protocol/syslog.rb +32 -0
  39. data/lib/langrove/protocol_base.rb +32 -0
  40. data/lib/langrove/version.rb +3 -0
  41. data/spec/functional/daemon/datagram_spec.rb +115 -0
  42. data/spec/langrove/adaptor/datagram_spec.rb +6 -0
  43. data/spec/langrove/adaptor_base_spec.rb +48 -0
  44. data/spec/langrove/client/datagram_spec.rb +1 -0
  45. data/spec/langrove/client_base_spec.rb +5 -0
  46. data/spec/langrove/daemon_base_spec.rb +101 -0
  47. data/spec/langrove/ext/class_loader_spec.rb +83 -0
  48. data/spec/langrove/ext/config_item_spec.rb +81 -0
  49. data/spec/langrove/ext/config_loader_spec.rb +5 -0
  50. data/{tmp/TMP → spec/langrove/ext/fake_logger_spec.rb} +0 -0
  51. data/spec/{ext → langrove/ext}/persistable_spec.rb +8 -9
  52. data/spec/{ext → langrove/ext}/string_spec.rb +1 -1
  53. data/spec/langrove/handler_base_spec.rb +57 -0
  54. data/spec/langrove/protocol/syslog_spec.rb +45 -0
  55. data/spec/langrove/protocol_base_spec.rb +6 -0
  56. data/spec/todo_spec.rb +1 -2
  57. data/tmp/README +2 -0
  58. metadata +150 -46
  59. data/config/daemons.yml.tmpl +0 -78
  60. data/lib/adaptor/base.rb +0 -1
  61. data/lib/adaptor/datagram.rb +0 -20
  62. data/lib/adaptor/socket_handler.rb +0 -27
  63. data/lib/adaptor_base.rb +0 -39
  64. data/lib/client/base.rb +0 -1
  65. data/lib/client/puppet_state.rb +0 -74
  66. data/lib/client/radio_state.rb +0 -81
  67. data/lib/client_base.rb +0 -24
  68. data/lib/daemon/base.rb +0 -1
  69. data/lib/daemon/datagram_example.rb +0 -12
  70. data/lib/handler/base.rb +0 -1
  71. data/lib/handler/socket_to_file.rb +0 -30
  72. data/lib/jobs/jobs.rb +0 -1
  73. data/lib/jobs/updated_puppet_state.rb +0 -17
  74. data/lib/protocol_base.rb +0 -5
  75. data/spec/adaptor/datagram_spec.rb +0 -6
  76. data/spec/adaptor/socket_handler_spec.rb +0 -5
  77. data/spec/adaptor_base_spec.rb +0 -45
  78. data/spec/client_base_spec.rb +0 -5
  79. data/spec/daemon_base_spec.rb +0 -97
  80. data/spec/ext/config_item_spec.rb +0 -77
  81. data/spec/ext/config_loader_spec.rb +0 -5
  82. data/spec/functional/datagram_spec.rb +0 -122
  83. data/spec/handler_base_spec.rb +0 -71
  84. 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("lib/(.*/*).rb") do |match|
17
- puts match
18
- run_spec %{spec/#{match[1]}_spec.rb}
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
- #sh "git tag v#{LanGrove::Version}"
11
- #sh "git push origin v#{Resque::Version}"
12
- #sh "git push origin master"
13
- #sh "git clean -fd"
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/*.*
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+
3
+ DAEMON_ROOT = File.expand_path('../../../functional/', __FILE__)
2
4
  DAEMON_NAME = File.basename $0
3
5
  require File.expand_path('../../config/environment', __FILE__)
4
6
  DaemonKit::Application.exec( DAEMON_ROOT + '/libexec/daemon.rb' )
File without changes
@@ -0,0 +1,12 @@
1
+ :daemons:
2
+ datagram:
3
+ :periodic: 5
4
+ :adaptor:
5
+ :connection: Datagram
6
+ :iface: 127.0.0.1
7
+ :port: 12701
8
+ :client:
9
+ :class: Datagram
10
+ :handler:
11
+ :collection: SocketToFile
12
+ :protocol: SocketToFile
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 'ext/string'
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,3 @@
1
+ *.log
2
+ *.pid
3
+ *.yml
@@ -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,3 @@
1
+ module LanGrove::Adaptor; end
2
+ require 'langrove/adaptor_base'
3
+ require 'langrove/adaptor/datagram'
@@ -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,2 @@
1
+ module LanGrove::Client; end
2
+ require 'langrove/client_base'
@@ -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