antfarm-core 0.5.0.beta1

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.
@@ -0,0 +1,166 @@
1
+ ################################################################################
2
+ # #
3
+ # Copyright (2008-2010) Sandia Corporation. Under the terms of Contract #
4
+ # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains #
5
+ # certain rights in this software. #
6
+ # #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy #
8
+ # of this software and associated documentation files (the "Software"), to #
9
+ # deal in the Software without restriction, including without limitation the #
10
+ # rights to use, copy, modify, merge, publish, distribute, distribute with #
11
+ # modifications, sublicense, and/or sell copies of the Software, and to permit #
12
+ # persons to whom the Software is furnished to do so, subject to the following #
13
+ # conditions: #
14
+ # #
15
+ # The above copyright notice and this permission notice shall be included in #
16
+ # all copies or substantial portions of the Software. #
17
+ # #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
21
+ # ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR #
23
+ # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
24
+ # SOFTWARE. #
25
+ # #
26
+ # Except as contained in this notice, the name(s) of the above copyright #
27
+ # holders shall not be used in advertising or otherwise to promote the sale, #
28
+ # use or other dealings in this Software without prior written authorization. #
29
+ # #
30
+ ################################################################################
31
+
32
+ require 'antfarm/plugin'
33
+
34
+ module Antfarm
35
+ class Framework
36
+ attr_reader :plugin
37
+
38
+ def version
39
+ return Antfarm.version
40
+ end
41
+
42
+ # If this method is called first, ALL plugins will be
43
+ # loaded and cached for the duration of process.
44
+ def plugins
45
+ return @plugins ||= Antfarm::Plugin.load
46
+ end
47
+
48
+ def clean_db
49
+ message = "Deleting #{ANTFARM_ENV} log file..."
50
+ Antfarm::Helpers.output message
51
+ Antfarm::Helpers.log :info, message
52
+
53
+ FileUtils.rm "#{Antfarm::Helpers.log_file(ANTFARM_ENV)}" if File.exists?(Antfarm::Helpers.log_file(ANTFARM_ENV))
54
+
55
+ message = "Deleted #{ANTFARM_ENV} log file successfully."
56
+ Antfarm::Helpers.output message
57
+ Antfarm::Helpers.log :info, message
58
+
59
+ config = YAML::load(IO.read(Antfarm::Helpers.defaults_file))
60
+
61
+ # TODO <scrapcoder>: can this stuff be done using the postgres gem instead?
62
+ if config && config[ANTFARM_ENV] && config[ANTFARM_ENV]['adapter'] == 'postgres'
63
+ message = "Dropping PostgreSQL #{ANTFARM_ENV} database..."
64
+ Antfarm::Helpers.output message
65
+ Antfarm::Helpers.log :info, message
66
+
67
+ exec "dropdb #{ANTFARM_ENV}"
68
+
69
+ message = "Dropped PostgreSQL #{ANTFARM_ENV} database successfully."
70
+ Antfarm::Helpers.output message
71
+ Antfarm::Helpers.log :info, message
72
+ else
73
+ message = "Dropping SQLite3 #{ANTFARM_ENV} database..."
74
+ Antfarm::Helpers.output message
75
+ Antfarm::Helpers.log :info, message
76
+
77
+ FileUtils.rm "#{Antfarm::Helpers.db_file(ANTFARM_ENV)}" if File.exists?(Antfarm::Helpers.db_file(ANTFARM_ENV))
78
+
79
+ message = "Dropped SQLite3 #{ANTFARM_ENV} database successfully."
80
+ Antfarm::Helpers.output message
81
+ Antfarm::Helpers.log :info, message
82
+ end
83
+ end
84
+
85
+ # Creates a new database and schema file. The location of the newly created
86
+ # database file is set in the initializer class via the user
87
+ # configuration hash, and is based on the current ANTFARM environment.
88
+ def migrate_db
89
+ begin
90
+ message = 'Migrating database...'
91
+ Antfarm::Helpers.output message
92
+ Antfarm::Helpers.log :info, message
93
+
94
+ DataMapper.auto_upgrade!
95
+
96
+ message = 'Database successfully migrated.'
97
+ Antfarm::Helpers.output message
98
+ Antfarm::Helpers.log :info, message
99
+ rescue => e # TODO: better error catching - not EVERY error is PostreSQL...
100
+ message = "No PostgreSQL database exists for the #{ANTFARM_ENV} environment. Creating PostgreSQL database..."
101
+ Antfarm::Helpers.output message
102
+ Antfarm::Helpers.log :info, message
103
+
104
+ exec "createdb #{ANTFARM_ENV}"
105
+
106
+ message = 'PostgreSQL database for this environment created. Continuing on with migration.'
107
+ Antfarm::Helpers.output message
108
+ Antfarm::Helpers.log :info, message
109
+
110
+ DataMapper.auto_upgrade!
111
+
112
+ message = 'Database successfully migrated.'
113
+ Antfarm::Helpers.output message
114
+ Antfarm::Helpers.log :info, message
115
+ end
116
+ end
117
+
118
+ # Forces a destructive migration
119
+ def reset_db
120
+ clean_db
121
+ migrate_db
122
+ end
123
+
124
+ def use(plugin)
125
+ @plugin = load_plugin(plugin)
126
+ end
127
+
128
+ def back
129
+ @plugin_name = nil
130
+ @plugin = nil
131
+ end
132
+
133
+ def run(options = Hash.new)
134
+ raise Antfarm::AntfarmError, 'No plugin loaded' unless @plugin
135
+
136
+ if @plugin.options.nil?
137
+ @plugin.run
138
+ else
139
+ @plugin.run(options)
140
+ end
141
+ end
142
+
143
+ def method_missing(method, *args)
144
+ raise Antfarm::AntfarmError, "Command '#{method}' not recognized"
145
+ end
146
+
147
+ #######
148
+ private
149
+ #######
150
+
151
+ def load_plugin(plugin)
152
+ raise Antfarm::AntfarmError, 'Must supply name of one plugin to use' if plugin.nil? or plugin.empty?
153
+
154
+ @plugins ||= Hash.new
155
+ return @plugins[plugin] if @plugins.has_key?(plugin)
156
+
157
+ # Load and save the plugin. An exception will be
158
+ # thrown if the plugin cannot be found or loaded.
159
+ @plugins[plugin] = Antfarm::Plugin.load(plugin)
160
+
161
+ # will not get here if plugin doesn't exist.
162
+ # Exception will have been thrown by now.
163
+ return @plugins[plugin]
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,146 @@
1
+ ################################################################################
2
+ # #
3
+ # Copyright (2008-2010) Sandia Corporation. Under the terms of Contract #
4
+ # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains #
5
+ # certain rights in this software. #
6
+ # #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy #
8
+ # of this software and associated documentation files (the "Software"), to #
9
+ # deal in the Software without restriction, including without limitation the #
10
+ # rights to use, copy, modify, merge, publish, distribute, distribute with #
11
+ # modifications, sublicense, and/or sell copies of the Software, and to permit #
12
+ # persons to whom the Software is furnished to do so, subject to the following #
13
+ # conditions: #
14
+ # #
15
+ # The above copyright notice and this permission notice shall be included in #
16
+ # all copies or substantial portions of the Software. #
17
+ # #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
21
+ # ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR #
23
+ # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
24
+ # SOFTWARE. #
25
+ # #
26
+ # Except as contained in this notice, the name(s) of the above copyright #
27
+ # holders shall not be used in advertising or otherwise to promote the sale, #
28
+ # use or other dealings in this Software without prior written authorization. #
29
+ # #
30
+ ################################################################################
31
+
32
+ require 'fileutils'
33
+
34
+ module Antfarm
35
+ module Helpers
36
+ # Symbolic marker points on the fuzzy logic certainty factor scale.
37
+ # Certainty Factors (CF)
38
+ CF_PROVEN_TRUE = 1.0000
39
+ CF_LIKELY_TRUE = 0.5000
40
+ CF_LACK_OF_PROOF = 0.0000
41
+ CF_LIKELY_FALSE = -0.5000
42
+ CF_PROVEN_FALSE = -1.0000
43
+
44
+ # Amount by which a value can differ and still be considered the same.
45
+ # Mainly used as a buffer against floating point round-off errors.
46
+ CF_VARIANCE = 0.0001
47
+
48
+ @user_dir = nil
49
+ @logger_callback = nil
50
+ class << self
51
+ attr_accessor :logger_callback
52
+ attr_accessor :outputter
53
+ attr_accessor :user_dir
54
+ end
55
+
56
+ def self.clamp(x, low = CF_PROVEN_FALSE, high = CF_PROVEN_TRUE)
57
+ if x < low
58
+ return low
59
+ elsif x > high
60
+ return high
61
+ else
62
+ return x
63
+ end
64
+ end
65
+
66
+ def self.simplify_interfaces
67
+ #TODO
68
+ end
69
+
70
+ def self.timestamp
71
+ return Time.now.utc.xmlschema
72
+ end
73
+
74
+ def self.output(message)
75
+ @outputter.puts(message) unless @outputter.nil?
76
+ end
77
+
78
+ def self.log(level, *msg)
79
+ @logger_callback.call(level, msg.join) if @logger_callback
80
+ end
81
+
82
+ def self.db_dir
83
+ return File.expand_path("#{self.user_dir}/db")
84
+ end
85
+
86
+ def self.db_file(environment)
87
+ return File.expand_path("#{self.user_dir}/db/#{environment}.db")
88
+ end
89
+
90
+ def self.log_dir
91
+ return File.expand_path("#{self.user_dir}/log")
92
+ end
93
+
94
+ def self.log_file(environment)
95
+ return File.expand_path("#{self.user_dir}/log/#{environment}.log")
96
+ end
97
+
98
+ def self.defaults_file
99
+ return File.expand_path("#{self.user_dir}/config/defaults.yml")
100
+ end
101
+
102
+ def self.history_file
103
+ return File.expand_path("#{self.user_dir}/history")
104
+ end
105
+
106
+ def self.user_plugins_dir
107
+ return File.expand_path("#{self.user_dir}/plugins")
108
+ end
109
+
110
+ #######
111
+ private
112
+ #######
113
+
114
+ USER_DIRECTORIES = ['config', 'db', 'log', 'plugins']
115
+
116
+ def self.user_dir
117
+ return @user_dir unless @user_dir.nil?
118
+ return self.create_user_directory
119
+ end
120
+
121
+ # Initializes a suitable directory structure for the user
122
+ def self.create_user_directory
123
+ USER_DIRECTORIES.each do |directory|
124
+ path = "#{ENV['HOME']}/.antfarm/#{directory}"
125
+ # Just to be safe... don't want to wipe out existing user data!
126
+ unless File.exists?(path)
127
+ FileUtils.makedirs(path)
128
+ Antfarm::Helpers.log :info, "User '#{directory}' directory created in #{ENV['HOME'] + '/.antfarm'}"
129
+ end
130
+ end
131
+
132
+ defaults_file = "#{ENV['HOME']}/.antfarm/config/defaults.yml"
133
+ # Just to be safe... don't want to wipe out existing user data!
134
+ unless File.exists?(defaults_file)
135
+ File.open(defaults_file, 'w') do |file|
136
+ file.puts '---'
137
+ file.puts 'environment: antfarm'
138
+ file.puts 'log_level: warn'
139
+ end
140
+ Antfarm::Helpers.log :info, "Default config file created at #{ENV['HOME'] + '/.antfarm/config/defaults.yml'}"
141
+ end
142
+
143
+ return @user_dir = (ENV['HOME'] + '/.antfarm').dup
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,160 @@
1
+ ################################################################################
2
+ # #
3
+ # Copyright (2008-2010) Sandia Corporation. Under the terms of Contract #
4
+ # DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains #
5
+ # certain rights in this software. #
6
+ # #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy #
8
+ # of this software and associated documentation files (the "Software"), to #
9
+ # deal in the Software without restriction, including without limitation the #
10
+ # rights to use, copy, modify, merge, publish, distribute, distribute with #
11
+ # modifications, sublicense, and/or sell copies of the Software, and to permit #
12
+ # persons to whom the Software is furnished to do so, subject to the following #
13
+ # conditions: #
14
+ # #
15
+ # The above copyright notice and this permission notice shall be included in #
16
+ # all copies or substantial portions of the Software. #
17
+ # #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
21
+ # ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR #
23
+ # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
24
+ # SOFTWARE. #
25
+ # #
26
+ # Except as contained in this notice, the name(s) of the above copyright #
27
+ # holders shall not be used in advertising or otherwise to promote the sale, #
28
+ # use or other dealings in this Software without prior written authorization. #
29
+ # #
30
+ ################################################################################
31
+
32
+ require 'yaml'
33
+
34
+ require 'rubygems'
35
+ require 'dm-core'
36
+
37
+ module Antfarm
38
+ class Initializer
39
+ attr_reader :configuration
40
+
41
+ # Run the initializer, first making the configuration object available
42
+ # to the user, then creating a new initializer object, then running the
43
+ # given command.
44
+ def self.run(command = :process, configuration = Configuration.new)
45
+ yield configuration if block_given?
46
+ initializer = new configuration
47
+ initializer.send(command)
48
+ end
49
+
50
+ def initialize(configuration)
51
+ @configuration = configuration
52
+ end
53
+
54
+ def process
55
+ initialize_database
56
+ initialize_logger
57
+ load_requirements
58
+ end
59
+
60
+ def setup
61
+ # Set application load paths
62
+ load_paths = configuration.load_paths
63
+ load_paths.reverse_each { |path| $LOAD_PATH.unshift(path) if File.directory?(path) }
64
+ $LOAD_PATH.uniq!
65
+
66
+ # Load the Antfarm::Helpers module
67
+ load_helpers
68
+
69
+ # Load the general Antfarm error classes
70
+ load_errors
71
+
72
+ # Make sure an application directory exists for the current user
73
+ Antfarm::Helpers.create_user_directory
74
+ end
75
+
76
+ #######
77
+ private
78
+ #######
79
+
80
+ def load_helpers
81
+ require 'antfarm/helpers'
82
+ end
83
+
84
+ def load_errors
85
+ require 'antfarm/errors'
86
+ end
87
+
88
+ # Currently, SQLite3 and PostgreSQL databases are the only ones supported.
89
+ # The name of the ANTFARM environment (which defaults to 'antfarm') is the
90
+ # name used for the database file and the log file.
91
+ def initialize_database
92
+ config = YAML::load(IO.read(Antfarm::Helpers.defaults_file))
93
+ # Database setup based on adapter specified
94
+ if config && config[ANTFARM_ENV] && config[ANTFARM_ENV].has_key?('adapter')
95
+ if config[ANTFARM_ENV]['adapter'] == 'sqlite3'
96
+ config[ANTFARM_ENV]['database'] = Antfarm::Helpers.db_file(ANTFARM_ENV)
97
+ elsif config[ANTFARM_ENV]['adapter'] == 'postgres'
98
+ config[ANTFARM_ENV]['database'] = ANTFARM_ENV
99
+ else
100
+ # If adapter specified isn't one of sqlite3 or postgresql,
101
+ # default to SQLite3 database configuration.
102
+ config = nil
103
+ end
104
+ else
105
+ # If the current environment configuration doesn't specify a
106
+ # database adapter, default to SQLite3 database configuration.
107
+ config = nil
108
+ end
109
+ # Default to SQLite3 database configuration
110
+ config ||= { ANTFARM_ENV => { 'adapter' => 'sqlite3', 'database' => Antfarm::Helpers.db_file(ANTFARM_ENV) } }
111
+ if config[ANTFARM_ENV]['adapter'] == 'postgres'
112
+ DataMapper.setup(:default, "postgres:///#{config[ANTFARM_ENV]['database']}")
113
+ else
114
+ DataMapper.setup(:default, "sqlite3://#{config[ANTFARM_ENV]['database']}")
115
+ end
116
+ end
117
+
118
+ def initialize_logger
119
+ @logger = DataMapper::Logger.new(Antfarm::Helpers.log_file(ANTFARM_ENV), configuration.log_level)
120
+ Antfarm::Helpers.logger_callback = lambda do |severity,msg|
121
+ @logger.send(severity,msg)
122
+ end
123
+ end
124
+
125
+ def load_requirements
126
+ # This will most likely already have been required by RubyGems, but let's
127
+ # keep it in here anyway just in case...
128
+ #
129
+ # Note that 'antfarm-core' calls for boot strapping the ANTFARM
130
+ # environment. However, that shouldn't lead to a circular dependency
131
+ # here since this 'load_requirements' method is called by the initializer
132
+ # 'process' method, not the boot strap's 'setup' method.
133
+ require 'antfarm-core'
134
+ end
135
+ end
136
+
137
+ class Configuration
138
+ attr_accessor :load_paths
139
+ attr_accessor :log_level
140
+
141
+ def initialize
142
+ self.load_paths = default_load_paths
143
+ self.log_level = default_log_level
144
+ end
145
+
146
+ #######
147
+ private
148
+ #######
149
+
150
+ def default_load_paths
151
+ paths = Array.new
152
+ paths << File.expand_path(ANTFARM_ROOT + "/lib")
153
+ return paths
154
+ end
155
+
156
+ def default_log_level
157
+ return :warn
158
+ end
159
+ end
160
+ end