huck 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9e205a66c535c1083e677ee4c21216c82a7e1871
4
+ data.tar.gz: 35f2101dd7b4bf04061a5551f10359d7c28ecfb5
5
+ SHA512:
6
+ metadata.gz: 9290fec08bc1f3f37ebab767daaa3b6c216eb8c5599d7287c86dfcc92e883342a0773cab1da1f2a8bdeb43645bc3cfc158a68184d068557a3d2b537467aa7464
7
+ data.tar.gz: 13fe443bd3e52143a0c9da1925ea104306335f3391a2ac96a52331b0f62a2e3da6c2b7f9c0090462f1469604bf7e447c9392d2ef27a24158b81dd4ce888243ff
@@ -0,0 +1,57 @@
1
+ module Huck
2
+
3
+ class Generator
4
+
5
+ # This method will call the generation method, and return the data in the
6
+ # desired format.
7
+ def dump kwargs = {}
8
+ format = Huck::getarg kwargs, :format, 'json'
9
+ data = generate
10
+ if !data.is_a? Hash
11
+ raise RuntimeError, 'cannot handle non-hash data'
12
+ end
13
+
14
+ case format
15
+ when 'json'
16
+ return JSON.dump data
17
+ when 'yaml'
18
+ return YAML.dump data
19
+ else
20
+ raise RuntimeError, "unknown format '#{format}'"
21
+ end
22
+ end
23
+
24
+ # Given a generator's name (or no name), return a new generator instance
25
+ #
26
+ # == Parameters:
27
+ # name::
28
+ # The name of the generator, or empty/nil to guess
29
+ #
30
+ # == Returns:
31
+ # A Huck::Generator instance
32
+ #
33
+ def self.factory name
34
+ if name.nil?
35
+ if Huck::try_load 'facter'
36
+ name = 'facter'
37
+ elsif Huck::try_load 'ohai'
38
+ name = 'ohai'
39
+ else
40
+ raise RuntimeError, 'unable to load any generators'
41
+ end
42
+ end
43
+
44
+ case name
45
+ when 'facter'
46
+ gen = Generators::FacterGenerator.new
47
+ when 'ohai'
48
+ gen = Generators::OhaiGenerator.new
49
+ else
50
+ raise RuntimeError, "bad generator: #{name}"
51
+ end
52
+
53
+ return gen
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,23 @@
1
+ module Huck
2
+
3
+ module Generators
4
+
5
+ # Facter provider for generating consumeable data
6
+ class FacterGenerator < Generator
7
+
8
+ # Load required modules for facter generator
9
+ def initialize
10
+ require 'facter'
11
+ end
12
+
13
+ # This method generates the data and returns it as a hash
14
+ #
15
+ # == Returns:
16
+ # A hash of facts as returned by facter
17
+ def generate
18
+ Facter.to_hash
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ module Huck
2
+
3
+ module Generators
4
+
5
+ # Ohai provider for generating consumeable data
6
+ class OhaiGenerator < Generator
7
+
8
+ # Load required modules for ohai generator
9
+ def initialize
10
+ require 'ohai/system'
11
+ end
12
+
13
+ # This method generates the data and returns it as a hash
14
+ #
15
+ # == Returns
16
+ # A hash of hints as returned by ohai
17
+ def generate
18
+ ohai = Ohai::System.new
19
+ ohai.all_plugins
20
+
21
+ # Need to load the JSON output, since ohai emits a 'mash' object map
22
+ # instead of normal hashes, making serialization ugly in some cases
23
+ # like YAML where canonical objects (eg. !ruby/mash) is emitted.
24
+ JSON.load ohai.json_pretty_print
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Huck
2
+
3
+ # Base handler class
4
+ class Handler
5
+
6
+ # Given a handler's name (or no name), return a new handler instance
7
+ #
8
+ # == Parameters:
9
+ # name::
10
+ # The name of the handler, or nil to guess
11
+ #
12
+ # == Returns:
13
+ # A Huck::Handler instance
14
+ #
15
+ def self.factory name
16
+ name = 'exec' if name.nil?
17
+
18
+ case name
19
+ when 'exec'
20
+ hand = Handlers::ExecHandler.new
21
+ else
22
+ raise RuntimeError, "bad handler: #{name}"
23
+ end
24
+
25
+ return hand
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,41 @@
1
+ module Huck
2
+
3
+ module Handlers
4
+
5
+ # A handler to execute arbitrary scripts, passing in the generated text as
6
+ # input on stdin.
7
+ class ExecHandler < Handler
8
+
9
+ def initialize
10
+ require 'open3'
11
+ end
12
+
13
+ # Ensures that configuration is set properly before executing
14
+ #
15
+ # == Parameters:
16
+ # config::
17
+ # A hash of configuration data to verify
18
+ #
19
+ def verify_config config
20
+ if !config.has_key? 'exec'
21
+ raise RuntimeError, 'missing exec config'
22
+ end
23
+ if !config['exec'].has_key? 'command'
24
+ raise RuntimeError, 'missing exec config: command'
25
+ end
26
+ end
27
+
28
+ # Handle an individual message by running an executable, passing in the
29
+ # gathered data via stdin.
30
+ def handle msg
31
+ config = Huck::config
32
+ verify_config config
33
+
34
+ Open3.popen2 config['exec']['command'] do |stdin, stdout, thread|
35
+ stdin.print msg
36
+ end
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,35 @@
1
+ module Huck
2
+
3
+ # Base receiver class
4
+ class Receiver
5
+
6
+ # Given a receiver's name (or no name), return a new receiver instance
7
+ #
8
+ # == Parameters:
9
+ # name::
10
+ # The name of the receiver, or nil to guess
11
+ #
12
+ # == Returns:
13
+ # A Huck::Receiver instance
14
+ #
15
+ def self.factory name
16
+ if name.nil?
17
+ if Huck::try_load 'aws-sdk'
18
+ name = 'sqs'
19
+ else
20
+ raise RuntimeError, 'unable to load any receivers'
21
+ end
22
+ end
23
+
24
+ case name
25
+ when 'sqs'
26
+ recv = Receivers::SQSReceiver.new
27
+ else
28
+ raise RuntimeError, "bad receiver: #{name}"
29
+ end
30
+
31
+ return recv
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,52 @@
1
+ module Huck
2
+
3
+ module Receivers
4
+
5
+ # A receiver that talks to Amazon Simple Queue Service
6
+ class SQSReceiver < Receiver
7
+
8
+ # Includes all required modules for the SQS receiver
9
+ def initialize
10
+ require 'aws-sdk'
11
+ end
12
+
13
+ # Ensures that configuration is set properly before trying to use the
14
+ # connection data to talk to AWS
15
+ #
16
+ # == Parameters:
17
+ # config::
18
+ # A hash of configuration data to verify
19
+ #
20
+ def verify_config config
21
+ if !config.has_key? 'sqs'
22
+ raise RuntimeError, 'missing sqs config'
23
+ end
24
+ ['access_key_id', 'secret_access_key', 'region',
25
+ 'queue_name'].each do |key|
26
+ if !config['sqs'].has_key? key
27
+ raise RuntimeError, "missing sqs config: #{key}"
28
+ end
29
+ end
30
+ end
31
+
32
+ # A long-running poller process which reads messages out of the remote
33
+ # queue and yields them to higher-order logic.
34
+ def receive
35
+ config = Huck::config
36
+ verify_config config
37
+
38
+ sqs = AWS::SQS.new(
39
+ :access_key_id => config['sqs']['access_key_id'],
40
+ :secret_access_key => config['sqs']['secret_access_key'],
41
+ :region => config['sqs']['region']
42
+ )
43
+
44
+ queue = sqs.queues.create config['sqs']['queue_name']
45
+ queue.poll do |msg|
46
+ yield msg.body
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,35 @@
1
+ module Huck
2
+
3
+ # The base sender class
4
+ class Sender
5
+
6
+ # Given a sender's name (or no name), return a new sender instance
7
+ #
8
+ # == Parameters:
9
+ # name::
10
+ # The name of the sender, or nil to guess
11
+ #
12
+ # == Returns:
13
+ # A Huck::Sender instance
14
+ #
15
+ def self.factory name
16
+ if name.nil?
17
+ if Huck::try_load 'aws-sdk'
18
+ name = 'sqs'
19
+ else
20
+ raise RuntimeError, 'unable to load any senders'
21
+ end
22
+ end
23
+
24
+ case name
25
+ when 'sqs'
26
+ send = Senders::SQSSender.new
27
+ else
28
+ raise RuntimeError, "bad sender: #{name}"
29
+ end
30
+
31
+ return send
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,54 @@
1
+ module Huck
2
+
3
+ module Senders
4
+
5
+ # A sender that talks to Amazon Simple Queue Service
6
+ class SQSSender < Sender
7
+
8
+ # Includes all required modules for the SQS sender
9
+ def initialize
10
+ require 'aws-sdk'
11
+ end
12
+
13
+ # Ensures that configuration is set properly before trying to use the
14
+ # connection data to talk to AWS
15
+ #
16
+ # == Parameters:
17
+ # config::
18
+ # A hash of configuration data to verify
19
+ #
20
+ def verify_config config
21
+ if !config.has_key? 'sqs'
22
+ raise RuntimeError, 'missing sqs sender config'
23
+ end
24
+ ['access_key_id', 'secret_access_key', 'region',
25
+ 'queue_name'].each do |key|
26
+ if !config['sqs'].has_key? key
27
+ raise RuntimeError, "missing sqs sender config: #{key}"
28
+ end
29
+ end
30
+ end
31
+
32
+ # Send an arbitrary text message to the queue for processing
33
+ #
34
+ # == Parameters:
35
+ # msg::
36
+ # The arbitrary text data to send
37
+ #
38
+ def send msg
39
+ config = Huck::config
40
+ verify_config config
41
+
42
+ sqs = AWS::SQS.new(
43
+ :access_key_id => config['sqs']['access_key_id'],
44
+ :secret_access_key => config['sqs']['secret_access_key'],
45
+ :region => config['sqs']['region']
46
+ )
47
+
48
+ queue = sqs.queues.create config['sqs']['queue_name']
49
+ queue.send_message msg
50
+ end
51
+
52
+ end
53
+ end
54
+ end
data/lib/huck/util.rb ADDED
@@ -0,0 +1,52 @@
1
+ module Huck
2
+
3
+ # Retrieve the value of an "emulated" kwarg easily
4
+ #
5
+ # == Parameters:
6
+ # args::
7
+ # A hash of kwargs
8
+ # arg::
9
+ # The name of the arg desired
10
+ # default::
11
+ # If arg does not exist in args, return this
12
+ #
13
+ # == Returns:
14
+ # The value of the arg, or the default value
15
+ #
16
+ def self.getarg args, arg, default
17
+ return args.has_key?(arg) ? args[arg] : default
18
+ end
19
+
20
+ # Read configuration out of a file on the filesystem.
21
+ #
22
+ # == Parameters:
23
+ # path::
24
+ # The path to the config file to read
25
+ #
26
+ # == Returns:
27
+ # A hash containing the configuration
28
+ #
29
+ def self.config kwargs = {}
30
+ path = self.getarg kwargs, 'path', '/etc/huck.conf'
31
+ YAML.load_file path
32
+ end
33
+
34
+ # Attempts to load a given module by name
35
+ #
36
+ # == Parameters:
37
+ # name::
38
+ # The name of the module
39
+ #
40
+ # == Returns:
41
+ # bool
42
+ #
43
+ def self.try_load name
44
+ begin
45
+ require name
46
+ rescue LoadError
47
+ return false
48
+ end
49
+ true
50
+ end
51
+
52
+ end
@@ -0,0 +1,3 @@
1
+ module Huck
2
+ Version = '0.1.0'
3
+ end
data/lib/huck.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'json'
2
+ require 'yaml'
3
+
4
+ require 'huck/version'
5
+ require 'huck/util'
6
+ require 'huck/generator'
7
+ require 'huck/generators/facter'
8
+ require 'huck/generators/ohai'
9
+ require 'huck/sender'
10
+ require 'huck/senders/sqs'
11
+ require 'huck/receiver'
12
+ require 'huck/receivers/sqs'
13
+ require 'huck/handler'
14
+ require 'huck/handlers/exec'
15
+
16
+ module Huck
17
+
18
+ # Main method to run Huck and dump info
19
+ #
20
+ # == Parameters:
21
+ # generator::
22
+ # The name of the generator to use (default=facter)
23
+ #
24
+ def self.run kwargs = {}
25
+ config = Huck::config
26
+ if config.has_key? 'generator'
27
+ gen_name = config['generator']
28
+ end
29
+
30
+ gen_arg = Huck::getarg kwargs, :generator, nil
31
+ gen_name = gen_arg if !gen_arg.nil?
32
+
33
+ g = Generator::factory gen_name
34
+
35
+ if config.has_key? 'sender'
36
+ send_name = config['sender']
37
+ end
38
+
39
+ send_arg = Huck::getarg kwargs, :sender, nil
40
+ send_name = send_arg if !send_arg.nil?
41
+
42
+ s = Sender::factory send_name
43
+ s.send g.dump
44
+ end
45
+
46
+ # Main method to receive messages from a Huck client
47
+ #
48
+ # == Parameters:
49
+ # receiver::
50
+ # The receiver to use (default=sqs)
51
+ #
52
+ def self.serve kwargs = {}
53
+ config = Huck::config
54
+ if config.has_key? 'handler'
55
+ hand_name = config['handler']
56
+ end
57
+
58
+ hand_arg = Huck::getarg kwargs, :handler, nil
59
+ hand_name = hand_arg if !hand_arg.nil?
60
+ h = Handler::factory hand_name
61
+
62
+ if config.has_key? 'receiver'
63
+ recv_name = config['receiver']
64
+ end
65
+
66
+ recv_arg = Huck::getarg kwargs, :receiver, nil
67
+ recv_name = recv_arg if !recv_arg.nil?
68
+
69
+ r = Receiver::factory recv_name
70
+ r.receive do |msg|
71
+ h.handle msg
72
+ end
73
+ end
74
+
75
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: huck
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Uber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Open-ended information sharing framework
70
+ email: ru@ryanuber.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/huck/generators/ohai.rb
76
+ - lib/huck/generators/facter.rb
77
+ - lib/huck/senders/sqs.rb
78
+ - lib/huck/receiver.rb
79
+ - lib/huck/sender.rb
80
+ - lib/huck/util.rb
81
+ - lib/huck/generator.rb
82
+ - lib/huck/receivers/sqs.rb
83
+ - lib/huck/handlers/exec.rb
84
+ - lib/huck/version.rb
85
+ - lib/huck/handler.rb
86
+ - lib/huck.rb
87
+ homepage: https://github.com/ryanuber/huck
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '1.8'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.1.11
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Information sharing framework
111
+ test_files: []