daf 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +71 -0
- data/LICENSE.txt +21 -0
- data/README.md +37 -0
- data/Rakefile +23 -0
- data/bin/dad +5 -0
- data/daf.gemspec +35 -0
- data/examples/config/SendEmail.yaml +16 -0
- data/lib/daf.rb +50 -0
- data/lib/daf/action.rb +25 -0
- data/lib/daf/actions/email_action.rb +34 -0
- data/lib/daf/actions/pushbullet_action.rb +26 -0
- data/lib/daf/actions/shell_action.rb +21 -0
- data/lib/daf/actions/sms_action.rb +25 -0
- data/lib/daf/command.rb +55 -0
- data/lib/daf/configurable.rb +145 -0
- data/lib/daf/datasources/yaml_data_source.rb +53 -0
- data/lib/daf/monitor.rb +27 -0
- data/lib/daf/monitors/file_update_monitor.rb +46 -0
- data/lib/daf/version.rb +4 -0
- data/spec/action_spec.rb +38 -0
- data/spec/command_spec.rb +78 -0
- data/spec/configurable_spec.rb +62 -0
- data/spec/daf_spec.rb +93 -0
- data/spec/email_action_spec.rb +61 -0
- data/spec/file_update_monitor_spec.rb +85 -0
- data/spec/monitor_spec.rb +41 -0
- data/spec/shell_action_spec.rb +55 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/yaml_data_source_spec.rb +117 -0
- metadata +188 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7fda2ec5348bcba315e6b234fe2d074ebdff16f1
|
4
|
+
data.tar.gz: 6c59a79b72716fedf16e9724a3c9dcd73ed7a07e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d2d94f5e13286e1f9be111612bcdd687ad91231d6060b997ffd9383ad88d529804953241c983673faa558680731efb1f84455e2006dde905513ab8c06e97e6bd
|
7
|
+
data.tar.gz: 4bcf8c5103e21bcafb9dc39a98083d251cfae11afe2a12fe667c3a0045d2744a81a9bc0dd1062255805237df81a3665ac97c621eadc709d8de4e5ae6da0be007
|
data/.gitignore
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
26
|
+
|
27
|
+
# for a library or gem, you might want to ignore these files since the code is
|
28
|
+
# intended to run in multiple environments; otherwise, check them in:
|
29
|
+
# Gemfile.lock
|
30
|
+
# .ruby-version
|
31
|
+
# .ruby-gemset
|
32
|
+
|
33
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
34
|
+
.rvmrc
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
daf (0.3.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.0.0)
|
10
|
+
astrolabe (1.3.0)
|
11
|
+
parser (>= 2.2.0.pre.3, < 3.0)
|
12
|
+
builder (3.2.2)
|
13
|
+
diff-lcs (1.2.5)
|
14
|
+
docile (1.1.5)
|
15
|
+
faraday (0.9.1)
|
16
|
+
multipart-post (>= 1.2, < 3)
|
17
|
+
jwt (1.5.0)
|
18
|
+
mime-types (2.6.1)
|
19
|
+
multi_json (1.10.1)
|
20
|
+
multipart-post (2.0.0)
|
21
|
+
parser (2.2.0.pre.8)
|
22
|
+
ast (>= 1.1, < 3.0)
|
23
|
+
slop (~> 3.4, >= 3.4.5)
|
24
|
+
powerpack (0.0.9)
|
25
|
+
rainbow (2.0.0)
|
26
|
+
rake (10.3.2)
|
27
|
+
rspec (3.1.0)
|
28
|
+
rspec-core (~> 3.1.0)
|
29
|
+
rspec-expectations (~> 3.1.0)
|
30
|
+
rspec-mocks (~> 3.1.0)
|
31
|
+
rspec-core (3.1.7)
|
32
|
+
rspec-support (~> 3.1.0)
|
33
|
+
rspec-expectations (3.1.2)
|
34
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
35
|
+
rspec-support (~> 3.1.0)
|
36
|
+
rspec-mocks (3.1.3)
|
37
|
+
rspec-support (~> 3.1.0)
|
38
|
+
rspec-support (3.1.2)
|
39
|
+
rubocop (0.27.1)
|
40
|
+
astrolabe (~> 1.3)
|
41
|
+
parser (>= 2.2.0.pre.7, < 3.0)
|
42
|
+
powerpack (~> 0.0.6)
|
43
|
+
rainbow (>= 1.99.1, < 3.0)
|
44
|
+
ruby-progressbar (~> 1.4)
|
45
|
+
ruby-progressbar (1.7.0)
|
46
|
+
simplecov (0.9.1)
|
47
|
+
docile (~> 1.1.0)
|
48
|
+
multi_json (~> 1.0)
|
49
|
+
simplecov-html (~> 0.8.0)
|
50
|
+
simplecov-html (0.8.0)
|
51
|
+
slop (3.6.0)
|
52
|
+
twilio-ruby (4.2.0)
|
53
|
+
builder (>= 2.1.2)
|
54
|
+
jwt (~> 1.0)
|
55
|
+
multi_json (>= 1.3.0)
|
56
|
+
washbullet (0.4.0)
|
57
|
+
faraday (~> 0.9.0)
|
58
|
+
mime-types
|
59
|
+
|
60
|
+
PLATFORMS
|
61
|
+
ruby
|
62
|
+
|
63
|
+
DEPENDENCIES
|
64
|
+
bundler (>= 1.6)
|
65
|
+
daf!
|
66
|
+
rake
|
67
|
+
rspec
|
68
|
+
rubocop
|
69
|
+
simplecov
|
70
|
+
twilio-ruby
|
71
|
+
washbullet
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Kayla McArthur
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
## Dynamic Action Framework
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/daf.svg)](http://badge.fury.io/rb/daf) [![Build Status](https://kayla-ci.org/klmcarthur/DAF.svg?branch=master)](https://kayla-ci.org/klmcarthur/DAF) [![Inline docs](http://inch-ci.org/github/klmcarthur/DAF.svg?branch=master)](http://inch-ci.org/github/klmcarthur/DAF) [![Code Climate](https://codeclimate.com/github/klmcarthur/DAF/badges/gpa.svg)](https://codeclimate.com/github/klmcarthur/DAF)
|
4
|
+
|
5
|
+
|
6
|
+
https://rubygems.org/gems/daf
|
7
|
+
|
8
|
+
Dynamic Action Framework, or DAF, is a flexible, extensible system to let a user trigger actions based on events, either on a system or through anything else you can write in Ruby. Some examples of things you can automate using DAF:
|
9
|
+
|
10
|
+
* When my bus is 10 minutes away, text me
|
11
|
+
* When I get an email from my mother, text me the contents
|
12
|
+
* When I'm five minutes away from a meeting, send me the agenda
|
13
|
+
* Automatically create a blog entry based on my tweets
|
14
|
+
* Automatically download any picture from facebook that has me tagged
|
15
|
+
* Alert me when the weather changes via text message
|
16
|
+
|
17
|
+
In addition, you could use it as a library to develop other action systems, including things like:
|
18
|
+
|
19
|
+
* Server monitoring systems
|
20
|
+
* Email filtering systems
|
21
|
+
|
22
|
+
DAF integrates with other action systems such as IFTTT in numerous ways, the easiest probably being through use of Dropbox and monitoring file modification times. Using DAF with these services permits an even greater level of integration and customizability.
|
23
|
+
|
24
|
+
### Planned Features
|
25
|
+
|
26
|
+
* Additional plugins for input/output
|
27
|
+
* A robust Erlang daemon that uses Ruby framework to provide high availability monitor
|
28
|
+
* Additional input sources (SQL, Socket/Listening API, etc)
|
29
|
+
* REST API layer
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
If you're interested in contributing custom actions or monitors you've written, please just submit a pull request - http://github.com/klmcarthur/DAF - and I'll happily have a look.
|
34
|
+
|
35
|
+
If you're interested in using DAF in something else, or have a different front-end experience, please let me know as well, for front-ends, I'd love to bring it into the core if it's interesting or useful, and for third party projects I'd love to link to you.
|
36
|
+
|
37
|
+
Thanks!
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
require 'rspec/core'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
task default: :validate
|
9
|
+
|
10
|
+
desc 'Validate Package'
|
11
|
+
task validate: [:rubocop, :spec]
|
12
|
+
|
13
|
+
desc 'Run RuboCop'
|
14
|
+
task :rubocop do
|
15
|
+
require 'rubocop/rake_task'
|
16
|
+
RuboCop::RakeTask.new
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Build Documentation'
|
20
|
+
task :yard do
|
21
|
+
require 'yard'
|
22
|
+
YARD::Rake::YardocTask.new
|
23
|
+
end
|
data/bin/dad
ADDED
data/daf.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'daf/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'daf'
|
8
|
+
spec.version = DAF::VERSION
|
9
|
+
spec.authors = ['Kayla McArthur']
|
10
|
+
spec.email = ['kayla@kayla.is']
|
11
|
+
spec.summary = 'A daemon and framework for monitoring events, '\
|
12
|
+
'and triggering actions'
|
13
|
+
spec.description = 'A library and corresponding daemon based on that '\
|
14
|
+
'library to monitor a number of sources for events '\
|
15
|
+
'and trigger actions based on those events. '\
|
16
|
+
'Includes a default set of monitors and actions '\
|
17
|
+
'and tools to create more'
|
18
|
+
spec.homepage = 'http://github.com/klmcarthur/DAF'
|
19
|
+
spec.license = 'MIT'
|
20
|
+
|
21
|
+
spec.files = `git ls-files -z`.split("\x0")
|
22
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
23
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
24
|
+
spec.require_paths = ['lib']
|
25
|
+
spec.required_ruby_version = '>= 2.0.0'
|
26
|
+
|
27
|
+
spec.add_development_dependency 'bundler', '>= 1.6'
|
28
|
+
spec.add_development_dependency 'rake'
|
29
|
+
spec.add_development_dependency 'rubocop'
|
30
|
+
spec.add_development_dependency 'simplecov'
|
31
|
+
spec.add_development_dependency 'rspec'
|
32
|
+
spec.add_development_dependency 'twilio-ruby'
|
33
|
+
spec.add_development_dependency 'washbullet'
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
Monitor:
|
3
|
+
Type: FileUpdateMonitor
|
4
|
+
Options:
|
5
|
+
path: /tmp/test1
|
6
|
+
frequency: 2
|
7
|
+
|
8
|
+
Action:
|
9
|
+
Type: EmailAction
|
10
|
+
Options:
|
11
|
+
to: test@example.com
|
12
|
+
from: test@example.com
|
13
|
+
subject: "File updated at {{time}}"
|
14
|
+
body: "Contents of File: {{contentts}}"
|
15
|
+
server: localhost
|
16
|
+
---
|
data/lib/daf.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'daf/datasources/yaml_data_source'
|
2
|
+
|
3
|
+
# Starts the DAF daemon (DAD) - takes a directory
|
4
|
+
# containing the YAML files for monitor/action pairs
|
5
|
+
# After parsing configuration, will daemonize and continue
|
6
|
+
# monitoring until SIGTERM is received
|
7
|
+
#
|
8
|
+
# @author Kayla McArthur (mailto:kayla@kayla.is)
|
9
|
+
# @icense MIT License
|
10
|
+
module DAF
|
11
|
+
def start_dad
|
12
|
+
if ARGV[0] && File.directory?(ARGV[0])
|
13
|
+
commands = []
|
14
|
+
|
15
|
+
Dir[ARGV[0] + '/*.yaml'].each do |file|
|
16
|
+
commands << Command.new(YAMLDataSource.new(file))
|
17
|
+
end
|
18
|
+
|
19
|
+
dad = DynamicActionDaemon.new(commands)
|
20
|
+
dad.start
|
21
|
+
else
|
22
|
+
print_usage
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def print_usage
|
27
|
+
puts 'DAF not started - please see below'
|
28
|
+
puts 'Usage: daf [path to config folder]'
|
29
|
+
puts 'Directory must contain one or more config'
|
30
|
+
puts 'files with a .yaml extension'
|
31
|
+
end
|
32
|
+
|
33
|
+
# This class represents the Dynamic Action Daemon
|
34
|
+
# it requires a set of commands to be passed in
|
35
|
+
class DynamicActionDaemon
|
36
|
+
# Initializes DAD with a given command set
|
37
|
+
#
|
38
|
+
# @param commands [Array] Array containing Command objects
|
39
|
+
def initialize(commands)
|
40
|
+
@commands = commands
|
41
|
+
end
|
42
|
+
|
43
|
+
# Starts the daemon - this method will block for duration
|
44
|
+
# of execution of program
|
45
|
+
def start
|
46
|
+
@commands.each(&:execute)
|
47
|
+
sleep
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/daf/action.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'daf/configurable'
|
2
|
+
|
3
|
+
module DAF
|
4
|
+
# Stores information related to actions that can
|
5
|
+
# be taken as a result of a Monitor firing
|
6
|
+
# Exposes only one method, and is a Configurable
|
7
|
+
class Action
|
8
|
+
include Configurable
|
9
|
+
|
10
|
+
# Activate this action using given options - takes an optional
|
11
|
+
# block parameter that will be invoked when action
|
12
|
+
# is complete, with a parameter of if the action was successful
|
13
|
+
# and also returns if action was successful
|
14
|
+
#
|
15
|
+
# @param options [Hash] A hash of options with name/value pairs, must
|
16
|
+
# match types expected for each option or will raise an exception
|
17
|
+
# @yield If successful, will execute the optional block passed in
|
18
|
+
def activate(options)
|
19
|
+
process_options(options)
|
20
|
+
success = invoke
|
21
|
+
yield success if block_given?
|
22
|
+
success
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'daf/action'
|
2
|
+
require 'net/smtp'
|
3
|
+
|
4
|
+
module DAF
|
5
|
+
# An action that sends an email based on parameters
|
6
|
+
class EmailAction < Action
|
7
|
+
attr_option :to, String, :required
|
8
|
+
attr_option :from, String, :required
|
9
|
+
attr_option :subject, String, :required
|
10
|
+
attr_option :body, String, :required
|
11
|
+
attr_option :server, String, :required
|
12
|
+
attr_option :port, Integer
|
13
|
+
|
14
|
+
def invoke
|
15
|
+
message = format_email(@to.value, @from.value,
|
16
|
+
@subject.value, @body.value)
|
17
|
+
port = self.port.valid? ? self.port.value : 25
|
18
|
+
Net::SMTP.start(@server.value, port) do |smtp|
|
19
|
+
smtp.send_message(message, @from.value, @to.value)
|
20
|
+
end
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def format_email(to, from, subject, body)
|
25
|
+
<<TEXT
|
26
|
+
From: #{from}
|
27
|
+
To: #{to}
|
28
|
+
Subject: #{subject}
|
29
|
+
|
30
|
+
#{body}
|
31
|
+
TEXT
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'daf/action'
|
2
|
+
require 'washbullet'
|
3
|
+
|
4
|
+
module DAF
|
5
|
+
# An action that sends an sms using twilio based on parameters
|
6
|
+
class PushbulletAction < Action
|
7
|
+
attr_option :key, String, :required
|
8
|
+
attr_option :identifier, String, :required
|
9
|
+
attr_option :title, String, :required
|
10
|
+
attr_option :message, String, :required
|
11
|
+
|
12
|
+
def client
|
13
|
+
@client ||= Washbullet::Client.new(@key)
|
14
|
+
end
|
15
|
+
|
16
|
+
def invoke
|
17
|
+
client.push_note(receiver: :device,
|
18
|
+
identifier: @identifier,
|
19
|
+
params: {
|
20
|
+
title: @title,
|
21
|
+
body: @message
|
22
|
+
}
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'daf/action'
|
2
|
+
require 'English'
|
3
|
+
|
4
|
+
module DAF
|
5
|
+
# An action that executes a shell script
|
6
|
+
class ShellAction < Action
|
7
|
+
attr_option :path, String, :required do |value|
|
8
|
+
File.executable?(value)
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_option :arguments, String
|
12
|
+
|
13
|
+
attr_output :results, String
|
14
|
+
|
15
|
+
def invoke
|
16
|
+
arguments = self.arguments.value ? " #{self.arguments.value}" : ''
|
17
|
+
@results = `#{path.value}#{arguments}`
|
18
|
+
$CHILD_STATUS.exitstatus
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|