sonar_connector 0.8.5
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.
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +41 -0
- data/VERSION +1 -0
- data/bin/sonar-connector +69 -0
- data/config/config.example.json +82 -0
- data/lib/sonar_connector.rb +40 -0
- data/lib/sonar_connector/commands/command.rb +21 -0
- data/lib/sonar_connector/commands/commit_seppuku_command.rb +15 -0
- data/lib/sonar_connector/commands/increment_status_value_command.rb +14 -0
- data/lib/sonar_connector/commands/send_admin_email_command.rb +12 -0
- data/lib/sonar_connector/commands/update_disk_usage_command.rb +13 -0
- data/lib/sonar_connector/commands/update_status_command.rb +16 -0
- data/lib/sonar_connector/config.rb +166 -0
- data/lib/sonar_connector/connectors/base.rb +243 -0
- data/lib/sonar_connector/connectors/dummy_connector.rb +17 -0
- data/lib/sonar_connector/connectors/seppuku_connector.rb +26 -0
- data/lib/sonar_connector/consumer.rb +94 -0
- data/lib/sonar_connector/controller.rb +164 -0
- data/lib/sonar_connector/emailer.rb +16 -0
- data/lib/sonar_connector/rspec/spec_helper.rb +61 -0
- data/lib/sonar_connector/status.rb +43 -0
- data/lib/sonar_connector/utils.rb +39 -0
- data/script/console +10 -0
- data/spec/sonar_connector/commands/command_spec.rb +34 -0
- data/spec/sonar_connector/commands/commit_seppuku_command_spec.rb +25 -0
- data/spec/sonar_connector/commands/increment_status_value_command_spec.rb +25 -0
- data/spec/sonar_connector/commands/send_admin_email_command_spec.rb +14 -0
- data/spec/sonar_connector/commands/update_disk_usage_command_spec.rb +21 -0
- data/spec/sonar_connector/commands/update_status_command_spec.rb +24 -0
- data/spec/sonar_connector/config_spec.rb +93 -0
- data/spec/sonar_connector/connectors/base_spec.rb +207 -0
- data/spec/sonar_connector/connectors/dummy_connector_spec.rb +22 -0
- data/spec/sonar_connector/connectors/seppuku_connector_spec.rb +37 -0
- data/spec/sonar_connector/consumer_spec.rb +116 -0
- data/spec/sonar_connector/controller_spec.rb +46 -0
- data/spec/sonar_connector/emailer_spec.rb +36 -0
- data/spec/sonar_connector/status_spec.rb +78 -0
- data/spec/sonar_connector/utils_spec.rb +62 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +6 -0
- metadata +235 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Trampoline Systems Ltd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Trampoline SONAR Connector framework
|
2
|
+
|
3
|
+
== Dependencies
|
4
|
+
|
5
|
+
=== Jruby
|
6
|
+
|
7
|
+
Here's how to install jruby 1.4.0 on OS X:
|
8
|
+
|
9
|
+
wget http://jruby.kenai.com/downloads/1.4.0/jruby-bin-1.4.0.tar.gz
|
10
|
+
sudo tar xfvz jruby-bin-1.4.0.tar.gz -C /usr/local/
|
11
|
+
ln -s /usr/local/jruby/bin/jruby /usr/bin/jruby
|
12
|
+
ln -s /usr/local/jruby/bin/rake /usr/bin/jrake
|
13
|
+
ln -s /usr/local/jruby/bin/gem /usr/bin/jgem
|
14
|
+
ln -s /usr/local/jruby/bin/jirb /usr/bin/jirb
|
15
|
+
|
16
|
+
== Copyright
|
17
|
+
|
18
|
+
Copyright (c) 2010 Trampoline Systems Ltd. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "sonar_connector"
|
8
|
+
gem.summary = %Q{A behind-the-firewall connector for Trampoline SONAR}
|
9
|
+
gem.description = %Q{Framework that allows arbitrary push and pull connectors to send data to an instance of the Trampoline SONAR server}
|
10
|
+
gem.email = "hello@empire42.com"
|
11
|
+
gem.homepage = "http://github.com/trampoline/sonar-connector"
|
12
|
+
gem.authors = ["Peter MacRobert", "Mark Meyer"]
|
13
|
+
|
14
|
+
gem.add_dependency "actionmailer", "= 2.3.10"
|
15
|
+
gem.add_dependency "actionmailer_extensions", ">= 0.4.2"
|
16
|
+
gem.add_dependency "json_pure", ">= 1.2.2"
|
17
|
+
gem.add_dependency "uuidtools", ">= 2.1.1"
|
18
|
+
gem.add_dependency "sonar_connector_filestore", ">= 0.1.0"
|
19
|
+
|
20
|
+
gem.add_development_dependency "rspec", ">= 1.2.8"
|
21
|
+
gem.add_development_dependency "rr", ">= 0.10.5"
|
22
|
+
end
|
23
|
+
Jeweler::GemcutterTasks.new
|
24
|
+
rescue LoadError
|
25
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'spec/rake/spectask'
|
29
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
35
|
+
spec.libs << 'lib' << 'spec'
|
36
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
37
|
+
spec.rcov = true
|
38
|
+
end
|
39
|
+
|
40
|
+
task :default => :spec
|
41
|
+
task :spec => :check_dependencies
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.8.5
|
data/bin/sonar-connector
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'sonar_connector')
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
config_filename = File.expand_path File.join(Dir.pwd, "config", "config.json")
|
7
|
+
mode = nil
|
8
|
+
install_path = nil
|
9
|
+
|
10
|
+
ARGV.options do |opts|
|
11
|
+
script_name = File.basename($0)
|
12
|
+
|
13
|
+
opts.banner = "Usage: #{script_name} OPTION"
|
14
|
+
|
15
|
+
opts.separator "Run modes:"
|
16
|
+
opts.on("--start", "Start the connector") { mode = :start }
|
17
|
+
opts.on("--check", "Validate the connector config") { mode = :check }
|
18
|
+
opts.on("--install=PATH", String, "Install the connector working dir and default config to the file system") {|p|
|
19
|
+
install_path = p
|
20
|
+
mode = :install
|
21
|
+
}
|
22
|
+
opts.on("--console", "Run IRB console in connector framework environment") { mode = :console }
|
23
|
+
|
24
|
+
opts.separator "Options:"
|
25
|
+
|
26
|
+
opts.on("-c", "--config=FILE", String, "Override the path to the config file.") {|s| config_filename = File.expand_path s}
|
27
|
+
|
28
|
+
opts.separator "Misc:"
|
29
|
+
opts.on_tail("-v", "--version", "Show version") { mode = :version }
|
30
|
+
opts.on_tail("-h", "--help", "Show this message")
|
31
|
+
opts.parse!
|
32
|
+
end
|
33
|
+
|
34
|
+
case mode
|
35
|
+
when :start
|
36
|
+
puts "Starting SONAR Connector from config file: #{config_filename}"
|
37
|
+
connector = Sonar::Connector::Controller.new(config_filename)
|
38
|
+
puts "Connector bootstrapped successfully, check log files for details."
|
39
|
+
connector.start
|
40
|
+
exit
|
41
|
+
|
42
|
+
when :check
|
43
|
+
puts "Checking config file: #{config_filename}"
|
44
|
+
Sonar::Connector::Controller.new(config_filename)
|
45
|
+
puts "...clean."
|
46
|
+
exit
|
47
|
+
when :install
|
48
|
+
path = File.expand_path install_path
|
49
|
+
|
50
|
+
if File.directory?(path)
|
51
|
+
puts "Error: Directory '#{path}' already exists, aborting."
|
52
|
+
exit(1)
|
53
|
+
end
|
54
|
+
|
55
|
+
%W{config log var}.each {|dir| FileUtils.mkdir_p File.join(path, dir)}
|
56
|
+
FileUtils.cp File.join(Sonar::Connector::ROOT, '..', "config", "config.example.json"), File.join(path, 'config', 'config.json')
|
57
|
+
puts "Success: Set up working directory '#{path}' and associated subdirs."
|
58
|
+
exit
|
59
|
+
when :console
|
60
|
+
lib_path = File.expand_path File.join(File.dirname(__FILE__), '..', 'lib')
|
61
|
+
Kernel.system "irb -rubygems -I #{lib_path} -r sonar_connector.rb"
|
62
|
+
exit
|
63
|
+
when :version
|
64
|
+
version_file = File.join File.expand_path(File.dirname(__FILE__)), "..", "VERSION"
|
65
|
+
puts "SONAR Connector Framework #{File.read(version_file)}"
|
66
|
+
exit
|
67
|
+
else
|
68
|
+
puts ARGV.options
|
69
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
{
|
2
|
+
/* log level must be one of: "debug", "info", "warn", "error", "fatal" */
|
3
|
+
"log_level" : "debug",
|
4
|
+
|
5
|
+
/* max log file size in megabytes */
|
6
|
+
"log_file_max_size" : "10",
|
7
|
+
|
8
|
+
/* number of log files to keep */
|
9
|
+
"log_files_to_keep" : "7",
|
10
|
+
|
11
|
+
"email_settings": {
|
12
|
+
"admin_recipients": ["admin@server.local"],
|
13
|
+
"admin_sender": "Sonar Connector <noreply@server.local>",
|
14
|
+
"perform_deliveries": false,
|
15
|
+
|
16
|
+
/* options are ["smtp", "sendmail", "test"] */
|
17
|
+
"delivery_method": "smtp",
|
18
|
+
"save_emails_to_disk": true,
|
19
|
+
|
20
|
+
"smtp_settings": {
|
21
|
+
"address": "127.0.0.1",
|
22
|
+
"port": 25,
|
23
|
+
"domain": "server.local",
|
24
|
+
"user_name": null,
|
25
|
+
"password": null,
|
26
|
+
|
27
|
+
/* options are ["plain", "login", "cram_md5"] */
|
28
|
+
"authentication": null
|
29
|
+
},
|
30
|
+
|
31
|
+
"sendmail_settings": {
|
32
|
+
"location": "/usr/sbin/sendmail",
|
33
|
+
"arguments": "-i -t -f nobody@localhost"
|
34
|
+
}
|
35
|
+
},
|
36
|
+
|
37
|
+
/*
|
38
|
+
Specific configuration for each connector. Each connector must have
|
39
|
+
a class and a unique name. The require load path can also be specified if necessary.
|
40
|
+
Note that each connector type may have further configuration options
|
41
|
+
that are specific to the connector class.
|
42
|
+
*/
|
43
|
+
"connectors": [
|
44
|
+
{
|
45
|
+
"class": "Sonar::Connector::ImapPullConnector",
|
46
|
+
"require": "sonar_imap_pull_connector",
|
47
|
+
"name": "gmail_1",
|
48
|
+
"repeat_delay": 10,
|
49
|
+
"host": "imap.gmail.com",
|
50
|
+
"user": "foo@bar.com",
|
51
|
+
"password": "---",
|
52
|
+
"folders": "[Gmail]/All Mail"
|
53
|
+
}
|
54
|
+
,
|
55
|
+
{
|
56
|
+
"class": "Sonar::Connector::ImapPullConnector",
|
57
|
+
"require": "sonar_imap_pull_connector",
|
58
|
+
"name": "gmail_2",
|
59
|
+
"repeat_delay": 10,
|
60
|
+
"host": "imap.gmail.com",
|
61
|
+
"user": "baz@bar.com",
|
62
|
+
"password": "---",
|
63
|
+
"folders": "[Google Mail]/All Mail"
|
64
|
+
}
|
65
|
+
,
|
66
|
+
{
|
67
|
+
"class": "Sonar::Connector::SonarPushConnector",
|
68
|
+
"require": "sonar_push_connector",
|
69
|
+
"name": "sonar_push",
|
70
|
+
"repeat_delay": 10,
|
71
|
+
"source_connectors": ["gmail_1", "gmail_2"],
|
72
|
+
"uri": "http://localhost:3000/api/1_0/rfc822_messages",
|
73
|
+
"connector_credentials": "---"
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"class": "Sonar::Connector::SeppukuConnector",
|
77
|
+
"name": "seppuku",
|
78
|
+
"enabled": true,
|
79
|
+
"repeat_delay": 43200
|
80
|
+
}
|
81
|
+
]
|
82
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Sonar
|
2
|
+
module Connector
|
3
|
+
ROOT = File.dirname(__FILE__) unless Sonar::Connector.const_defined?("ROOT")
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
$:.unshift(File.expand_path("..", __FILE__))
|
9
|
+
|
10
|
+
# Load external deps
|
11
|
+
require 'active_support'
|
12
|
+
require 'json'
|
13
|
+
require 'yaml'
|
14
|
+
require 'thread'
|
15
|
+
require 'logger'
|
16
|
+
require 'action_mailer'
|
17
|
+
require 'actionmailer_extensions'
|
18
|
+
require 'fileutils'
|
19
|
+
require 'sonar_connector_filestore'
|
20
|
+
|
21
|
+
# Load internal classes
|
22
|
+
%W(
|
23
|
+
controller
|
24
|
+
config
|
25
|
+
status
|
26
|
+
consumer
|
27
|
+
emailer
|
28
|
+
utils
|
29
|
+
connectors/base
|
30
|
+
connectors/dummy_connector
|
31
|
+
connectors/seppuku_connector
|
32
|
+
commands/command
|
33
|
+
commands/update_status_command
|
34
|
+
commands/send_admin_email_command
|
35
|
+
commands/update_disk_usage_command
|
36
|
+
commands/increment_status_value_command
|
37
|
+
commands/commit_seppuku_command
|
38
|
+
).each do |file|
|
39
|
+
require File.join('sonar_connector', file)
|
40
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Sonar
|
2
|
+
module Connector
|
3
|
+
|
4
|
+
##
|
5
|
+
# Base command class that all commands should subclass.
|
6
|
+
|
7
|
+
class Command
|
8
|
+
|
9
|
+
attr_accessor :proc
|
10
|
+
|
11
|
+
def initialize(proc)
|
12
|
+
@proc = proc
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute(context = nil)
|
16
|
+
context.instance_eval(&@proc)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Sonar
|
2
|
+
module Connector
|
3
|
+
|
4
|
+
class CommitSeppukuCommand < Sonar::Connector::Command
|
5
|
+
def initialize
|
6
|
+
l = lambda do
|
7
|
+
# controller is in scope here because we've jumped thru some serious hoops
|
8
|
+
# and shaved the hell out of a yak or three.
|
9
|
+
Thread.new {controller.shutdown_lambda.call}
|
10
|
+
end
|
11
|
+
super(l)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Sonar
|
2
|
+
module Connector
|
3
|
+
|
4
|
+
class IncrementStatusValueCommand < Sonar::Connector::Command
|
5
|
+
def initialize(connector, field, value = 1)
|
6
|
+
l = lambda do
|
7
|
+
current = status[connector.name] ? status[connector.name][field].to_i : 0
|
8
|
+
status.set connector.name, field, current+value
|
9
|
+
end
|
10
|
+
super(l)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Sonar
|
2
|
+
module Connector
|
3
|
+
class UpdateDiskUsageCommand < Sonar::Connector::Command
|
4
|
+
def initialize(connector)
|
5
|
+
l = lambda do
|
6
|
+
du = (Sonar::Connector::Utils.du(connector.connector_dir).to_f / 1024).round
|
7
|
+
status.set connector.name, 'disk_usage', "#{du} Kb"
|
8
|
+
end
|
9
|
+
super(l)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Sonar
|
2
|
+
module Connector
|
3
|
+
|
4
|
+
ACTION_OK = 'ok'
|
5
|
+
ACTION_FAILED = 'failed'
|
6
|
+
|
7
|
+
class UpdateStatusCommand < Sonar::Connector::Command
|
8
|
+
def initialize(connector, field, value)
|
9
|
+
l = lambda do
|
10
|
+
status.set connector.name, field, value
|
11
|
+
end
|
12
|
+
super(l)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module Sonar
|
2
|
+
module Connector
|
3
|
+
class InvalidConfig < RuntimeError; end
|
4
|
+
|
5
|
+
class Config
|
6
|
+
|
7
|
+
# base params
|
8
|
+
attr_reader :base_dir
|
9
|
+
attr_reader :log_dir
|
10
|
+
attr_reader :connectors_dir
|
11
|
+
attr_reader :controller_log_file
|
12
|
+
attr_reader :status_file
|
13
|
+
attr_reader :connectors
|
14
|
+
attr_reader :email_settings
|
15
|
+
|
16
|
+
# configurable: logger params
|
17
|
+
attr_reader :log_level
|
18
|
+
attr_reader :log_file_max_size
|
19
|
+
attr_reader :log_files_to_keep
|
20
|
+
|
21
|
+
# Entry-point for creating and setting the CONFIG instance.
|
22
|
+
# Give it a path to the JSON settings file and it'll do the rest.
|
23
|
+
def self.load(config_file)
|
24
|
+
config = Config.new(config_file).parse
|
25
|
+
Sonar::Connector.const_set("CONFIG", config)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Helper method to read and parse JSON file from disk. Abstracted for testing purposes.
|
29
|
+
def self.read_json_file(config_file)
|
30
|
+
JSON.parse IO.read(config_file)
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(config_file)
|
34
|
+
@config_file = config_file
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse
|
38
|
+
@raw_config = Config.read_json_file(config_file)
|
39
|
+
|
40
|
+
# extract the core config params
|
41
|
+
@base_dir = parse_base_dir @raw_config["base_dir"]
|
42
|
+
@log_dir = File.join @base_dir, 'log'
|
43
|
+
@connectors_dir = File.join @base_dir, 'var'
|
44
|
+
@controller_log_file = File.join @log_dir, 'controller.log'
|
45
|
+
@status_file = File.join @base_dir, 'status.yml'
|
46
|
+
@log_level = parse_log_level @raw_config["log_level"]
|
47
|
+
@log_file_max_size = parse_log_file_max_size @raw_config["log_file_max_size"]
|
48
|
+
@log_files_to_keep = parse_log_files_to_keep @raw_config["log_files_to_keep"]
|
49
|
+
@email_settings = parse_email_settings @raw_config["email_settings"]
|
50
|
+
|
51
|
+
# extract each connector, locate its class and attempt to parse its config
|
52
|
+
@connectors = parse_connectors @raw_config["connectors"]
|
53
|
+
|
54
|
+
associate_connector_dependencies! @connectors
|
55
|
+
|
56
|
+
self
|
57
|
+
rescue JSON::ParserError => e
|
58
|
+
raise InvalidConfig.new("Config file #{config_file} is not in a valid JSON format. Please check the contents carefully. This is the exact error: \n#{e.message}")
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
attr_reader :config_file
|
64
|
+
attr_reader :raw_config
|
65
|
+
|
66
|
+
def parse_base_dir(base_dir)
|
67
|
+
d = base_dir.blank? ? File.dirname(File.dirname(@config_file)) : base_dir
|
68
|
+
raise InvalidConfig.new("#{d} not a valid directory") unless File.directory?(d)
|
69
|
+
d
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_log_level(log_level)
|
73
|
+
raise InvalidConfig.new("Config option 'log_level' is a required parameter.") if log_level.blank?
|
74
|
+
valid_log_levels = ["debug", "info", "warn", "error", "fatal"]
|
75
|
+
raise InvalidConfig.new("unknown log_level #{log_level}") unless valid_log_levels.include?(log_level)
|
76
|
+
Logger.const_get log_level.upcase
|
77
|
+
end
|
78
|
+
|
79
|
+
def parse_log_file_max_size(log_file_max_size)
|
80
|
+
raise InvalidConfig.new("invalid log_file_max_size #{log_file_max_size}") if !log_file_max_size.blank? && log_file_max_size.to_i == 0
|
81
|
+
log_file_max_size.blank? ? 10*1024*1024 : log_file_max_size.to_i*1024*1024
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_log_files_to_keep(log_files_to_keep)
|
85
|
+
raise InvalidConfig.new("invalid log_files_to_keep #{log_files_to_keep}") if !log_files_to_keep.blank? && log_files_to_keep.to_i == 0
|
86
|
+
log_files_to_keep.blank? ? 10 : log_files_to_keep.to_i
|
87
|
+
end
|
88
|
+
|
89
|
+
def parse_email_settings(settings)
|
90
|
+
ActionMailer::Base.perform_deliveries = settings["perform_deliveries"]
|
91
|
+
ActionMailer::Base.delivery_method = settings["delivery_method"].to_sym
|
92
|
+
ActionMailer::Base.raise_delivery_errors = true
|
93
|
+
|
94
|
+
# ActionMailer needs the smtp and sendmail settings hashes to have symbols for keys
|
95
|
+
ActionMailer::Base.smtp_settings = symbolise_hash_keys settings["smtp_settings"]
|
96
|
+
ActionMailer::Base.sendmail_settings = symbolise_hash_keys settings["sendmail_settings"]
|
97
|
+
|
98
|
+
ActionMailer::Base.save_emails_to_disk = settings["save_emails_to_disk"]
|
99
|
+
ActionMailer::Base.email_output_dir = File.join @base_dir, 'sent_administrator_emails'
|
100
|
+
ActionMailer::Base.safe_recipients = settings["admin_recipients"].to_a
|
101
|
+
settings
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse_connectors(connectors_config)
|
105
|
+
raise InvalidConfig.new("Connector parameter must be an array and cannot be empty") unless connectors_config.instance_of?(Array) && !connectors_config.empty?
|
106
|
+
|
107
|
+
c = []
|
108
|
+
connectors_config.each do |config|
|
109
|
+
c << parse_connector(config)
|
110
|
+
end
|
111
|
+
|
112
|
+
raise InvalidConfig.new("Connector names must be unique. You supplied: #{c.map(&:name).inspect}") if c.map(&:name).uniq.size != c.size
|
113
|
+
c
|
114
|
+
end
|
115
|
+
|
116
|
+
def parse_connector(config)
|
117
|
+
|
118
|
+
# Load the require first, if specified
|
119
|
+
begin
|
120
|
+
require config["require"] unless config["require"].blank?
|
121
|
+
rescue MissingSourceFile
|
122
|
+
raise InvalidConfig.new("Error with parameter 'require' in connector settings '#{config.inspect}': require failed - check that the path is correct.")
|
123
|
+
end
|
124
|
+
|
125
|
+
# Insist that class is specified
|
126
|
+
raise InvalidConfig.new("Error with parameter 'class' in connector settings '#{config.inspect}': class must be specified.") if config["class"].blank?
|
127
|
+
|
128
|
+
# Attempt to load the class definition
|
129
|
+
begin
|
130
|
+
klass = config["class"].constantize
|
131
|
+
rescue
|
132
|
+
raise InvalidConfig.new("Error with parameter 'class' in connector settings '#{config.inspect}': could not load class.")
|
133
|
+
end
|
134
|
+
|
135
|
+
# sanity-check that the connector class subclasses the base
|
136
|
+
raise InvalidConfig.new("Connector class #{klass.name} must subclass Sonar::Connector::Base") unless klass.ancestors.include?(Sonar::Connector::Base)
|
137
|
+
klass.new(config, self)
|
138
|
+
end
|
139
|
+
|
140
|
+
def symbolise_hash_keys(hash)
|
141
|
+
return nil unless hash
|
142
|
+
hash.keys.inject({}){|acc, k| acc[k.to_sym] = hash[k]; acc}
|
143
|
+
end
|
144
|
+
|
145
|
+
# Find all connectors with "source_connectors" specified in config, and map these
|
146
|
+
# associations to the connector instances.
|
147
|
+
def associate_connector_dependencies!(connectors)
|
148
|
+
connectors.each do |connector|
|
149
|
+
source_names = [*connector.raw_config["source_connectors"]].compact
|
150
|
+
next if source_names.blank?
|
151
|
+
|
152
|
+
source_connectors = source_names.map do |source_name|
|
153
|
+
c = connectors.select{|connector2| connector2.name == source_name}.first
|
154
|
+
raise InvalidConfig.new("Connector '#{connector.name}' references a source connector '#{source_name}' but no such connector name is defined.") unless c
|
155
|
+
raise InvalidConfig.new("Connector '#{connector.name}' cannot have itself as a source connector.") if c == connector
|
156
|
+
c
|
157
|
+
end
|
158
|
+
|
159
|
+
connector.send :source_connectors=, source_connectors
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|