ocular 0.1.1

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: de167ed33e75bba8f6482de164f5b1f7c1fea60a
4
+ data.tar.gz: f9ce4d9717736477221e9a456bfafcd1d6a4d0f9
5
+ SHA512:
6
+ metadata.gz: 260602dd6cef56943d98f5a6271dfd5cded3753a222c1e14d3ba6eb437e45e048f1074b63a09e6e18684c415aeb1856a0dc8837680c1f0b512cf0f078e2b637f
7
+ data.tar.gz: 84e6e806f943dff204d98a39dcf125dbf9a8cf61f7db2f1a0c5b53c2bcb5a7afe6f1fa28e1c68cd9c739a5d9732b7e51b73b12c796d6ad095a8c305ed38215e2
data/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # ocular
2
+ Framework to automate responses for infrastructure events.
3
+
4
+ Ocular allows to easily create small scripts which are triggered from multiple different event sources and which can then execute scripts commanding all kinds of infrastructure, do remote command execution, execute AWS API calls, modify databases and so on.
5
+
6
+ The goal is that a new script could be written really quickly to automate a previously manual infrastructure maintenance job instead of doing the manual job yet another time. Scripts are written in Ruby with a simple Ocular DSL which allows the script to easily respond to multitude different events.
7
+
8
+ Planned event sources:
9
+ - HTTP calls
10
+ - RabbitMQ messages
11
+ - SQS/SNS messages
12
+ - Graphite item triggers
13
+ - Zabbix alerts
14
+ - Timers
15
+
@@ -0,0 +1,11 @@
1
+ require 'pp'
2
+
3
+ onEvent nil do
4
+ asdf("localhost")
5
+ end
6
+
7
+ def asdf(host)
8
+ r = ssh_to(host)
9
+ pp r.execute("ls")
10
+ end
11
+
data/lib/blocktest.rb ADDED
@@ -0,0 +1,40 @@
1
+ # game.rb
2
+
3
+ module MixinTest
4
+
5
+ def setMixingTestValue(val)
6
+ @mixingTestValue = val
7
+ end
8
+
9
+ def getMixingTestValue
10
+ return @mixingTestValue
11
+ end
12
+
13
+ end
14
+
15
+ class BlockTest
16
+
17
+ attr_accessor :testValue
18
+
19
+ include MixinTest
20
+
21
+ def initialize(&block)
22
+ @callback = block
23
+ end
24
+
25
+ def testMethod(val)
26
+ @testValue = val
27
+ end
28
+
29
+ def call(&block)
30
+ block.call
31
+ end
32
+
33
+ def ieval(&block)
34
+ self.instance_eval(&block)
35
+ end
36
+
37
+ def ievaldef
38
+ self.instance_eval(&@callback)
39
+ end
40
+ end
data/lib/ocular.rb ADDED
@@ -0,0 +1,2 @@
1
+
2
+ require 'ocular/ocular.rb'
@@ -0,0 +1,117 @@
1
+ require 'logger'
2
+
3
+ class Ocular
4
+ module DSL
5
+ module Logging
6
+
7
+ def debug(message = nil, &block)
8
+ @logger.add(Logger::Severity::DEBUG, message, @run_id, &block)
9
+ end
10
+ alias log debug
11
+
12
+ def info(message = nil, &block)
13
+ add(Severity::INFO, nil, message, &block)
14
+ end
15
+
16
+ def warn(message = nil, &block)
17
+ add(Severity::INFO, nil, message, &block)
18
+ end
19
+
20
+ def error(message = nil, &block)
21
+ add(Severity::INFO, nil, message, &block)
22
+ end
23
+
24
+ def fatal(message = nil, &block)
25
+ add(Severity::INFO, nil, message, &block)
26
+ end
27
+
28
+
29
+ end
30
+
31
+ # Most of the Logger class is copied from the Ruby Logger class source code.
32
+ class Logger
33
+
34
+ # Logging severity.
35
+ module Severity
36
+ # Low-level information, mostly for developers.
37
+ DEBUG = 0
38
+ # Generic (useful) information about system operation.
39
+ INFO = 1
40
+ # A warning.
41
+ WARN = 2
42
+ # A handleable error condition.
43
+ ERROR = 3
44
+ # An unhandleable error that results in a program crash.
45
+ FATAL = 4
46
+ # An unknown message that should always be logged.
47
+ UNKNOWN = 5
48
+ end
49
+
50
+ def initialize()
51
+ @level = Severity::DEBUG
52
+ @formatter = Logger::Formatter.new
53
+ end
54
+
55
+ def add(severity, message = nil, run_id = nil, &block)
56
+ severity ||= Severity::UNKNOWN
57
+ if severity < @level
58
+ return true
59
+ end
60
+
61
+ if message.nil?
62
+ if block_given?
63
+ message = yield
64
+ else
65
+ message = progname
66
+ end
67
+ end
68
+
69
+ puts format_message(format_severity(severity), Time.now, run_id, message)
70
+ true
71
+ end
72
+
73
+ SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY).each(&:freeze).freeze
74
+
75
+ def format_severity(severity)
76
+ SEV_LABEL[severity] || 'ANY'
77
+ end
78
+
79
+ def format_message(severity, datetime, progname, msg)
80
+ @formatter.call(severity, datetime, progname, msg)
81
+ end
82
+
83
+ # Default formatter for log messages.
84
+ class Formatter
85
+ Format = "%s, [%s#%d] %5s -- %s: %s\n".freeze
86
+
87
+ attr_accessor :datetime_format
88
+
89
+ def initialize
90
+ @datetime_format = nil
91
+ end
92
+
93
+ def call(severity, time, progname, msg)
94
+ Format % [severity[0..0], format_datetime(time), $$, severity, progname, msg2str(msg)]
95
+ end
96
+
97
+ private
98
+
99
+ def format_datetime(time)
100
+ time.strftime(@datetime_format || "%Y-%m-%dT%H:%M:%S.%6N ".freeze)
101
+ end
102
+
103
+ def msg2str(msg)
104
+ case msg
105
+ when ::String
106
+ msg
107
+ when ::Exception
108
+ "#{ msg.message } (#{ msg.class })\n" <<
109
+ (msg.backtrace || []).join("\n")
110
+ else
111
+ msg.inspect
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,28 @@
1
+
2
+ require 'securerandom'
3
+
4
+ class Ocular
5
+ module DSL
6
+ class RunContext
7
+ attr_accessor :run_id
8
+ attr_accessor :proxy
9
+ attr_accessor :class_name
10
+
11
+ include Ocular::DSL::Logging
12
+ include Ocular::DSL::SSH
13
+
14
+ def initialize
15
+ @run_id = SecureRandom.uuid()
16
+ @logger = Ocular::DSL::Logger.new
17
+ end
18
+
19
+ def method_missing(method_sym, *arguments, &block)
20
+ if self.proxy
21
+ self.proxy.send(method_sym, *arguments, &block)
22
+ else
23
+ raise NoMethodError("undefined method `#{method_sym}` in event #{self.class_name}")
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ require 'logger'
2
+ require 'rye'
3
+
4
+ class Ocular
5
+ module DSL
6
+ module SSH
7
+
8
+ def ssh_to(hostname)
9
+ rbox = ::Rye::Box.new(hostname, :safe => false, :password_prompt => false)
10
+ return rbox
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ require 'ocular/mixin/from_file'
2
+ require 'ocular/dsl/ssh'
3
+ require 'ocular/dsl/logging'
4
+
5
+ class Ocular
6
+ module DSL
7
+
8
+ class EventBase
9
+ include Ocular::DSL::SSH
10
+ include Ocular::DSL::Logging
11
+
12
+ attr_accessor :proxy
13
+
14
+
15
+ def initialize(&block)
16
+ @callback = block
17
+ end
18
+
19
+ def exec(run_context)
20
+ puts "Running #{run_context}"
21
+ run_context.proxy = self.proxy
22
+ run_context.instance_eval(&@callback)
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,47 @@
1
+ require 'ocular/event/eventbase.rb'
2
+
3
+ class Ocular
4
+ module Event
5
+ class DefinitionProxy
6
+ attr_accessor :events
7
+ attr_accessor :klass_name
8
+
9
+ def initialize(klass_name)
10
+ self.klass_name = klass_name
11
+ @events = []
12
+ @logger = Ocular::DSL::Logger.new
13
+ end
14
+
15
+ include Ocular::Mixin::FromFile
16
+ include Ocular::DSL::Logging
17
+
18
+ def onEvent(factory_class, &block)
19
+ eventbase = Ocular::DSL::EventBase.new(&block)
20
+ eventbase.proxy = self
21
+ @events << eventbase
22
+ end
23
+ end
24
+
25
+ class EventFactory
26
+
27
+ def initialize
28
+ @files = {}
29
+ end
30
+
31
+ def load_from_file(file)
32
+ proxy = DefinitionProxy.new(file)
33
+ proxy.from_file(file)
34
+ @files[file] = proxy
35
+ return proxy
36
+ end
37
+
38
+ def load_from_block(name, &block)
39
+ proxy = DefinitionProxy.new(name)
40
+ proxy.instance_eval(&block)
41
+ @files[name] = proxy
42
+ return proxy
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,49 @@
1
+ #
2
+ # OriginalAuthor:: Adam Jacob (<adam@opscode.com>)
3
+ # OriginalAuthor:: Christopher Walters (<cw@opscode.com>)
4
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ class Ocular
20
+ module Mixin
21
+ module FromFile
22
+
23
+ # Loads a given ruby file, and runs instance_eval against it in the context of the current
24
+ # object.
25
+ #
26
+ # Raises an IOError if the file cannot be found, or is not readable.
27
+ def from_file(filename)
28
+ if File.exists?(filename) && File.readable?(filename)
29
+ self.instance_eval(IO.read(filename), filename, 1)
30
+ else
31
+ raise IOError, "Cannot open or read #{filename}!"
32
+ end
33
+ end
34
+
35
+ # Loads a given ruby file, and runs class_eval against it in the context of the current
36
+ # object.
37
+ #
38
+ # Raises an IOError if the file cannot be found, or is not readable.
39
+ def class_from_file(filename)
40
+ if File.exists?(filename) && File.readable?(filename)
41
+ self.class_eval(IO.read(filename), filename, 1)
42
+ else
43
+ raise IOError, "Cannot open or read #{filename}!"
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,7 @@
1
+
2
+ require 'ocular/version'
3
+ require 'ocular/event/eventbase'
4
+ require 'ocular/event/eventfactory'
5
+ require 'ocular/dsl/logging'
6
+ require 'ocular/dsl/ssh'
7
+ require 'ocular/dsl/runcontext'
@@ -0,0 +1,3 @@
1
+ class Ocular
2
+ Version = "0.1.1"
3
+ end
@@ -0,0 +1,70 @@
1
+ #require_relative "../lib/game.rb"
2
+ require 'blocktest'
3
+
4
+ def globalMethodForTesting(val)
5
+ $globalMethodVariable = val
6
+ end
7
+
8
+ RSpec.describe BlockTest do
9
+ describe "#call" do
10
+ it "can call a block" do
11
+ test = BlockTest.new
12
+ a = false
13
+ test.call do
14
+ a = true
15
+ end
16
+ expect(a).to eq(true)
17
+ end
18
+ end
19
+
20
+ describe "#ieval" do
21
+ it "can instance_eval a block" do
22
+ test = BlockTest.new
23
+ a = false
24
+ test.ieval do
25
+ a = true
26
+ end
27
+ expect(a).to eq(true)
28
+ end
29
+
30
+ it "can call a BlockTest method" do
31
+ test = BlockTest.new
32
+ test.ieval do
33
+ testMethod(2)
34
+ end
35
+ expect(test.testValue).to eq(2)
36
+ end
37
+
38
+ it "can call a BlockTest method while calling global methods" do
39
+ test = BlockTest.new
40
+ test.ieval do
41
+ globalMethodForTesting(3)
42
+ end
43
+ expect($globalMethodVariable).to eq(3)
44
+ end
45
+
46
+ it "can call a mixin function" do
47
+ test = BlockTest.new
48
+ test.ieval do
49
+ setMixingTestValue(6)
50
+ end
51
+ expect(test.getMixingTestValue).to eq(6)
52
+ end
53
+ end
54
+
55
+ describe "#ievaldef" do
56
+ it "can execute callback from initialise" do
57
+ a = false
58
+ test = BlockTest.new do
59
+ a = true
60
+ end
61
+ test.ievaldef
62
+ expect(a).to eq(true)
63
+
64
+
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
@@ -0,0 +1,6 @@
1
+ $:.unshift(File.dirname(__FILE__) + '../lib')
2
+
3
+ RSpec.configure do |config|
4
+ config.color = true
5
+ end
6
+
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ocular
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Juho Mäkinen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rye
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.13
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.13
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 3.4.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 3.4.0
41
+ description: |+
42
+ Framework to automate responses for infrastructure events.
43
+
44
+ Ocular allows to easily create small scripts which are triggered from multiple different event sources and which can then execute scripts commanding all kinds of infrastructure, do remote command execution, execute AWS API calls, modify databases and so on.
45
+
46
+ The goal is that a new script could be written really quickly to automate a previously manual infrastructure maintenance job instead of doing the manual job yet another time. Scripts are written in Ruby with a simple Ocular DSL which allows the script to easily respond to multitude different events.
47
+
48
+ email: juho@unity3d.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - README.md
54
+ - examples/ssh-example.rb
55
+ - lib/blocktest.rb
56
+ - lib/ocular.rb
57
+ - lib/ocular/dsl/logging.rb
58
+ - lib/ocular/dsl/runcontext.rb
59
+ - lib/ocular/dsl/ssh.rb
60
+ - lib/ocular/event/eventbase.rb
61
+ - lib/ocular/event/eventfactory.rb
62
+ - lib/ocular/mixin/from_file.rb
63
+ - lib/ocular/ocular.rb
64
+ - lib/ocular/version.rb
65
+ - spec/blocktest_spec.rb
66
+ - spec/spec_helper.rb
67
+ homepage: http://github.com/garo/ocular
68
+ licenses:
69
+ - Apache 2.0
70
+ metadata: {}
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 2.4.5.1
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: Tool to create simple operational scripts
91
+ test_files: []