itrigga-config 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.6.4"
12
+ gem "rcov", ">= 0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ jeweler (1.6.4)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rake (0.8.7)
11
+ rcov (0.9.9)
12
+ rspec (2.5.0)
13
+ rspec-core (~> 2.5.0)
14
+ rspec-expectations (~> 2.5.0)
15
+ rspec-mocks (~> 2.5.0)
16
+ rspec-core (2.5.1)
17
+ rspec-expectations (2.5.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.5.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ bundler (~> 1.0.0)
26
+ jeweler (~> 1.6.4)
27
+ rcov
28
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Al Davidson
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,19 @@
1
+ = itrigga-config.git
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to itrigga-config.git
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Al Davidson. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ require 'rake'
6
+
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
10
+ gem.name = "itrigga-config"
11
+ gem.homepage = "http://github.com/drsnooks/itrigga-config"
12
+ gem.license = "MIT"
13
+ gem.summary = %Q{iTrigga's config object & initialization}
14
+ gem.description = %Q{Allows you to define default abitrary config and override per-key by loading in a YAML file }
15
+ gem.email = "aldavidson@itrigga.com"
16
+ gem.authors = ["Al Davidson"]
17
+ # dependencies defined in Gemfile
18
+ end
19
+ Jeweler::RubygemsDotOrgTasks.new
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ require 'rcov/rcovtask'
29
+ Rcov::RcovTask.new do |test|
30
+ test.libs << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ test.rcov_opts << '--exclude "gems/*"'
34
+ end
35
+
36
+ task :default => :test
37
+
38
+ require 'rake/rdoctask'
39
+ Rake::RDocTask.new do |rdoc|
40
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
+
42
+ rdoc.rdoc_dir = 'rdoc'
43
+ rdoc.title = "itrigga-config.git #{version}"
44
+ rdoc.rdoc_files.include('README*')
45
+ rdoc.rdoc_files.include('lib/**/*.rb')
46
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.3
@@ -0,0 +1,225 @@
1
+ require 'itrigga/config/macros'
2
+ require 'singleton'
3
+
4
+ module Itrigga
5
+ module Config
6
+ class Configuration
7
+ include ::Singleton
8
+
9
+ include Itrigga::Config::Macros
10
+
11
+ def_param( 'constants', {
12
+ :RAILS_ENV => ( defined?(RAILS_ENV) ? RAILS_ENV : ENV['RAILS_ENV'] || 'development'),
13
+ :TRIGGA_SHARED_DIR => '/var/www/itrigga/shared'
14
+ })
15
+
16
+ def_param('search_tracker', {
17
+ :host => 'http://localhost:3001',
18
+ :access_token => 'GGH4672LqctJmNp5LFGG'
19
+ } )
20
+
21
+ def_param('sessions', {
22
+ :expire_in_hours => 24
23
+ })
24
+
25
+ # what server should we scp worker generated sitemaps to
26
+ def_param('sitemap', {
27
+ :targets => [:localhost]
28
+ })
29
+
30
+ # urls split by application to hit to warm caches
31
+ def_param('cache_urls', {
32
+ :trigga_dot_com => ["http://itrigga.com/refresh_stats"]
33
+ })
34
+
35
+ def_param( 'timers',
36
+ :tick_interval_seconds => 60,
37
+ :specs => [
38
+ {:name=>'Update all sources', :cron_string=>"2 * * * *", :job_yaml=>"--- !ruby/object:UpdateSourceJobSchedulerJob {}\n\n"},
39
+ {:name=>'Expire items', :cron_string=>"1 0 * * *", :job_yaml=>"--- !ruby/object:ExpireItemsJob \ndatetime: \n"},
40
+ {:name=>'Hello World heartbeat', :cron_string=>"* * * * *", :job_yaml=>"--- !ruby/object:HelloWorldJob \noptions: {}\n\n"},
41
+ {:name=>'Update item site scores', :cron_string=>"*/10 * * * *", :job_yaml=>"--- !ruby/object:UpdateItemSiteScoresJob \noptions: {}\n\n"},
42
+ {:name=>'Issue send_item_subscription_email jobs', :cron_string=>"15 13 * * 5", :job_yaml=>"--- !ruby/object:IssueSendItemSubscriptionEmailJobsJob \noptions: {}\n\n"},
43
+ {:name=>'Update Site Popular & Recent Searches', :cron_string=>"*/10 * * * *", :job_yaml=>"--- !ruby/object:UpdateCachedSiteSearchesJobSchedulerJob \noptions: {}\n\n"},
44
+ {:name=>'Update Cached Site Tags', :cron_string=>"*/20 * * * *", :job_yaml=>"--- !ruby/object:UpdateCachedSiteTagsJobSchedulerJob \noptions: {}\n\n"},
45
+ {:name=>'Update Cached Channel Tags', :cron_string=>"*/20 * * * *", :job_yaml=>"--- !ruby/object:UpdateCachedChannelTagsJobSchedulerJob \noptions: {}\n\n"},
46
+ {:name=>'Delete Expired items', :cron_string=>"30 0 * * *", :job_yaml=>"--- !ruby/object:DeleteExpiredItemsJob \ndatetime: \n"},
47
+ {:name=>'Delete old benchmark events', :cron_string=>"45 0 * * *", :job_yaml=>"--- !ruby/object:DeleteOldBenchmarkEventsJob \ndatetime: \n"},
48
+ {:name=>'Increment Cache Version', :cron_string=>"*/5 * * * *", :job_yaml=>"--- !ruby/object:IncrementCacheVersionJob {}\n\n"},
49
+ {:name=>'Activate Items', :cron_string=>"0 4 * * * *", :job_yaml=>"--- !ruby/object:ActivateItemsJob {}\n\n"},
50
+ {:name=>'Expire old unallocated items', :cron_string=>"1 0 * * *", :job_yaml=>"--- !ruby/object:ExpireOldUnallocatedItemsJob \ndatetime: \n"},
51
+ {:name=>'Clear old sessions', :cron_string=>"0 3 * * *", :job_yaml=>"--- !ruby/object:ClearSessionsJob {} \n\n"},
52
+ {:name=>'Update Seatwave Cached Performances', :cron_string=>"0 2 * * *", :job_yaml=>"--- !ruby/object:UpdateSeatwaveCachedPerformancesJob {} \n\n"},
53
+ {:name=>'Optimize all Tables', :cron_string=>"30 3 * * *", :job_yaml=>"--- !ruby/object:OptimizeTableJobSchedulerJob {}\n\n"},
54
+ {:name=>'Generate All Sitemaps', :cron_string=>"0 */4 * * *", :job_yaml=>"--- !ruby/object:GenerateAllSitemapsJob {}\n\n"},
55
+ {:name=>'Warm the itrigga.com stats caches', :cron_string=>"0 2,14 * * *", :job_yaml=>"--- !ruby/object:WarmTriggaDotComCachesJob {}\n\n"},
56
+ {:name=>'Schedule item email deliveries', :cron_string=>"0 */1 * * * *", :job_yaml=>"--- !ruby/object:SendChannelItemsEmailJobSchedulerJob {}\n\n"},
57
+ {:name=>'Optimize solr index', :cron_string=>"0 2 * * * *", :job_yaml=>"--- !ruby/object:OptimizeSolrIndexJob {}\n\n"}
58
+
59
+ ]
60
+ )
61
+
62
+ def_param( 'memcache',
63
+ :enabled => true,
64
+ :options => {
65
+ :c_threshold => 10_000,
66
+ :compression => true,
67
+ :debug => false,
68
+ :namespace => "trigga_default",
69
+ :readonly => false,
70
+ :urlencode => false
71
+ },
72
+ :servers => 'localhost:11211',
73
+ :lifetime_seconds => 60
74
+ )
75
+
76
+ def_param( 'sites', [] )
77
+
78
+ def_param( 'facebook',
79
+ :perms => "email,publish_stream,offline_access,read_stream"
80
+ )
81
+
82
+ def_param( 'processes',
83
+ :web => {
84
+ :port => 3000,
85
+ :servers => 3,
86
+ :request_timeout => 30
87
+ },
88
+ :solr => {
89
+ :paths => {
90
+ :root=> "vendor/plugins/acts_as_solr/solr/",
91
+ :instances_root => "../solr/instances",
92
+ :data=> "../solr/data"
93
+ },
94
+ :url => "http://127.0.0.1:8983/solr",
95
+ :jvm_options=> "" # for production: -server -d64 -Xmx1024M -Xms64M
96
+ },
97
+ :broker => {
98
+ :options => {
99
+ :host => '127.0.0.1',
100
+ :port => 5672,
101
+ :vhost => 'itrigga.com',
102
+ :user => 'trigga',
103
+ :pass => 'n0sp00n3r15m5plz',
104
+ :timeout => 5,
105
+ :logging => false, # <- extremely verbose protocol logging,
106
+ :prefetch => 1 # <- maximum of this many msgs to be sent to the client at any one time (stop rabbit flooding the worker, also stop messages disappearing when client dies)
107
+ },
108
+ :connection_check_seconds => 5,
109
+ :queues => [
110
+ {:name=>'priority_high',
111
+ :binding => { :exchange_name=>'jobs_exchange', :key => 'trigga.jobs.priority.high.*' },
112
+ :options=>{:durable=>true, :ack=>true} # <- ack=true says to acknowledge each msg (otherwise they can get lost)
113
+ },
114
+ {:name=>'priority_med',
115
+ :binding => { :exchange_name=>'jobs_exchange', :key => 'trigga.jobs.priority.med.*' },
116
+ :options=>{:durable=>true, :ack=>true} # <- ack=true says to acknowledge each msg (otherwise they can get lost)
117
+ },
118
+ {:name=>'priority_low',
119
+ :binding => { :exchange_name=>'jobs_exchange', :key => 'trigga.jobs.priority.low.*' },
120
+ :options=>{:durable=>true, :ack=>true} # <- ack=true says to acknowledge each msg (otherwise they can get lost)
121
+ }
122
+ ],
123
+ :exchanges => [
124
+ { :name=>'jobs_exchange',
125
+ :key_root=>'trigga',
126
+ :options=>{:type=>:topic, :passive=>false, :durable=>true, :auto_delete => false },
127
+ :default_msg_options=>{:mandatory => true, :immediate=>false, :persistent => true}
128
+ }
129
+ ],
130
+ :default_exchange_name => 'jobs_exchange',
131
+ :unique_process_search_string => 'rabbitmq-server'
132
+ },
133
+ :job_resubmitter=> {
134
+ :tick_interval_seconds => 10,
135
+ :max_batch_size => 100
136
+ },
137
+ :timer => {
138
+ :tick_interval_seconds => 10,
139
+ :reactivate_stale_seconds => 14400,
140
+ :reactivate_old_queued_seconds => 14400
141
+ },
142
+ # worker's queue_names determines which queues (defined in the broker config above)
143
+ # each worker process will subscribe to.
144
+ # the default 'worker' will subscribe to them all,
145
+ # but you can have separate hi/med/low priority workers to prevent
146
+ # workers getting swamped by one type of slow-running job (e.g. UpdateItemLinksJob)
147
+ :worker => {
148
+ :queue_names=>['priority_high', 'priority_med', 'priority_low']
149
+ },
150
+ :"worker-hi" => {
151
+ :queue_names=>['priority_high']
152
+ },
153
+ :"worker-med" => {
154
+ :queue_names=>['priority_med']
155
+ },
156
+ :"worker-low" => {
157
+ :queue_names=>['priority_low']
158
+ },
159
+ :term_extractor => {
160
+ :port => 4567,
161
+ :url => "http://localhost:4567/terms"
162
+ },
163
+ :memcached => {
164
+ :port => 11212,
165
+ :max_mem_mb => 64,
166
+ :user => 'root'
167
+ }
168
+ )
169
+
170
+ def_param( 'processes_to_start',
171
+ [:broker, :solr, :memcached, :web, :"worker", :timer, :scheduled_job_resubmitter, :term_extractor] # <- start these processes, in this order
172
+ )
173
+ def_param( 'ssh_hosts_to_monitor',
174
+ [:localhost]
175
+ )
176
+ def_param( 'monit_templates_to_render',
177
+ []
178
+ )
179
+ def_param( 'cron_templates_to_render',
180
+ []
181
+ )
182
+ def_param( 'monitoring_templates_to_render',
183
+ []
184
+ )
185
+
186
+ def_param('mysql',
187
+ :replication_user => { :username => "ws_status", :password => "ws_status123" }
188
+ )
189
+
190
+ def_param( 'hosts',
191
+ [
192
+ { :host => "localhost", :display_name => "localhost", :port => 22, :user => ENV["USER"], :ssh_key_path => nil, :mysql_user => "tn", :mysql_pwd => "n0sp00n3r15m5plz", :types => [:db_slave_stats, :process_stats, :broker_stats] }
193
+ ]
194
+ )
195
+
196
+ # Aliases
197
+ # TODO: refactor refs to these
198
+ def rabbit_mq; processes[:broker]; end
199
+ def web_service_term_extractor; processes[:term_extractor]; end
200
+ def scheduled_job_submitter; processes[:job_resubmitter]; end
201
+
202
+ def environment
203
+ RAILS_ENV
204
+ end
205
+
206
+ def environment_type
207
+ case environment
208
+ when /test/: 'test'
209
+ when /development/: 'development'
210
+ else 'production'
211
+ end
212
+ end
213
+
214
+ def is_test?; environment_type == 'test'; end
215
+ def is_production?; environment_type == 'production'; end
216
+ def is_development?; environment_type == 'development'; end
217
+
218
+ def exchange_config(name)
219
+ @rabbit_mq[:exchanges].find{ |e| e[:name] == name }
220
+ end
221
+
222
+ end
223
+ end
224
+ end
225
+
@@ -0,0 +1,30 @@
1
+ require 'itrigga/config/configuration'
2
+
3
+ raise ArgumentError.new("you must define ITRIGGA_APP_NAME if you're going to use itrigga/config/environment") unless defined?(ITRIGGA_APP_NAME)
4
+ puts "initialising itrigga-config for '#{ITRIGGA_APP_NAME}' app"
5
+
6
+ app_name_upper = ITRIGGA_APP_NAME.upcase
7
+ app_name_lower = ITRIGGA_APP_NAME.downcase
8
+ config_file_env_var_name = "#{app_name_upper}_CONFIG_FILE"
9
+
10
+ param = ARGV.find{|a| a.match(/--#{app_name_lower}-config-file=(.*)/)}
11
+ given_file = param ? param.gsub(/--#{app_name_lower}-config-file=(.*)/, '\1') : nil
12
+
13
+ ITRIGGA_CONFIG = Itrigga::Config::Configuration.instance()
14
+ [ given_file, ENV["#{app_name_upper}_CONFIG_FILE"], "/etc/#{app_name_lower}_config_file" ].compact.each { |f|
15
+ if File.exists?(f)
16
+ true_path = (File.symlink?(f) ? File.readlink(f) : f)
17
+ puts "loading #{app_name_lower} config file #{true_path}"
18
+ ITRIGGA_CONFIG.from_file(true_path)
19
+ break
20
+ end
21
+ }
22
+
23
+ # silence warnings, before we load the convenient Rails silence_warnings method:
24
+ old_verbose = $VERBOSE
25
+ $VERBOSE = false
26
+ begin
27
+ ITRIGGA_CONFIG.constants.each { |k,v| eval("#{k}='#{v}'") }
28
+ ensure
29
+ $VERBOSE = old_verbose
30
+ end
@@ -0,0 +1,189 @@
1
+ require 'yaml'
2
+
3
+ module Itrigga
4
+ module Config
5
+ module Macros
6
+ def self.included(klass)
7
+ klass.send(:include, InstanceMethods)
8
+
9
+ # provides a convenient array of all param names without the "@", handy for dumping / debugging
10
+ define_method( :params ) do
11
+ klass.instance_variables.map{ |v| v.gsub(/@(.+)/, '\1') } - ['inheritable_attributes']
12
+ end
13
+
14
+ define_method(:param) do |arg|
15
+ if klass.instance_variables.include? "@#{arg}"
16
+ klass.instance_variable_get("@#{arg}")
17
+ else
18
+ raise ArgumentError.new("no param found called '#{arg}'")
19
+ end
20
+ end
21
+
22
+
23
+ klass.class_eval {
24
+
25
+ class << self
26
+
27
+ def param_getter( name, default_value=nil, &block )
28
+ instance_variable_set( "@#{name}", default_value )
29
+ define_method( name.to_s ) do
30
+ if instance_variables.include? "@#{name}"
31
+ instance_variable_get("@#{name}")
32
+ else
33
+ if block
34
+ instance_variable_set("@#{name}", block.call(self) )
35
+ else
36
+ instance_variable_set("@#{name}", default_value)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def param_setter( name )
43
+ define_method(:recursive_update) do |p, h|
44
+ h.each do |k, v|
45
+ prev = p[k.to_sym]
46
+ if prev.is_a?(Hash) && v.is_a?(Hash)
47
+ recursive_update(prev, v)
48
+ else
49
+ p[k.to_sym]=v
50
+ end
51
+ end
52
+ end
53
+
54
+ define_method("#{name}=") do |val|
55
+ if val.is_a?(Hash) && self.send("#{name}".to_sym).is_a?(Hash)
56
+ recursive_update(self.send("#{name}".to_sym), val)
57
+ else
58
+ instance_variable_set("@#{name}", val)
59
+ end
60
+ end
61
+ end
62
+
63
+
64
+ def def_param( name, default_value, &block )
65
+ param_getter( name, default_value, &block )
66
+ param_setter( name )
67
+ end
68
+
69
+
70
+ end
71
+
72
+
73
+ } # klass.class_eval
74
+
75
+ end
76
+ end
77
+
78
+ module InstanceMethods
79
+
80
+ def initialize(file=nil)
81
+ self.from_file(file) unless file.to_s.empty?
82
+ self
83
+ end
84
+
85
+ def to_hash
86
+ h = {}
87
+ params.each do |p|
88
+ h[p] = param(p)
89
+ end
90
+ h
91
+ end
92
+
93
+ def from_hash( h )
94
+ h.keys.each do |k|
95
+ self.class.def_param(k,h[k]) unless params.include?(k)
96
+ self.class.instance_variable_set("@#{k}", h[k] )
97
+ self.instance_variable_set("@#{k}", h[k] )
98
+ end
99
+ self
100
+ end
101
+
102
+ def from_file( f )
103
+ raise ArgumentError.new("#{f.to_s} is not a valid file") unless File.file?(f.to_s)
104
+ h = File.open( f ){ |yml| ::YAML::load( yml ) }
105
+ c = from_hash(h)
106
+ self.instance_variable_set("@from_file", f.to_s)
107
+ c
108
+ end
109
+
110
+ def to_file(f)
111
+ File.open( f, "w+" ) do |f|
112
+ f.write( to_hash.to_yaml )
113
+ end
114
+ end
115
+
116
+ def loaded_file
117
+ self.instance_variable_get("@from_file")
118
+ end
119
+
120
+ def loaded_file_basename
121
+ loaded_file ? File.basename(loaded_file) : nil
122
+ end
123
+
124
+ def site_config_root
125
+ "#{RAILS_ROOT}/config/itrigga"
126
+ end
127
+
128
+ def site_keys
129
+ Dir.chdir(site_config_root) do
130
+ Dir['*/'].map{ |d| d.gsub( /(.*)[\/\\]/, '\1' ) }
131
+ end
132
+ end
133
+
134
+ def site_config_files(site_dir)
135
+ Dir.chdir(File.join(site_config_root, site_dir)) do
136
+ Dir['*.yml']
137
+ end
138
+ end
139
+
140
+ def load_site_config_file( site_name, filename )
141
+ path = File.join(site_config_root, site_name, filename)
142
+ File.open( path ){ |yml| ::YAML::load( yml ) }
143
+ end
144
+
145
+ def load_site_config( site_name )
146
+ h = {}
147
+ site_config_files(site_name).each do |f|
148
+ key_name = f.gsub(/(.*)\.yml/, '\1').to_sym
149
+ h[key_name] = load_site_config_file(site_name, f)
150
+ end
151
+ h
152
+ end
153
+
154
+ def load_site_config_for_all_sites
155
+ default_config = load_site_config('default_site')
156
+
157
+ h = {}
158
+ site_keys.each do |site|
159
+ h[site] = default_config.merge(load_site_config(site))
160
+ end
161
+
162
+ self.sites = h
163
+ self
164
+ end
165
+
166
+ def site_config( site_key )
167
+ self.sites[site_key]
168
+ end
169
+
170
+ def site_config_with_defaults( site_key )
171
+ config = site_config('default_site').clone
172
+ this_site_config = site_config(site_key)
173
+ config.merge!(this_site_config) if this_site_config
174
+ config
175
+ end
176
+
177
+ def apply_action_mailer_config( site_key )
178
+ Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
179
+
180
+ mailer_settings = site_config_with_defaults(site_key)[:actionmailer]
181
+ ActionMailer::Base.smtp_settings = mailer_settings[:smtp_settings]
182
+ end
183
+
184
+ end
185
+
186
+
187
+
188
+ end
189
+ end
@@ -0,0 +1 @@
1
+ require 'itrigga/config/configuration'
@@ -0,0 +1,374 @@
1
+ require 'spec_helper'
2
+
3
+ describe Itrigga::Config::Configuration do
4
+
5
+ describe "defining a param" do
6
+ it "should set the given param as an instance variable" do
7
+ Itrigga::Config::Configuration.def_param( "blart", "flange")
8
+ Itrigga::Config::Configuration.instance_variables.should include("@blart")
9
+ end
10
+
11
+ it "should let you read back a param once set" do
12
+ Itrigga::Config::Configuration.def_param( "blart", "flange")
13
+ Itrigga::Config::Configuration.instance().blart.should == "flange"
14
+ end
15
+ end
16
+
17
+ describe "params" do
18
+ it "should return an array of all param names without the '@'" do
19
+ Itrigga::Config::Configuration.def_param( "blart", "flange" )
20
+ Itrigga::Config::Configuration.def_param( "monkeys", {:infinite=>true} )
21
+ Itrigga::Config::Configuration.instance().params.should include("blart")
22
+ Itrigga::Config::Configuration.instance().params.should include("monkeys")
23
+ end
24
+
25
+ it "should not include 'inheritable_attributes'" do
26
+ Itrigga::Config::Configuration.def_param( "blart", "flange" )
27
+ Itrigga::Config::Configuration.instance().params.should_not include("inheritable_attributes")
28
+ end
29
+
30
+
31
+ end
32
+
33
+ describe "param" do
34
+ it "should return the value of the given param" do
35
+ Itrigga::Config::Configuration.def_param( "blart", "flange" )
36
+ Itrigga::Config::Configuration.instance().param("blart").should == "flange"
37
+ end
38
+
39
+ describe "when asked for a param that doesn't exist" do
40
+ it "should raise an ArgumentError" do
41
+ lambda{
42
+ Itrigga::Config::Configuration.instance().param("asfasfasf")
43
+ }.should raise_error(ArgumentError)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "environment" do
49
+ before(:each) do
50
+ RAILS_ENV = "blart" unless defined?(RAILS_ENV)
51
+ end
52
+
53
+ it "should be RAILS_ENV" do
54
+ Itrigga::Config::Configuration.instance().environment.should == RAILS_ENV
55
+ end
56
+ end
57
+
58
+ describe "environment_type" do
59
+ before(:each) do
60
+ @tc = Itrigga::Config::Configuration.instance()
61
+ end
62
+
63
+ describe "when environment name contains 'test'" do
64
+ it "should return 'test'" do
65
+ @tc.stub!(:environment).and_return('test')
66
+ @tc.environment_type.should == 'test'
67
+
68
+ @tc.stub!(:environment).and_return('monkey_test')
69
+ @tc.environment_type.should == 'test'
70
+ end
71
+ end
72
+ describe "when environment name contains 'development'" do
73
+ it "should return 'test'" do
74
+ @tc.stub!(:environment).and_return('development')
75
+ @tc.environment_type.should == 'development'
76
+
77
+ @tc.stub!(:environment).and_return('donkey_development')
78
+ @tc.environment_type.should == 'development'
79
+ end
80
+ end
81
+ describe "when environment name doesn't contain 'test' OR 'development'" do
82
+ it "should return 'production'" do
83
+ @tc.stub!(:environment).and_return('production')
84
+ @tc.environment_type.should == 'production'
85
+
86
+ @tc.stub!(:environment).and_return('cheese_widgets')
87
+ @tc.environment_type.should == 'production'
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "to_hash" do
93
+ before(:each) do
94
+ Itrigga::Config::Configuration.def_param( :a_2_level_hash, {:key=>'a key', :sub_hash=>{:sub_key_1=>"sub_value 1", :sub_key_2=>"sub_value 2"}} )
95
+ Itrigga::Config::Configuration.def_param( :array_of_arrays, [['0 0', '0 1'], ['1 0', '1 1']] )
96
+ Itrigga::Config::Configuration.def_param( :array_of_hashes, [ {:key=>'val'}, {:key=>'val 2'} ] )
97
+ @tc = Itrigga::Config::Configuration.instance()
98
+ end
99
+
100
+ it "should generate a correct hash to arbitrary depth" do
101
+ h = @tc.to_hash
102
+ h.keys.sort.should == @tc.params.sort
103
+ h.keys.each do |key|
104
+ h[key].should == @tc.param(key)
105
+ end
106
+
107
+ end
108
+ end
109
+
110
+ describe "hash import/export" do
111
+ before(:each) do
112
+ @hash = {
113
+ :a_2_level_hash => {:key=>'a new key', :sub_hash=>{:sub_key_1=>"sub_value 1 new", :sub_key_2=>"sub_value 2 new"}},
114
+ :array_of_arrays => [['0 0 2', '0 1 2'], ['1 0 2', '1 1 2']] ,
115
+ :array_of_hashes => [ {:key=>'val 2'}, {:key=>'val 2 2'} ]
116
+ }
117
+ Itrigga::Config::Configuration.def_param( :a_2_level_hash, {:key=>'a key', :sub_hash=>{:sub_key_1=>"sub_value 1", :sub_key_2=>"sub_value 2"}} )
118
+ Itrigga::Config::Configuration.def_param( :array_of_arrays, [['0 0', '0 1'], ['1 0', '1 1']] )
119
+ Itrigga::Config::Configuration.def_param( :array_of_hashes, [ {:key=>'val'}, {:key=>'val 2'} ] )
120
+ end
121
+
122
+ describe "from_hash" do
123
+ context "all params" do
124
+ before(:each) do
125
+ @tc = Itrigga::Config::Configuration.instance().from_hash(@hash)
126
+ end
127
+
128
+ it "should define a param for each key in the hash" do
129
+ @tc.params.should include( "a_2_level_hash" )
130
+ @tc.params.should include( "array_of_arrays" )
131
+ @tc.params.should include( "array_of_hashes" )
132
+ end
133
+
134
+ it "should set the param value to the hash key value" do
135
+ @tc.param('a_2_level_hash').should == @hash[:a_2_level_hash]
136
+ @tc.param('array_of_arrays').should == @hash[:array_of_arrays]
137
+ @tc.param('array_of_hashes').should == @hash[:array_of_hashes]
138
+
139
+ @tc.a_2_level_hash.should == @hash[:a_2_level_hash]
140
+ end
141
+ end
142
+
143
+ context "when the param doesnt already exist" do
144
+ before(:each) do
145
+ @hash[:new_param] = {:key1=>'some value'}
146
+ @tc = Itrigga::Config::Configuration.instance().from_hash(@hash)
147
+ end
148
+
149
+ it "should define the param with the given value as default" do
150
+ @tc.new_param.should == {:key1=>'some value'}
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "from_file" do
156
+ before(:each) do
157
+ @f = mock("file")
158
+ File.stub!(:file?).with("/my/file/path").and_return true
159
+ File.stub!(:open).with("/my/file/path").and_yield(@f)
160
+ YAML.stub!(:load).and_return( @hash )
161
+ end
162
+
163
+ it "should load the given file as YAML" do
164
+ YAML.should_receive(:load).with(@f).and_return( @hash )
165
+ @tc = Itrigga::Config::Configuration.instance().from_file( "/my/file/path" )
166
+ end
167
+
168
+ it "should initialise from the parsed hash" do
169
+ @tc = Itrigga::Config::Configuration.instance()
170
+ @tc.should_receive( :from_hash ).with(@hash)
171
+ @tc.from_file( "/my/file/path" )
172
+ end
173
+ end
174
+
175
+ describe "to_file" do
176
+ before(:each) do
177
+ @tc = Itrigga::Config::Configuration.instance()
178
+ @yaml = "some yaml"
179
+ @f = mock("file")
180
+ File.stub!(:open).and_yield( @f )
181
+ end
182
+
183
+ it "should serialise the config object to YAML" do
184
+ @f.stub!(:write)
185
+ @tc.should_receive(:to_hash).and_return(@hash)
186
+ @hash.should_receive(:to_yaml).and_return( @yaml )
187
+ @tc.to_file( "/some/file/path" )
188
+ end
189
+
190
+ it "should write the yaml to the given file" do
191
+ @tc.stub!(:to_hash).and_return(@hash)
192
+ @hash.stub!(:to_yaml).and_return( @yaml )
193
+ @f.should_receive(:write).with( "some yaml" )
194
+ @tc.to_file( "/some/file/path" )
195
+ end
196
+
197
+ end
198
+ end
199
+
200
+ describe "site_keys" do
201
+ before(:each) do
202
+ @tc = Itrigga::Config::Configuration.instance()
203
+ RAILS_ROOT='/some/dir'
204
+ end
205
+
206
+ it "should have one element for each subdir of site_config_root" do
207
+ @tc.should_receive(:site_config_root).and_return("blart")
208
+ Dir.should_receive(:chdir).with("blart")
209
+ @tc.site_keys
210
+ end
211
+
212
+ it "should strip any trailing slashes from each element" do
213
+ Dir.stub!(:chdir).and_yield
214
+ Dir.stub!(:[]).and_return( ['dir1/', 'dir2\\'] )
215
+ @tc.site_keys.should == ['dir1', 'dir2']
216
+ end
217
+
218
+ end
219
+
220
+ describe "site_config_files" do
221
+ before(:each) do
222
+ @tc = Itrigga::Config::Configuration.instance()
223
+ end
224
+
225
+ it "should return an array of all yml files under the given dir" do
226
+ @tc.should_receive(:site_config_root).and_return("blart")
227
+ Dir.should_receive(:chdir).with('blart/site_dir').and_yield
228
+ Dir.should_receive(:[]).with("*.yml").and_return(["file1.yml", "file2.yml"] )
229
+ @tc.site_config_files("site_dir").should == ["file1.yml", "file2.yml"]
230
+ end
231
+ end
232
+
233
+ describe "load_site_config_file" do
234
+ before(:each) do
235
+ @tc = Itrigga::Config::Configuration.instance()
236
+ @file_contents = "file contents"
237
+ @data = {:my_key => {:subkey1 => "value1"}}
238
+ File.stub!(:open).and_yield(@file_contents)
239
+ end
240
+
241
+ it "should load the given file from the given site sub dir" do
242
+ @tc.should_receive(:site_config_root).and_return("site_config_dir")
243
+ File.should_receive(:open).with("site_config_dir/site_name/filename.yml").and_yield( @file_contents )
244
+ @tc.load_site_config_file("site_name", "filename.yml")
245
+ end
246
+
247
+
248
+ it "should return the resulting data decoded from yaml" do
249
+ YAML.should_receive(:load).with(@file_contents).and_return( @data )
250
+ @tc.load_site_config_file("site_name", "filename.yml").should == @data
251
+ end
252
+ end
253
+
254
+ describe "load_site_config" do
255
+ before(:each) do
256
+ @tc = Itrigga::Config::Configuration.instance()
257
+ @tc.stub!(:site_config_files).and_return( ['file1.yml', 'file2.yml'] )
258
+ @tc.stub!(:load_site_config_file).and_return( {} )
259
+ end
260
+
261
+ it "should get all config files for the given site" do
262
+ @tc.should_receive(:site_config_files).with("my_site").and_return( [] )
263
+ @tc.load_site_config("my_site")
264
+ end
265
+
266
+ describe "for each config file for the given site" do
267
+ it "should make a key from the filename.to_sym" do
268
+ keys = @tc.load_site_config("my_site").keys
269
+ keys.sort{|a,b| a.to_s <=> b.to_s }.should == [:file1, :file2]
270
+ end
271
+
272
+ it "should load the config file" do
273
+ @tc.should_receive(:load_site_config_file).with("my_site", "file1.yml").and_return( {} )
274
+ @tc.should_receive(:load_site_config_file).with("my_site", "file2.yml").and_return( {} )
275
+ @tc.load_site_config("my_site")
276
+ end
277
+
278
+ it "should set the key to the loaded data" do
279
+ @tc.stub!(:load_site_config_file).and_return( {:key1=>:value1} , {:key2=>:value2} )
280
+ @tc.load_site_config("my_site").should == {
281
+ :file1 => {:key1=>:value1},
282
+ :file2 => {:key2=>:value2}
283
+ }
284
+ end
285
+
286
+ end
287
+
288
+ end
289
+
290
+ describe "apply_action_mailer_config" do
291
+ before(:each) do
292
+ @tc = Itrigga::Config::Configuration.instance()
293
+ unless defined?(Net::SMTP)
294
+ module Net
295
+ module SMTP
296
+ module_function
297
+
298
+ def enable_tls(opt)
299
+ end
300
+ end
301
+ end
302
+ end
303
+
304
+ unless defined?(ActionMailer::Base)
305
+ module ActionMailer
306
+ class Base
307
+ def self.smtp_settings=(opt)
308
+ end
309
+ end
310
+ end
311
+ end
312
+ end
313
+
314
+ it "should get the site-specific-but-defaulted ActionMailer settings" do
315
+ @tc.should_receive(:site_config_with_defaults).with('blart').and_return( :actionmailer => { :smtp_settings => {:setting1=>'setting1'} } )
316
+ @tc.apply_action_mailer_config('blart')
317
+ end
318
+
319
+ it "should apply those settings to ActionMailer::Base" do
320
+ @tc.stub!(:site_config_with_defaults).with('blart').and_return( :actionmailer => { :smtp_settings => {:setting1=>'setting1'} } )
321
+ ActionMailer::Base.should_receive(:smtp_settings=).with({:setting1=>'setting1'})
322
+ @tc.apply_action_mailer_config('blart')
323
+ end
324
+ end
325
+
326
+ describe "site_config_with_defaults" do
327
+ before(:each) do
328
+ @tc = Itrigga::Config::Configuration.instance()
329
+ @tc.stub!(:site_config).with("blart")
330
+ @tc.stub!(:site_config).with("default_site").and_return(@config = {:blart=>'flange'} )
331
+ @config.stub!(:clone).and_return(@config2 = {:blart=>'flange'})
332
+ end
333
+
334
+ it "should get the default site's config" do
335
+ @tc.should_receive(:site_config).with("default_site").at_least(:once).and_return(:blart=>'flange')
336
+ @tc.site_config_with_defaults("blart")
337
+ end
338
+
339
+ it "should clone the default site's config" do
340
+ @tc.stub!(:site_config).with("default_site").and_return(@config = {:blart=>'flange'} )
341
+ @config.should_receive(:clone).and_return(@config2 = {:blart=>'flange'})
342
+ @tc.site_config_with_defaults("blart")
343
+ end
344
+
345
+ it "should get the requested site's config" do
346
+ @tc.should_receive(:site_config).with("blart").and_return(:blart=>'flange')
347
+ @tc.site_config_with_defaults("blart")
348
+ end
349
+
350
+ context "when the requested site's config is empty" do
351
+ before(:each) do
352
+ @tc.stub!(:site_config).with("blart").and_return(nil)
353
+ end
354
+
355
+ it "should return the cloned default site config" do
356
+ @tc.site_config_with_defaults("blart").should == @config2
357
+ end
358
+ end
359
+
360
+ context "when the requested site's config is not empty" do
361
+ before(:each) do
362
+ @tc.stub!(:site_config).with("blart").and_return(@config = {:blart=>'flange'})
363
+ @config2.stub!(:merge!).with( @config ).and_return(@config3 = {:cheese=>'emmental'})
364
+ end
365
+
366
+ it "should merge the requested site config into the defaults config" do
367
+ @config2.should_receive(:merge!).with( @config ).and_return(@config3 = {:cheese=>'emmental'})
368
+ @tc.site_config_with_defaults("blart")
369
+ end
370
+
371
+ end
372
+ end
373
+
374
+ end
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'rspec'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+
16
+ require 'itrigga/config'
17
+
18
+ RSpec.configure do |config|
19
+ # some (optional) config here
20
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'itrigga-config.git'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestItriggaConfig.git < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: itrigga-config
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 3
9
+ version: 0.0.3
10
+ platform: ruby
11
+ authors:
12
+ - Al Davidson
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-08-12 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ type: :development
22
+ name: rspec
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ requirement: *id001
31
+ prerelease: false
32
+ - !ruby/object:Gem::Dependency
33
+ type: :development
34
+ name: bundler
35
+ version_requirements: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 1
41
+ - 0
42
+ - 0
43
+ version: 1.0.0
44
+ requirement: *id002
45
+ prerelease: false
46
+ - !ruby/object:Gem::Dependency
47
+ type: :development
48
+ name: jeweler
49
+ version_requirements: &id003 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 1
55
+ - 6
56
+ - 4
57
+ version: 1.6.4
58
+ requirement: *id003
59
+ prerelease: false
60
+ - !ruby/object:Gem::Dependency
61
+ type: :development
62
+ name: rcov
63
+ version_requirements: &id004 !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ requirement: *id004
71
+ prerelease: false
72
+ description: "Allows you to define default abitrary config and override per-key by loading in a YAML file "
73
+ email: aldavidson@itrigga.com
74
+ executables: []
75
+
76
+ extensions: []
77
+
78
+ extra_rdoc_files:
79
+ - LICENSE.txt
80
+ - README.rdoc
81
+ files:
82
+ - .document
83
+ - Gemfile
84
+ - Gemfile.lock
85
+ - LICENSE.txt
86
+ - README.rdoc
87
+ - Rakefile
88
+ - VERSION
89
+ - lib/itrigga/config.rb
90
+ - lib/itrigga/config/configuration.rb
91
+ - lib/itrigga/config/environment.rb
92
+ - lib/itrigga/config/macros.rb
93
+ - spec/config_spec.rb
94
+ - spec/spec_helper.rb
95
+ - test/helper.rb
96
+ - test/test_itrigga-config.git.rb
97
+ has_rdoc: true
98
+ homepage: http://github.com/drsnooks/itrigga-config
99
+ licenses:
100
+ - MIT
101
+ post_install_message:
102
+ rdoc_options: []
103
+
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ segments:
118
+ - 0
119
+ version: "0"
120
+ requirements: []
121
+
122
+ rubyforge_project:
123
+ rubygems_version: 1.3.6
124
+ signing_key:
125
+ specification_version: 3
126
+ summary: iTrigga's config object & initialization
127
+ test_files: []
128
+