rubysync 0.0.5 → 0.1.0
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/HISTORY.txt +7 -0
- data/Manifest.txt +18 -76
- data/Rakefile +2 -2
- data/bin/rubysync +60 -21
- data/bin/rubysync.rb +60 -21
- data/examples/ar_webapp/public/dispatch.cgi +1 -1
- data/examples/ar_webapp/public/dispatch.fcgi +1 -1
- data/examples/ar_webapp/public/dispatch.rb +1 -1
- data/examples/csv_to_ldap/config/connectors/hr_connector.rb +14 -0
- data/examples/csv_to_ldap/config/connectors/ldap_vault_connector.rb +11 -0
- data/examples/{ar_webapp/.DS_Store → csv_to_ldap/config/db/HrImportPipeline(vault)_assoc_to_path.db} +0 -0
- data/{.DS_Store → examples/csv_to_ldap/config/db/HrImportPipeline(vault)_mirror.db} +0 -0
- data/examples/csv_to_ldap/config/db/HrImportPipeline(vault)_path_to_assoc.db +0 -0
- data/examples/csv_to_ldap/config/pipelines/hr_import_pipeline.rb +24 -0
- data/examples/csv_to_ldap/in/henchmen.csv.bak +3 -0
- data/examples/csv_to_xml/config/connectors/databank_connector.rb +8 -0
- data/examples/csv_to_xml/config/connectors/hr_connector.rb +14 -0
- data/examples/csv_to_xml/config/db/HrImportPipeline(vault)_assoc_to_path.db +0 -0
- data/examples/csv_to_xml/config/db/HrImportPipeline(vault)_mirror.db +0 -0
- data/examples/csv_to_xml/config/db/HrImportPipeline(vault)_path_to_assoc.db +0 -0
- data/examples/csv_to_xml/config/pipelines/hr_import_pipeline.rb +24 -0
- data/examples/csv_to_xml/databank.xml +1 -0
- data/examples/csv_to_xml/in/henchmen.csv.bak +3 -0
- data/examples/csv_to_xml/transcript.txt +1 -2
- data/examples/data/henchmen.csv +3 -0
- data/examples/data/more.csv +2 -0
- data/lib/ruby_sync/connectors/active_record_connector.rb +19 -4
- data/lib/ruby_sync/connectors/base_connector.rb +3 -9
- data/lib/ruby_sync/connectors/file_connector.rb +2 -2
- data/lib/ruby_sync/event.rb +16 -9
- data/lib/ruby_sync/pipelines/base_pipeline.rb +137 -164
- data/lib/ruby_sync/util/utilities.rb +14 -21
- data/lib/ruby_sync.rb +37 -39
- data/test/ruby_sync_test.rb +3 -2
- data/test/tc_active_record_connector.rb +15 -6
- data/test/tc_csv_file_connector.rb +10 -6
- data/test/tc_ldap_connector.rb +1 -1
- data/test/tc_memory_connectors.rb +5 -3
- data/test/tc_transformation.rb +15 -7
- data/test/tc_utilities.rb +1 -1
- data/test/tc_xml_connectors.rb +4 -0
- data/test/ts_rubysync.rb +3 -1
- metadata +21 -81
- data/.project +0 -17
- data/docs/in_pipeline.graffle +0 -2690
- data/docs/out_pipeline.graffle +0 -3274
- data/docs/to_sync.txt +0 -15
- data/docs/walkthru.txt +0 -186
- data/examples/ar_client_webapp/README +0 -182
- data/examples/ar_client_webapp/Rakefile +0 -10
- data/examples/ar_client_webapp/app/controllers/application.rb +0 -7
- data/examples/ar_client_webapp/app/controllers/user_controller.rb +0 -5
- data/examples/ar_client_webapp/app/helpers/application_helper.rb +0 -3
- data/examples/ar_client_webapp/app/helpers/user_helper.rb +0 -2
- data/examples/ar_client_webapp/app/models/user.rb +0 -2
- data/examples/ar_client_webapp/config/boot.rb +0 -45
- data/examples/ar_client_webapp/config/database.yml +0 -36
- data/examples/ar_client_webapp/config/environment.rb +0 -60
- data/examples/ar_client_webapp/config/environments/development.rb +0 -21
- data/examples/ar_client_webapp/config/environments/production.rb +0 -18
- data/examples/ar_client_webapp/config/environments/test.rb +0 -19
- data/examples/ar_client_webapp/config/routes.rb +0 -23
- data/examples/ar_client_webapp/db/migrate/001_create_users.rb +0 -13
- data/examples/ar_client_webapp/db/schema.rb +0 -13
- data/examples/ar_client_webapp/doc/README_FOR_APP +0 -2
- data/examples/ar_client_webapp/log/development.log +0 -753
- data/examples/ar_client_webapp/log/production.log +0 -0
- data/examples/ar_client_webapp/log/server.log +0 -0
- data/examples/ar_client_webapp/log/test.log +0 -0
- data/examples/ar_client_webapp/public/.htaccess +0 -40
- data/examples/ar_client_webapp/public/404.html +0 -30
- data/examples/ar_client_webapp/public/500.html +0 -30
- data/examples/ar_client_webapp/public/dispatch.cgi +0 -10
- data/examples/ar_client_webapp/public/dispatch.fcgi +0 -24
- data/examples/ar_client_webapp/public/dispatch.rb +0 -10
- data/examples/ar_client_webapp/public/favicon.ico +0 -0
- data/examples/ar_client_webapp/public/images/rails.png +0 -0
- data/examples/ar_client_webapp/public/index.html +0 -277
- data/examples/ar_client_webapp/public/javascripts/application.js +0 -2
- data/examples/ar_client_webapp/public/javascripts/controls.js +0 -833
- data/examples/ar_client_webapp/public/javascripts/dragdrop.js +0 -942
- data/examples/ar_client_webapp/public/javascripts/effects.js +0 -1088
- data/examples/ar_client_webapp/public/javascripts/prototype.js +0 -2515
- data/examples/ar_client_webapp/public/robots.txt +0 -1
- data/examples/ar_client_webapp/script/about +0 -3
- data/examples/ar_client_webapp/script/breakpointer +0 -3
- data/examples/ar_client_webapp/script/console +0 -3
- data/examples/ar_client_webapp/script/destroy +0 -3
- data/examples/ar_client_webapp/script/generate +0 -3
- data/examples/ar_client_webapp/script/performance/benchmarker +0 -3
- data/examples/ar_client_webapp/script/performance/profiler +0 -3
- data/examples/ar_client_webapp/script/plugin +0 -3
- data/examples/ar_client_webapp/script/process/inspector +0 -3
- data/examples/ar_client_webapp/script/process/reaper +0 -3
- data/examples/ar_client_webapp/script/process/spawner +0 -3
- data/examples/ar_client_webapp/script/runner +0 -3
- data/examples/ar_client_webapp/script/server +0 -3
- data/examples/ar_client_webapp/test/fixtures/users.yml +0 -5
- data/examples/ar_client_webapp/test/functional/user_controller_test.rb +0 -18
- data/examples/ar_client_webapp/test/test_helper.rb +0 -28
- data/examples/ar_client_webapp/test/unit/user_test.rb +0 -10
- data/examples/ar_client_webapp/tmp/sessions/ruby_sess.e2e3c63a67baef6d +0 -0
- data/examples/ar_webapp/app/.DS_Store +0 -0
- data/examples/ar_webapp/app/views/.DS_Store +0 -0
- data/examples/ar_webapp/app/views/people/.DS_Store +0 -0
- data/examples/ims2/connectors/hr_db_connector.rb +0 -6
- data/examples/ims2/connectors/my_csv_connector.rb +0 -12
- data/examples/ims2/pipelines/hr_import_pipeline.rb +0 -33
- data/examples/my_ims/connectors/my_csv_connector.rb +0 -10
- data/examples/my_ims/connectors/my_db_connector.rb +0 -7
- data/examples/my_ims/pipelines/my_pipeline.rb +0 -33
- data/lib/rubysync.rb +0 -19
- data/nbproject/private/private.properties +0 -3
- data/nbproject/project.properties +0 -8
- data/nbproject/project.xml +0 -16
- data/rubysync.tmproj +0 -568
- data/test/tc_rubysync.rb +0 -28
|
@@ -51,7 +51,6 @@ module RubySync::Connectors
|
|
|
51
51
|
db_config_filename = File.join(rails_app_path, 'config', 'database.yml')
|
|
52
52
|
db_config = YAML::load(ERB.new(IO.read(db_config_filename)).result)[rails_env]
|
|
53
53
|
# Require the models
|
|
54
|
-
log.debug "Loading the models for #{self.class.name}:"
|
|
55
54
|
Dir.chdir(File.join(rails_app_path,'app','models')) do
|
|
56
55
|
Dir.glob('*.rb') do |filename|
|
|
57
56
|
log.debug("\t#{filename}")
|
|
@@ -76,9 +75,25 @@ module RubySync::Connectors
|
|
|
76
75
|
def self.sample_config
|
|
77
76
|
return <<END
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
# Uncomment and adjust the following if your app is a Ruby on Rails
|
|
79
|
+
# application. It will grab the config from the RoR database.yml.
|
|
80
|
+
# application '/path/to/a/rails/application'
|
|
81
|
+
# model 'name_of_model_to_sync'
|
|
82
|
+
# rails_env 'development' # typically development or production
|
|
83
|
+
|
|
84
|
+
# OR
|
|
85
|
+
|
|
86
|
+
# Uncomment and adjust the following if your app is not
|
|
87
|
+
# a Ruby on Rails application (EXPERIMENTAL)
|
|
88
|
+
#
|
|
89
|
+
# db_type 'mysql' # eg 'db2', 'mysql', 'oci', 'postgresql', 'sqlite', 'sqlserver'
|
|
90
|
+
# db_host 'localhost' # network name of db server
|
|
91
|
+
# db_name 'database_name' # Name of the database (not the table)
|
|
92
|
+
# model 'my_model'
|
|
93
|
+
# class MyModel < ActiveRecord::Base
|
|
94
|
+
# set_table_name "users"
|
|
95
|
+
# end
|
|
96
|
+
|
|
82
97
|
END
|
|
83
98
|
end
|
|
84
99
|
|
|
@@ -371,18 +371,12 @@ module RubySync::Connectors
|
|
|
371
371
|
# Ensures that the named connector is loaded and returns its class object
|
|
372
372
|
def self.class_for connector_name
|
|
373
373
|
name = class_name_for connector_name
|
|
374
|
-
(name)? eval(
|
|
374
|
+
(name)? eval(name) : nil
|
|
375
375
|
end
|
|
376
376
|
|
|
377
|
-
#
|
|
377
|
+
# Return the class name for a path style connector name
|
|
378
378
|
def self.class_name_for connector_name
|
|
379
|
-
|
|
380
|
-
class_name = filename.camelize
|
|
381
|
-
eval "defined? #{class_name}" or
|
|
382
|
-
$".include?(filename) or
|
|
383
|
-
require filename or
|
|
384
|
-
raise Exception.new("Can't find connector '#{filename}'")
|
|
385
|
-
class_name
|
|
379
|
+
'::' + "#{connector_name}_connector".camelize
|
|
386
380
|
end
|
|
387
381
|
|
|
388
382
|
private
|
data/lib/ruby_sync/event.rb
CHANGED
|
@@ -46,8 +46,9 @@ module RubySync
|
|
|
46
46
|
|
|
47
47
|
include RubySync::Utilities
|
|
48
48
|
|
|
49
|
-
attr_accessor :type, # delete, add, modify ...
|
|
49
|
+
attr_accessor :type, # :delete, :add, :modify ...
|
|
50
50
|
:source,
|
|
51
|
+
:target,
|
|
51
52
|
:payload,
|
|
52
53
|
:source_path,
|
|
53
54
|
:target_path,
|
|
@@ -145,14 +146,14 @@ module RubySync
|
|
|
145
146
|
|
|
146
147
|
# Remove any operations from the payload that affect fields with the given key or
|
|
147
148
|
# keys (key can be a single field name or an array of field names).
|
|
148
|
-
def drop_changes_to
|
|
149
|
-
subjects =
|
|
149
|
+
def drop_changes_to *subjects
|
|
150
|
+
subjects = subjects.flatten.collect {|s| s.to_s}
|
|
150
151
|
uncommitted_operations
|
|
151
152
|
@uncommitted_operations = @uncommitted_operations.delete_if {|op| subjects.include? op.subject }
|
|
152
153
|
end
|
|
153
154
|
|
|
154
|
-
def drop_all_but_changes_to
|
|
155
|
-
subjects =
|
|
155
|
+
def drop_all_but_changes_to *subjects
|
|
156
|
+
subjects = subjects.flatten.collect {|s| s.to_s}
|
|
156
157
|
@uncommitted_operations = uncommitted_operations.delete_if {|op| !subjects.include?(op.subject.to_s)}
|
|
157
158
|
end
|
|
158
159
|
|
|
@@ -170,15 +171,17 @@ module RubySync
|
|
|
170
171
|
uncommitted_operations << Operation.new(:replace, field_name.to_s, as_array(value))
|
|
171
172
|
end
|
|
172
173
|
|
|
173
|
-
def values_for field_name
|
|
174
|
+
def values_for field_name, default=[]
|
|
174
175
|
values = perform_operations @payload, {}, :subjects=>[field_name.to_s]
|
|
175
|
-
values[field_name.to_s]
|
|
176
|
+
values[field_name.to_s] || default
|
|
176
177
|
end
|
|
178
|
+
alias_method :values_of, :values_for
|
|
177
179
|
|
|
178
|
-
def value_for field_name
|
|
180
|
+
def value_for field_name, default=''
|
|
179
181
|
values = values_for field_name
|
|
180
|
-
|
|
182
|
+
values[0] || default
|
|
181
183
|
end
|
|
184
|
+
alias_method :value_of, :value_for
|
|
182
185
|
|
|
183
186
|
def uncommitted_operations
|
|
184
187
|
@uncommitted_operations ||= @payload || []
|
|
@@ -223,6 +226,10 @@ module RubySync
|
|
|
223
226
|
uncommitted_operations << RubySync::Operation.replace(left.to_s, blk.call)
|
|
224
227
|
end
|
|
225
228
|
end
|
|
229
|
+
|
|
230
|
+
def place(&blk)
|
|
231
|
+
self.target_path = blk.call
|
|
232
|
+
end
|
|
226
233
|
|
|
227
234
|
protected
|
|
228
235
|
|
|
@@ -13,11 +13,12 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License along with RubySync; if not, write to the
|
|
14
14
|
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
15
15
|
|
|
16
|
-
lib_path = File.dirname(__FILE__)
|
|
17
|
-
$:.unshift lib_path unless $:.include?(lib_path)
|
|
16
|
+
lib_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
17
|
+
$:.unshift lib_path unless $:.include?(lib_path)
|
|
18
18
|
|
|
19
19
|
require 'active_support'
|
|
20
20
|
require 'ruby_sync/util/metaid'
|
|
21
|
+
require 'ruby_sync/util/utilities'
|
|
21
22
|
require 'yaml'
|
|
22
23
|
|
|
23
24
|
|
|
@@ -42,6 +43,10 @@ module RubySync
|
|
|
42
43
|
|
|
43
44
|
attr_accessor :delay # delay in seconds between checking connectors
|
|
44
45
|
|
|
46
|
+
array_option :dump_before, :dump_after
|
|
47
|
+
dump_before []
|
|
48
|
+
dump_after []
|
|
49
|
+
|
|
45
50
|
def initialize
|
|
46
51
|
@delay = 5
|
|
47
52
|
end
|
|
@@ -55,7 +60,7 @@ module RubySync
|
|
|
55
60
|
options[:name] ||= "#{self.name}(client)"
|
|
56
61
|
options[:is_vault] = false
|
|
57
62
|
class_def 'client' do
|
|
58
|
-
@client ||= eval(
|
|
63
|
+
@client ||= eval(class_name).new(options)
|
|
59
64
|
end
|
|
60
65
|
end
|
|
61
66
|
|
|
@@ -65,163 +70,72 @@ module RubySync
|
|
|
65
70
|
options[:is_vault] = true
|
|
66
71
|
class_def 'vault' do
|
|
67
72
|
unless @vault
|
|
68
|
-
@vault = eval(
|
|
73
|
+
@vault = eval(class_name).new(options)
|
|
69
74
|
@vault.pipeline = self
|
|
70
75
|
end
|
|
71
76
|
@vault
|
|
72
77
|
end
|
|
73
78
|
end
|
|
74
79
|
|
|
75
|
-
def self.map_client_to_vault mappings
|
|
76
|
-
remove_method :client_to_vault_map if method_defined? :client_to_vault_map
|
|
77
|
-
class_def 'client_to_vault_map' do
|
|
78
|
-
unless @client_to_vault_map
|
|
79
|
-
@client_to_vault_map = {}
|
|
80
|
-
mappings.each {|k,v| @client_to_vault_map[k.to_s] = v.to_s}
|
|
81
|
-
end
|
|
82
|
-
@client_to_vault_map
|
|
83
|
-
end
|
|
84
|
-
unless method_defined? :vault_to_client_map
|
|
85
|
-
class_def 'vault_to_client_map' do
|
|
86
|
-
@vault_to_client_map ||= client_to_vault_map.invert
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def self.map_vault_to_client mappings
|
|
92
|
-
remove_method :vault_to_client_map if method_defined? :vault_to_client_map
|
|
93
|
-
class_def 'vault_to_client_map' do
|
|
94
|
-
unless @vault_to_client_map
|
|
95
|
-
@vault_to_client_map = {}
|
|
96
|
-
mappings.each {|k,v| @vault_to_client_map[k.to_s] = v.to_s}
|
|
97
|
-
end
|
|
98
|
-
@vault_to_client_map
|
|
99
|
-
end
|
|
100
|
-
unless method_defined? :client_to_vault_map
|
|
101
|
-
class_def 'client_to_vault_map' do
|
|
102
|
-
@client_to_vault_map ||= vault_to_client_map.invert
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def self.out_transform &blk
|
|
108
|
-
define_method :out_transform do |event|
|
|
109
|
-
event.meta_def :transform, &blk
|
|
110
|
-
event.transform
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def self.in_transform &blk
|
|
115
|
-
define_method :in_transform do |event|
|
|
116
|
-
event.meta_def :transform, &blk
|
|
117
|
-
event.transform
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
# Called by the identity-vault connector in the 'out' thread to process events generated
|
|
123
|
-
# by the identity vault.
|
|
124
|
-
def out_handler(event)
|
|
125
80
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
return unless out_event_filter event
|
|
133
|
-
|
|
134
|
-
# Remove unwanted attributes
|
|
135
|
-
perform_transform :out_filter, event
|
|
81
|
+
def self.in_transform(&blk) event_method :in_transform,&blk; end
|
|
82
|
+
def self.out_transform(&blk) event_method :out_transform,&blk; end
|
|
83
|
+
def self.in_match(&blk) event_method :in_match_if,&blk; end
|
|
84
|
+
def self.out_match(&blk) event_method :out_match_if,&blk; end
|
|
85
|
+
def self.in_create_if(&blk) event_method :in_create_if,&blk; end
|
|
86
|
+
def self.out_create_if(&blk) event_method :out_create_if,&blk; end
|
|
136
87
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
log.info YAML.dump(event)
|
|
141
|
-
return
|
|
142
|
-
end
|
|
88
|
+
def self.event_method name,&blk
|
|
89
|
+
define_method name do |event|
|
|
90
|
+
event.instance_eval &blk
|
|
143
91
|
end
|
|
92
|
+
end
|
|
144
93
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
event.convert_to_add
|
|
148
|
-
end
|
|
149
|
-
end
|
|
94
|
+
def self.in_place(&blk) place :in, &blk; end
|
|
95
|
+
def self.out_place(&blk) place :out, &blk; end
|
|
150
96
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if match # exactly one event record on the client matched
|
|
155
|
-
log.info "Match found, merging"
|
|
156
|
-
event.merge(match)
|
|
157
|
-
association = Association.new(self.association_context, match.src_path)
|
|
158
|
-
vault.associate asssociation, event.source_path
|
|
159
|
-
return
|
|
160
|
-
end
|
|
161
|
-
log.info "No match found, creating"
|
|
162
|
-
return unless out_create(event)
|
|
163
|
-
perform_transform :out_place, event
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
perform_transform :out_map_schema, event
|
|
167
|
-
perform_transform :out_transform, event
|
|
168
|
-
association_key = nil
|
|
169
|
-
with_rescue("#{client.name}: Processing command") do
|
|
170
|
-
association_key = client.process(event)
|
|
171
|
-
end
|
|
172
|
-
if association_key
|
|
173
|
-
association = Association.new(association_context, association_key)
|
|
174
|
-
with_rescue("#{client.name}: Storing association #{association} in vault") do
|
|
175
|
-
vault.associate(association, event.source_path)
|
|
176
|
-
end
|
|
97
|
+
def self.place direction, &blk
|
|
98
|
+
define_method "#{direction}_place" do |event|
|
|
99
|
+
event.target_path = event.instance_eval &blk
|
|
177
100
|
end
|
|
178
101
|
end
|
|
179
102
|
|
|
180
|
-
# Override to map schema from vault namespace to client namespace
|
|
181
|
-
# def out_map_schema event
|
|
182
|
-
# end
|
|
183
103
|
|
|
184
104
|
# Override to implement some kind of matching
|
|
185
|
-
def
|
|
105
|
+
def default_match event
|
|
186
106
|
log.debug "Default matching rule - source path exists on client?"
|
|
187
|
-
|
|
188
|
-
false
|
|
107
|
+
event.target.respond_to?('[]') and event.target[event.source_path]
|
|
189
108
|
end
|
|
109
|
+
alias_method :in_match, :default_match
|
|
110
|
+
alias_method :out_match, :default_match
|
|
190
111
|
|
|
191
112
|
# Override to restrict creation on the client
|
|
192
|
-
def
|
|
113
|
+
def default_create event
|
|
193
114
|
log.debug "Create allowed through default rule"
|
|
194
115
|
true
|
|
195
116
|
end
|
|
117
|
+
alias_method :in_create, :default_create
|
|
118
|
+
alias_method :out_create, :default_create
|
|
196
119
|
|
|
197
|
-
# Override to restrict creation on the vault
|
|
198
|
-
def in_create event
|
|
199
|
-
log.debug "Create allowed through default rule"
|
|
200
|
-
true
|
|
201
|
-
end
|
|
202
120
|
|
|
203
121
|
# Override to modify the target path for creation on the client
|
|
204
|
-
def
|
|
122
|
+
def default_place(event)
|
|
205
123
|
log.debug "Default placement rule target_path = source_path"
|
|
206
124
|
event.target_path = event.source_path
|
|
207
125
|
end
|
|
126
|
+
alias_method :in_place, :default_place
|
|
127
|
+
alias_method :out_place, :default_place
|
|
208
128
|
|
|
209
|
-
# Override to modify the target path for creation in the vault
|
|
210
|
-
def in_place(event)
|
|
211
|
-
log.debug "Default placement rule target_path = source_path"
|
|
212
|
-
event.target_path = event.source_path
|
|
213
|
-
end
|
|
214
129
|
|
|
215
130
|
def perform_transform name, event, hint=""
|
|
131
|
+
log.info "Performing #{name}"
|
|
132
|
+
log.info event.to_yaml if dump_before.include?(name.to_sym)
|
|
216
133
|
call_if_exists name, event, hint
|
|
217
134
|
event.commit_changes
|
|
218
|
-
|
|
135
|
+
log.info event.to_yaml if dump_after.include?(name.to_sym)
|
|
136
|
+
#log_progress name, event, hint
|
|
219
137
|
end
|
|
220
|
-
|
|
221
|
-
# Transform the out-going event before the client receives it
|
|
222
|
-
# def out_transform(event)
|
|
223
|
-
# end
|
|
224
|
-
|
|
138
|
+
|
|
225
139
|
# Execute the pipeline once then return.
|
|
226
140
|
def run_once
|
|
227
141
|
log.info "Running #{name} pipeline once"
|
|
@@ -243,6 +157,7 @@ module RubySync
|
|
|
243
157
|
|
|
244
158
|
# Execute the in pipe once and then return
|
|
245
159
|
def run_in_once
|
|
160
|
+
return unless allowed_in
|
|
246
161
|
log.debug "Running #{name} 'in' pipeline once"
|
|
247
162
|
client.once_only = true
|
|
248
163
|
client.start {|event| in_handler(event)}
|
|
@@ -250,6 +165,7 @@ module RubySync
|
|
|
250
165
|
|
|
251
166
|
# Execute the out pipe once and then return
|
|
252
167
|
def run_out_once
|
|
168
|
+
return unless allowed_out
|
|
253
169
|
log.debug "Running #{name} 'out' pipeline once"
|
|
254
170
|
vault.once_only = true
|
|
255
171
|
vault.start {|event| out_handler(event)}
|
|
@@ -282,51 +198,127 @@ module RubySync
|
|
|
282
198
|
|
|
283
199
|
# Called by the 'in' connector in the 'in' thread to process events generated by the client.
|
|
284
200
|
def in_handler(event)
|
|
285
|
-
event.
|
|
201
|
+
event.target = @vault
|
|
202
|
+
event.retrieve_association(association_context)
|
|
286
203
|
|
|
287
|
-
hint = "
|
|
288
|
-
log.info "Processing incoming #{event.type} event"+hint
|
|
289
|
-
log.info YAML.dump(event)
|
|
290
|
-
perform_transform :in_map_schema, event, hint
|
|
291
|
-
perform_transform :in_transform, event, hint
|
|
204
|
+
hint = "(#{client.name} => #{vault.name}) #{event.source_path}"
|
|
205
|
+
log.info "Processing incoming #{event.type} event "+hint
|
|
292
206
|
perform_transform :in_filter, event, hint
|
|
293
207
|
|
|
294
208
|
# The client can't really know whether its an add or a modify because it doesn't store
|
|
295
209
|
# the association.
|
|
296
210
|
if event.type == :modify
|
|
297
|
-
|
|
211
|
+
unless event.associated? and vault.find_associated(event.association)
|
|
212
|
+
log.info "No associated entry in vault for modify event. Converting to add"
|
|
213
|
+
event.convert_to_add
|
|
214
|
+
end
|
|
298
215
|
elsif event.type == :add and event.associated? and vault.find_associated(event.association)
|
|
216
|
+
log.info "Associated entry in vault for add event. Converting to modify"
|
|
299
217
|
event.convert_to_modify
|
|
300
218
|
end
|
|
219
|
+
|
|
220
|
+
perform_transform :in_transform, event, hint
|
|
221
|
+
|
|
301
222
|
|
|
223
|
+
# todo: Maybe we should merge any add or modify that is associated or matched
|
|
302
224
|
if event.type == :add
|
|
303
|
-
match = in_match(event)
|
|
225
|
+
match = in_match(event)
|
|
304
226
|
if match
|
|
227
|
+
log.info "Matching record found in vault. Merging."
|
|
305
228
|
event.merge(match)
|
|
306
|
-
return
|
|
229
|
+
log.info "---\n"; return
|
|
307
230
|
end
|
|
308
231
|
|
|
309
232
|
if in_create(event)
|
|
310
233
|
perform_transform :in_place, event, hint
|
|
234
|
+
log.info "Create on vault allowed. Placing at #{event.target_path}"
|
|
311
235
|
else
|
|
312
|
-
|
|
236
|
+
log.info "Create rule disallowed creation"
|
|
237
|
+
log.info "---\n"; return
|
|
313
238
|
end
|
|
314
239
|
end
|
|
315
|
-
|
|
240
|
+
|
|
316
241
|
with_rescue("#{vault.name}: Processing command") {vault.process(event)}
|
|
242
|
+
log.info "---\n"
|
|
317
243
|
|
|
318
244
|
end
|
|
319
245
|
|
|
246
|
+
|
|
247
|
+
# Called by the identity-vault connector in the 'out' thread to process events generated
|
|
248
|
+
# by the identity vault.
|
|
249
|
+
def out_handler(event)
|
|
250
|
+
event.target = @client
|
|
251
|
+
event.retrieve_association(association_context)
|
|
252
|
+
event.convert_to_modify if event.associated? and event.type == :add
|
|
253
|
+
|
|
254
|
+
hint = "(path=#{event.source_path} #{vault.name} => #{client.name})"
|
|
255
|
+
log.info "Processing out-going #{event.type} event #{hint}"
|
|
256
|
+
#log.info YAML.dump(event)
|
|
257
|
+
unless out_event_filter event
|
|
258
|
+
log.info "Disallowed by out_event_filter"
|
|
259
|
+
log.info "---\n"; return
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Remove unwanted attributes
|
|
263
|
+
perform_transform :out_filter, event
|
|
264
|
+
|
|
265
|
+
unless event.associated?
|
|
266
|
+
log.info "no association"
|
|
267
|
+
if [:delete, :remove_association].include? event.type
|
|
268
|
+
log.info "#{name}: No action for #{event.type} of unassociated entry"
|
|
269
|
+
log.info "---\n"; return
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
if event.type == :modify
|
|
274
|
+
unless event.associated? and client.has_entry_for_key?(event.association.key)
|
|
275
|
+
log.info "Can't find associated client record so converting modify to add"
|
|
276
|
+
event.convert_to_add
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
if event.type == :add
|
|
281
|
+
match = out_match(event)
|
|
282
|
+
log.info "Attempting to match"
|
|
283
|
+
if match # exactly one event record on the client matched
|
|
284
|
+
log.info "Match found, merging"
|
|
285
|
+
event.merge(match)
|
|
286
|
+
association = Association.new(self.association_context, match.source_path)
|
|
287
|
+
vault.associate asssociation, event.source_path
|
|
288
|
+
log.info "---\n"; return
|
|
289
|
+
end
|
|
290
|
+
log.info "No match found, creating"
|
|
291
|
+
unless out_create(event)
|
|
292
|
+
log.info "Creation denied by create rule"
|
|
293
|
+
log.info "---\n"; return
|
|
294
|
+
end
|
|
295
|
+
perform_transform :out_place, event
|
|
296
|
+
log.info "Placing new entry at #{event.target_path}"
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
perform_transform :out_transform, event
|
|
300
|
+
association_key = nil
|
|
301
|
+
with_rescue("#{client.name}: Processing command") do
|
|
302
|
+
association_key = client.process(event)
|
|
303
|
+
end
|
|
304
|
+
if association_key
|
|
305
|
+
association = Association.new(association_context, association_key)
|
|
306
|
+
with_rescue("#{client.name}: Storing association #{association} in vault") do
|
|
307
|
+
vault.associate(association, event.source_path)
|
|
308
|
+
end
|
|
309
|
+
else
|
|
310
|
+
log.info "Client didn't return an association key"
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
|
|
320
316
|
# The context for all association keys used by this pipeline.
|
|
321
317
|
# By default, defer to the client
|
|
322
318
|
def association_context
|
|
323
319
|
@client.association_context
|
|
324
320
|
end
|
|
325
|
-
|
|
326
|
-
def in_match event
|
|
327
|
-
log.debug "Default match rule - source path exists in vault"
|
|
328
|
-
vault.respond_to?('[]') and vault[event.source_path]
|
|
329
|
-
end
|
|
321
|
+
|
|
330
322
|
|
|
331
323
|
# If client_to_vault_map is defined (usually by map_client_to_vault)
|
|
332
324
|
# then fix up the contents of the payload to refer to the fields by
|
|
@@ -345,15 +337,6 @@ module RubySync
|
|
|
345
337
|
op.subject = map[op.subject] || op.subject if op.subject
|
|
346
338
|
end
|
|
347
339
|
end
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
# Override to perform whatever transformation on the event is required
|
|
353
|
-
#def in_transform(event); event; end
|
|
354
|
-
|
|
355
|
-
# Convert fields in the incoming event to those used by the identity vault
|
|
356
|
-
#def in_map_schema(event); end
|
|
357
340
|
|
|
358
341
|
# Specify which fields will be allowed through the incoming filter
|
|
359
342
|
# If nil (the default), all fields are allowed.
|
|
@@ -366,14 +349,9 @@ module RubySync
|
|
|
366
349
|
# default allowed_in in case allow_in doesn't get called
|
|
367
350
|
def allowed_in; nil; end
|
|
368
351
|
|
|
369
|
-
|
|
370
|
-
#def allowed_in; false; end
|
|
352
|
+
|
|
371
353
|
def in_filter(event)
|
|
372
|
-
|
|
373
|
-
event.drop_all_but_changes_to allowed_in
|
|
374
|
-
else
|
|
375
|
-
event
|
|
376
|
-
end
|
|
354
|
+
allowed_in == [] or event.drop_all_but_changes_to(allowed_in || [])
|
|
377
355
|
end
|
|
378
356
|
|
|
379
357
|
|
|
@@ -388,17 +366,12 @@ module RubySync
|
|
|
388
366
|
# default allowed_out in case allow_out doesn't get called
|
|
389
367
|
def allowed_out; nil; end
|
|
390
368
|
|
|
391
|
-
# Default method for allowed_out. Override by calling allow_in
|
|
392
|
-
#def allowed_out; false; end
|
|
393
369
|
def out_filter(event)
|
|
394
|
-
|
|
395
|
-
event.drop_all_but_changes_to allowed_out
|
|
396
|
-
else
|
|
397
|
-
event
|
|
398
|
-
end
|
|
370
|
+
allowed_out == [] or event.drop_all_but_changes_to(allowed_out || [])
|
|
399
371
|
end
|
|
400
372
|
|
|
401
373
|
|
|
374
|
+
|
|
402
375
|
end
|
|
403
376
|
end
|
|
404
377
|
end
|
|
@@ -13,22 +13,17 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License along with RubySync; if not, write to the
|
|
14
14
|
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
15
15
|
|
|
16
|
+
lib_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
17
|
+
$:.unshift lib_path unless $:.include?(lib_path)
|
|
16
18
|
|
|
17
19
|
require 'fileutils'
|
|
20
|
+
require 'rubygems'
|
|
21
|
+
require 'active_support'
|
|
18
22
|
require 'irb'
|
|
19
23
|
|
|
20
24
|
|
|
21
|
-
class ::File
|
|
22
|
-
def self.delete_if_exists(files)
|
|
23
|
-
files.kind_of?(Array) or files = [files]
|
|
24
|
-
files.each do |file|
|
|
25
|
-
File.delete(file) if File.exist?(file)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
class Object
|
|
31
25
|
|
|
26
|
+
module Kernel
|
|
32
27
|
# Make the log method globally available
|
|
33
28
|
def log
|
|
34
29
|
unless defined? @@log
|
|
@@ -39,7 +34,12 @@ class Object
|
|
|
39
34
|
@@log
|
|
40
35
|
end
|
|
41
36
|
end
|
|
42
|
-
|
|
37
|
+
|
|
38
|
+
class Array
|
|
39
|
+
def to_ruby
|
|
40
|
+
map {|f| "'#{f}'"}.join(', ')
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
43
|
|
|
44
44
|
# Generally useful methods
|
|
45
45
|
module RubySync
|
|
@@ -104,7 +104,6 @@ module RubySync
|
|
|
104
104
|
# the given name.
|
|
105
105
|
def something_called name, extension
|
|
106
106
|
filename = "#{name.to_s}_#{extension}"
|
|
107
|
-
$".include?(filename) or require filename or return nil
|
|
108
107
|
eval(filename.camelize).new
|
|
109
108
|
end
|
|
110
109
|
|
|
@@ -115,8 +114,8 @@ module RubySync
|
|
|
115
114
|
$:.unshift path unless $:.include?(path)
|
|
116
115
|
end
|
|
117
116
|
|
|
118
|
-
# Return the base_path
|
|
119
|
-
|
|
117
|
+
# Return the base_path
|
|
118
|
+
::Kernel.send :define_method, :base_path do
|
|
120
119
|
@@base_path = find_base_path unless @@base_path
|
|
121
120
|
@@base_path
|
|
122
121
|
end
|
|
@@ -125,7 +124,7 @@ module RubySync
|
|
|
125
124
|
# all of it's ancestors until it finds one that looks like a rubysync configuration
|
|
126
125
|
# directory.
|
|
127
126
|
# Returns false if no suitable directory was found
|
|
128
|
-
|
|
127
|
+
::Kernel.send :define_method, :find_base_path do
|
|
129
128
|
bp = File.expand_path(".")
|
|
130
129
|
last = nil
|
|
131
130
|
# Keep going up until we start repeating ourselves
|
|
@@ -138,12 +137,6 @@ module RubySync
|
|
|
138
137
|
return false
|
|
139
138
|
end
|
|
140
139
|
|
|
141
|
-
# Make and instance method _name_ that returns the value set by the
|
|
142
|
-
# class method _name_.
|
|
143
|
-
# def self.class_option name
|
|
144
|
-
# self.class_eval "def #{name}() self.class.instance_variable_get :#{name}; end"
|
|
145
|
-
# self.instance_eval "def #{name}(value) @#{name}=value; end"
|
|
146
|
-
# end
|
|
147
140
|
|
|
148
141
|
def get_preference(name, file_name=nil)
|
|
149
142
|
class_name ||= get_preference_file
|