LanGrove 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.
Files changed (51) hide show
  1. data/.rspec +1 -0
  2. data/.rvmrc +62 -0
  3. data/.watchr +19 -0
  4. data/Gemfile +16 -0
  5. data/Gemfile.lock +61 -0
  6. data/Rakefile +17 -0
  7. data/bin/datagram_example +4 -0
  8. data/config/boot.rb +64 -0
  9. data/config/daemons.yml.tmpl +78 -0
  10. data/config/environment.rb +28 -0
  11. data/config/environments/development.rb +0 -0
  12. data/config/environments/production.rb +0 -0
  13. data/config/environments/test.rb +0 -0
  14. data/lib/adaptor/base.rb +1 -0
  15. data/lib/adaptor/datagram.rb +20 -0
  16. data/lib/adaptor/socket_handler.rb +27 -0
  17. data/lib/adaptor_base.rb +39 -0
  18. data/lib/client/base.rb +1 -0
  19. data/lib/client/puppet_state.rb +74 -0
  20. data/lib/client/radio_state.rb +81 -0
  21. data/lib/client_base.rb +24 -0
  22. data/lib/daemon/base.rb +1 -0
  23. data/lib/daemon/datagram_example.rb +12 -0
  24. data/lib/daemon_base.rb +168 -0
  25. data/lib/ext/config_item.rb +35 -0
  26. data/lib/ext/config_loader.rb +16 -0
  27. data/lib/ext/persistable.rb +103 -0
  28. data/lib/ext/string.rb +35 -0
  29. data/lib/handler/base.rb +1 -0
  30. data/lib/handler/socket_to_file.rb +30 -0
  31. data/lib/handler_base.rb +125 -0
  32. data/lib/jobs/Rakefile +0 -0
  33. data/lib/jobs/jobs.rb +1 -0
  34. data/lib/jobs/updated_puppet_state.rb +17 -0
  35. data/lib/protocol_base.rb +5 -0
  36. data/libexec/daemon.rb +57 -0
  37. data/spec/adaptor/datagram_spec.rb +6 -0
  38. data/spec/adaptor/socket_handler_spec.rb +5 -0
  39. data/spec/adaptor_base_spec.rb +45 -0
  40. data/spec/client_base_spec.rb +5 -0
  41. data/spec/daemon_base_spec.rb +97 -0
  42. data/spec/ext/config_item_spec.rb +77 -0
  43. data/spec/ext/config_loader_spec.rb +5 -0
  44. data/spec/ext/persistable_spec.rb +118 -0
  45. data/spec/ext/string_spec.rb +16 -0
  46. data/spec/functional/datagram_spec.rb +122 -0
  47. data/spec/handler_base_spec.rb +71 -0
  48. data/spec/protocol_base_spec.rb +6 -0
  49. data/spec/todo_spec.rb +13 -0
  50. data/tmp/TMP +0 -0
  51. metadata +97 -0
@@ -0,0 +1,97 @@
1
+ require 'daemon_base'
2
+
3
+ require 'ext/fake_logger'
4
+
5
+ describe Daemon::Base do
6
+
7
+ before :each do
8
+
9
+ @logger = FakeLogger.new :silent
10
+
11
+ @daemon_name = 'pretend_daemon'
12
+
13
+ @adaptor_class = 'Base'
14
+ @collection_class = 'Base'
15
+
16
+ @config = {
17
+
18
+ 'server' => false,
19
+
20
+ 'daemons' => {
21
+
22
+ 'pretend_daemon' => {
23
+
24
+ 'adaptor' => {
25
+
26
+ 'connection' => @adaptor_class
27
+
28
+ },
29
+
30
+ 'handler' => {
31
+
32
+ 'collection' => @collection_class
33
+
34
+ }
35
+ }
36
+ }
37
+ }
38
+
39
+ end
40
+
41
+ subject do
42
+
43
+ Daemon::Base.new( @config, @daemon_name, @logger )
44
+
45
+ end
46
+
47
+ it 'requires a logger' do
48
+
49
+ expect {
50
+
51
+ Daemon::Base.new( @config, @daemon_name, nil )
52
+
53
+ }.to raise_error( DaemonConfigException, /Requires a logger/ )
54
+
55
+ end
56
+
57
+ it 'requires a configuration' do
58
+
59
+ expect {
60
+
61
+ Daemon::Base.new( {}, @daemon_name, @logger )
62
+
63
+ }.to raise_error( DaemonConfigException, /Missing config item/ )
64
+
65
+ end
66
+
67
+ it 'latebinds an adaptor by config' do
68
+
69
+ adaptor = subject.instance_variable_get( :@adaptor )
70
+
71
+ adaptor.should be_a( Adaptor.const_get( @adaptor_class ) )
72
+
73
+ end
74
+
75
+ it 'latebinds a handler by config' do
76
+
77
+ handler = subject.instance_variable_get( :@handler )
78
+
79
+ handler.should be_a( Handler.const_get( @collection_class ) )
80
+
81
+ end
82
+
83
+ it 'it schedules periodics'
84
+
85
+ it 'when run, it calls to listen if server is true' do
86
+
87
+ expect {
88
+
89
+ subject.instance_variable_set( :@server, true )
90
+
91
+ subject.run
92
+
93
+ }.to raise_error( DaemonConfigException, "NotYetExtended: undefined listen()" )
94
+
95
+ end
96
+
97
+ end
@@ -0,0 +1,77 @@
1
+ require 'ext/config_item'
2
+
3
+ describe ConfigItem do
4
+
5
+ before :each do
6
+ @config_hash = {
7
+ 'root' => "3",
8
+ 'BLANK' => "",
9
+ 'daemons' => {
10
+ 'puppet_log' => {
11
+ 'handler' => {
12
+ 'collection' => 'SyslogStateMachines'
13
+ }
14
+ }
15
+ }
16
+ }
17
+ end
18
+
19
+ it 'accesses config items' do
20
+ ConfigItem.get(@config_hash, ['root']).should == '3'
21
+ end
22
+
23
+ it 'accesses nested config items' do
24
+ ConfigItem.get(@config_hash, ['daemons','puppet_log','handler','collection']).should == 'SyslogStateMachines'
25
+ end
26
+
27
+ it 'raises a config exception if the key isnt present' do
28
+
29
+ expect {
30
+
31
+ ConfigItem.get(@config_hash, ['NOT'])
32
+
33
+ }.to raise_error( ConfigException, /Missing config item 'NOT'/ )
34
+
35
+ end
36
+
37
+ it 'raises a config exception if the key isnt present' do
38
+
39
+ expect {
40
+
41
+ ConfigItem.get(@config_hash, ['BLANK'])
42
+
43
+ }.to raise_error( ConfigException, /Missing config item 'BLANK'/ )
44
+
45
+ end
46
+
47
+ it 'raises a config exception if the value isnt present' do
48
+
49
+ expect {
50
+
51
+ ConfigItem.get(@config_hash, ['BLANK'], false)
52
+
53
+ }.to_not raise_error( ConfigException, /Missing config item 'BLANK'/ )
54
+
55
+ end
56
+
57
+ it 'raises a config exception if the nested item isnt present' do
58
+
59
+ expect {
60
+
61
+ ConfigItem.get(@config_hash, ['daemons', 'NEITHER', 'this'])
62
+
63
+ }.to raise_error( ConfigException, /Missing config item 'NEITHER'/ )
64
+
65
+ end
66
+
67
+ it 'does not raise on not mandatory fields' do
68
+
69
+ expect {
70
+
71
+ ConfigItem.get(@config_hash, ['daemons', 'NEITHER'], false)
72
+
73
+ }.to_not raise_error( ConfigException )
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,5 @@
1
+ require 'ext/config_loader'
2
+
3
+ describe ConfigLoader do
4
+
5
+ end
@@ -0,0 +1,118 @@
1
+ require 'ext/persistable'
2
+ require 'ext/fake_logger'
3
+
4
+ #
5
+ # This will likely change.
6
+ #
7
+
8
+ describe Persistable do
9
+
10
+ before :each do
11
+
12
+ class TestSerialization
13
+ attr_accessor :data
14
+ end
15
+
16
+ @class_instance = TestSerialization.new
17
+ @class_instance.data = 'VALUE'
18
+
19
+ @now = Time.now
20
+ @state_file = File.dirname( __FILE__ ) + "/../../tmp/persistable.yml"
21
+
22
+ #
23
+ # delete the file
24
+ #
25
+ File.delete( @state_file ) if File.file?( @state_file )
26
+
27
+ @hash = {
28
+ 'tree' => {
29
+ 'type' => {
30
+ 'thing1' => 1
31
+ }
32
+ },
33
+ :now => @now,
34
+ :class_instance => @class_instance
35
+ }
36
+
37
+ end
38
+
39
+ subject do
40
+
41
+ test = Persistable.new
42
+ test.instance_variable_set :@logger, (FakeLogger.new :silent)
43
+ test
44
+
45
+ end
46
+
47
+ it 'can serialize a hash to file' do
48
+
49
+ #
50
+ # install the hash to be 'stored'
51
+ #
52
+ subject.instance_variable_set( :@hash, @hash )
53
+ subject.store_hash( '@hash', @state_file )
54
+
55
+ #
56
+ # is the file there?
57
+ #
58
+ File.file?( @state_file ).should == true
59
+
60
+ end
61
+
62
+ context 'can de-serialize a hash' do
63
+
64
+ before :each do
65
+
66
+ #
67
+ # set up the file to read
68
+ #
69
+ subject.instance_variable_set( :@hash, @hash )
70
+ subject.store_hash( '@hash', @state_file )
71
+
72
+ #
73
+ # replace the hash with another containg other things
74
+ #
75
+ subject.instance_variable_set( :@hash, { 'thing2' => 2 } )
76
+
77
+ end
78
+
79
+ it 'from file' do
80
+
81
+ subject.load_hash( '@hash', @state_file )
82
+
83
+ hash = subject.instance_variable_get( :@hash )
84
+ hash['tree']['type']['thing1'].should == 1
85
+
86
+ end
87
+
88
+ it 'from file and re-instanciate as correct native ruby classes' do
89
+
90
+ subject.load_hash( '@hash', @state_file )
91
+ hash = subject.instance_variable_get( :@hash )
92
+
93
+ hash[:now].should be_a( Time )
94
+ hash[:now].should == @now
95
+
96
+ end
97
+
98
+ it 'from file and re-instanciate as correct userland ruby classes' do
99
+
100
+ subject.load_hash( '@hash', @state_file )
101
+ hash = subject.instance_variable_get( :@hash )
102
+
103
+ hash[:class_instance].should be_a( TestSerialization )
104
+ hash[:class_instance].data.should == 'VALUE'
105
+
106
+ end
107
+
108
+ it 'from file and not overrwrite other variables in the hash' do
109
+
110
+ subject.load_hash( '@hash', @state_file )
111
+ hash = subject.instance_variable_get( :@hash )
112
+
113
+ hash['tree']['type']['thing1'].should == 1
114
+ hash['thing2'].should == 2
115
+
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,16 @@
1
+ require 'ext/string'
2
+ describe String do
3
+
4
+ it 'has been extended to camelize' do
5
+
6
+ "this_is_a_class_file_name".camelize.should == "ThisIsAClassFileName"
7
+
8
+ end
9
+
10
+ it 'has been extended to underscore' do
11
+
12
+ "ThisIsAClassName".underscore.should == "this_is_a_class_name"
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,122 @@
1
+ require 'daemon/base'
2
+
3
+ require 'ext/fake_logger'
4
+
5
+ describe 'A daemon' do
6
+
7
+ before :all do
8
+
9
+ @daemon_name = 'test_daemon'
10
+ @adaptor_class = 'Datagram'
11
+ @collection_class = 'SocketToFile'
12
+
13
+ @logger = FakeLogger.new :silent
14
+
15
+ @file = File.dirname( __FILE__ ) + "/../../tmp/datagram.txt"
16
+ `rm -f #{@file}`
17
+ @mesg = "Send This As Datagram"
18
+
19
+ @config = {
20
+
21
+ 'daemons' => {
22
+
23
+ @daemon_name => {
24
+
25
+ 'adaptor' => {
26
+
27
+ 'connection' => @adaptor_class
28
+
29
+ },
30
+
31
+ 'handler' => {
32
+
33
+ 'collection' => @collection_class
34
+
35
+ }
36
+ }
37
+ }
38
+ }
39
+
40
+ #
41
+ # start the daemon
42
+ #
43
+ @pid = fork do
44
+
45
+ #
46
+ # after :each should kill it,
47
+ #
48
+ # but just incase, it can be found in the
49
+ # process table with
50
+ #
51
+ # ps aux | grep test_daemon
52
+ #
53
+ $0 = @daemon_name
54
+
55
+ Daemon::Base.new( @config, @daemon_name, @logger ).run
56
+
57
+ end
58
+
59
+ end
60
+
61
+ after :all do
62
+
63
+ #
64
+ # stop the daemon
65
+ #
66
+ `kill #{@pid}`
67
+
68
+ end
69
+
70
+ context 'running a server' do
71
+
72
+ it 'receives a message' do
73
+
74
+ require "eventmachine"
75
+
76
+ class Sender < EventMachine::Connection
77
+
78
+ def send( data )
79
+
80
+ send_datagram( data, '127.0.0.1', 12701 )
81
+
82
+ end
83
+
84
+ end
85
+
86
+ EM.run do
87
+
88
+ sender = nil
89
+
90
+ EM.add_periodic_timer(1) do
91
+
92
+ sender.send( "#{@file}|#{@mesg}" )
93
+ EM.stop
94
+
95
+ end
96
+
97
+ EM.open_datagram_socket "127.0.0.1", 0, Sender do |connected|
98
+
99
+ sender = connected
100
+
101
+ end
102
+
103
+ end
104
+
105
+ #
106
+ # Give the daemon a moment to write the file
107
+ #
108
+ sleep 1
109
+
110
+ File.file?( @file ).should == true
111
+
112
+ File.open( @file, 'r' ).each_line do |line|
113
+
114
+ line.should == @mesg
115
+
116
+ end
117
+
118
+ end
119
+
120
+ end
121
+
122
+ end
@@ -0,0 +1,71 @@
1
+ require 'handler/base'
2
+
3
+ require 'ext/fake_logger'
4
+
5
+ describe Handler::Base do
6
+
7
+ before :each do
8
+
9
+ @logger = FakeLogger.new :silent
10
+
11
+ @daemon_name = 'test_daemon'
12
+
13
+ @config = {
14
+
15
+ 'daemons' => {
16
+
17
+ @daemon_name => {
18
+
19
+ 'handler' => {
20
+
21
+ 'collection' => 'Base'
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ end
28
+
29
+ context 'uses a protocol' do
30
+
31
+ it 'that defaults to an instance of Protocol::Base' do
32
+
33
+ test = Handler::Base.new( @config, @daemon_name, @logger )
34
+
35
+ protocol = test.instance_variable_get( :@protocol )
36
+
37
+ protocol.should be_a( Protocol.const_get('Base') )
38
+
39
+ end
40
+
41
+ it 'as defined by the config_hash' do
42
+
43
+ @config['daemons'][@daemon_name]['handler']['protocol'] = 'MedievalLanternMorse'
44
+
45
+ expect {
46
+
47
+ test = Handler::Base.new( @config, @daemon_name, @logger )
48
+
49
+ }.to raise_error( LoadError,
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+ "no such file to load -- protocol/medieval_lantern_morse"
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+ )
66
+
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,6 @@
1
+ require 'protocol_base'
2
+
3
+ describe Protocol::Base do
4
+
5
+
6
+ end
data/spec/todo_spec.rb ADDED
@@ -0,0 +1,13 @@
1
+ describe 'Outstanding:' do
2
+
3
+ pending 'Push the module name \'LanGrove\' into all classes'
4
+ pending 'Symbolize the config keys'
5
+ pending 'make a langrove --create for developers to autogenerate their project base dir'
6
+ pending 'cut and publish'
7
+
8
+
9
+
10
+
11
+ pending 'rdoc'
12
+
13
+ end
data/tmp/TMP ADDED
File without changes
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: LanGrove
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Richard
9
+ - ''
10
+ - ''
11
+ - ''
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+ date: 2012-04-21 00:00:00.000000000Z
16
+ dependencies: []
17
+ description: ''
18
+ email: richard@clue.co.za
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - .rspec
26
+ - .rvmrc
27
+ - .watchr
28
+ - Rakefile
29
+ - config/boot.rb
30
+ - config/daemons.yml.tmpl
31
+ - config/environment.rb
32
+ - config/environments/development.rb
33
+ - config/environments/production.rb
34
+ - config/environments/test.rb
35
+ - bin/datagram_example
36
+ - lib/adaptor/base.rb
37
+ - lib/adaptor/datagram.rb
38
+ - lib/adaptor/socket_handler.rb
39
+ - lib/adaptor_base.rb
40
+ - lib/client/base.rb
41
+ - lib/client/puppet_state.rb
42
+ - lib/client/radio_state.rb
43
+ - lib/client_base.rb
44
+ - lib/daemon/base.rb
45
+ - lib/daemon/datagram_example.rb
46
+ - lib/daemon_base.rb
47
+ - lib/ext/config_item.rb
48
+ - lib/ext/config_loader.rb
49
+ - lib/ext/persistable.rb
50
+ - lib/ext/string.rb
51
+ - lib/handler/base.rb
52
+ - lib/handler/socket_to_file.rb
53
+ - lib/handler_base.rb
54
+ - lib/jobs/jobs.rb
55
+ - lib/jobs/Rakefile
56
+ - lib/jobs/updated_puppet_state.rb
57
+ - lib/protocol_base.rb
58
+ - libexec/daemon.rb
59
+ - spec/functional/datagram_spec.rb
60
+ - spec/ext/config_item_spec.rb
61
+ - spec/ext/config_loader_spec.rb
62
+ - spec/ext/persistable_spec.rb
63
+ - spec/ext/string_spec.rb
64
+ - spec/adaptor/datagram_spec.rb
65
+ - spec/adaptor/socket_handler_spec.rb
66
+ - spec/adaptor_base_spec.rb
67
+ - spec/client_base_spec.rb
68
+ - spec/daemon_base_spec.rb
69
+ - spec/handler_base_spec.rb
70
+ - spec/protocol_base_spec.rb
71
+ - spec/todo_spec.rb
72
+ - tmp/TMP
73
+ homepage: ''
74
+ licenses: []
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 1.8.8
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: eventmachine based networked daemon framework
97
+ test_files: []