rubysync 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.txt +4 -0
- data/Manifest.txt +25 -12
- data/README.txt +0 -2
- data/bin/rubysync +20 -6
- data/bin/rubysync.rb +333 -0
- data/docs/in_pipeline.graffle +2690 -0
- data/docs/init_openldap.ldif +11 -0
- data/docs/out_pipeline.graffle +3274 -0
- data/docs/schema/99rubysync.ldif +27 -0
- data/docs/schema/rubysync.schema +16 -0
- data/docs/to_sync.txt +15 -0
- data/docs/walkthru.txt +186 -0
- data/lib/ruby_sync.rb +7 -29
- data/lib/ruby_sync/connectors/base_connector.rb +55 -86
- data/lib/ruby_sync/connectors/csv_file_connector.rb +16 -4
- data/lib/ruby_sync/connectors/ldap_associations.rb +126 -0
- data/lib/ruby_sync/connectors/ldap_changelog_connector.rb +127 -0
- data/lib/ruby_sync/connectors/ldap_connector.rb +29 -192
- data/lib/ruby_sync/connectors/memory_connector.rb +1 -1
- data/lib/ruby_sync/connectors/xml_connector.rb +105 -32
- data/lib/ruby_sync/event.rb +40 -12
- data/lib/ruby_sync/operation.rb +18 -2
- data/lib/ruby_sync/pipelines/base_pipeline.rb +44 -6
- data/lib/ruby_sync/util/utilities.rb +97 -4
- data/lib/rubysync.rb +1 -1
- data/rubysync.tmproj +279 -59
- data/test/.LCKts_rubysync.rb~ +1 -0
- data/test/ruby_sync_test.rb +9 -4
- data/test/{test_active_record_vault.rb → tc_active_record_connector.rb} +11 -7
- data/test/{test_base_connector.rb → tc_base_connector.rb} +1 -1
- data/test/{test_base_pipeline.rb → tc_base_pipeline.rb} +1 -1
- data/test/tc_changelog_ldap_connector.rb +93 -0
- data/test/{test_csv_file_connector.rb → tc_csv_file_connector.rb} +14 -5
- data/test/{test_event.rb → tc_event.rb} +1 -1
- data/test/{test_ldap_changelog.rb → tc_ldap_changelog.rb} +1 -1
- data/test/{test_ldap_connector.rb → tc_ldap_connector.rb} +20 -22
- data/test/{test_ldap_vault.rb → tc_ldap_vault.rb} +2 -2
- data/test/{test_ldif.rb → tc_ldif.rb} +1 -1
- data/test/{test_memory_connectors.rb → tc_memory_connectors.rb} +10 -6
- data/test/{test_rubysync.rb → tc_rubysync.rb} +4 -4
- data/test/tc_transformation.rb +71 -0
- data/test/{test_utilities.rb → tc_utilities.rb} +28 -1
- data/test/tc_xml_connectors.rb +107 -6
- data/test/ts_rubysync.rb +11 -6
- metadata +33 -28
data/HISTORY.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -7,6 +7,14 @@ README.txt
|
|
7
7
|
Rakefile
|
8
8
|
bin/.DS_Store
|
9
9
|
bin/rubysync
|
10
|
+
bin/rubysync.rb
|
11
|
+
docs/in_pipeline.graffle
|
12
|
+
docs/init_openldap.ldif
|
13
|
+
docs/out_pipeline.graffle
|
14
|
+
docs/schema/99rubysync.ldif
|
15
|
+
docs/schema/rubysync.schema
|
16
|
+
docs/to_sync.txt
|
17
|
+
docs/walkthru.txt
|
10
18
|
examples/.DS_Store
|
11
19
|
examples/ar_client_webapp/README
|
12
20
|
examples/ar_client_webapp/Rakefile
|
@@ -179,6 +187,8 @@ lib/ruby_sync/connectors/base_connector.rb
|
|
179
187
|
lib/ruby_sync/connectors/connector_event_processing.rb
|
180
188
|
lib/ruby_sync/connectors/csv_file_connector.rb
|
181
189
|
lib/ruby_sync/connectors/file_connector.rb
|
190
|
+
lib/ruby_sync/connectors/ldap_associations.rb
|
191
|
+
lib/ruby_sync/connectors/ldap_changelog_connector.rb
|
182
192
|
lib/ruby_sync/connectors/ldap_connector.rb
|
183
193
|
lib/ruby_sync/connectors/memory_connector.rb
|
184
194
|
lib/ruby_sync/connectors/xml_connector.rb
|
@@ -193,6 +203,7 @@ nbproject/project.properties
|
|
193
203
|
nbproject/project.xml
|
194
204
|
rubysync.tmproj
|
195
205
|
test/.DS_Store
|
206
|
+
test/.LCKts_rubysync.rb~
|
196
207
|
test/data/example1.ldif
|
197
208
|
test/data/example2.ldif
|
198
209
|
test/data/example3.ldif
|
@@ -202,17 +213,19 @@ test/data/example6.ldif
|
|
202
213
|
test/data/example7.ldif
|
203
214
|
test/hashlike_tests.rb
|
204
215
|
test/ruby_sync_test.rb
|
216
|
+
test/tc_active_record_connector.rb
|
217
|
+
test/tc_base_connector.rb
|
218
|
+
test/tc_base_pipeline.rb
|
219
|
+
test/tc_changelog_ldap_connector.rb
|
220
|
+
test/tc_csv_file_connector.rb
|
221
|
+
test/tc_event.rb
|
222
|
+
test/tc_ldap_changelog.rb
|
223
|
+
test/tc_ldap_connector.rb
|
224
|
+
test/tc_ldap_vault.rb
|
225
|
+
test/tc_ldif.rb
|
226
|
+
test/tc_memory_connectors.rb
|
227
|
+
test/tc_rubysync.rb
|
228
|
+
test/tc_transformation.rb
|
229
|
+
test/tc_utilities.rb
|
205
230
|
test/tc_xml_connectors.rb
|
206
|
-
test/test_active_record_vault.rb
|
207
|
-
test/test_base_connector.rb
|
208
|
-
test/test_base_pipeline.rb
|
209
|
-
test/test_csv_file_connector.rb
|
210
|
-
test/test_event.rb
|
211
|
-
test/test_ldap_changelog.rb
|
212
|
-
test/test_ldap_connector.rb
|
213
|
-
test/test_ldap_vault.rb
|
214
|
-
test/test_ldif.rb
|
215
|
-
test/test_memory_connectors.rb
|
216
|
-
test/test_rubysync.rb
|
217
|
-
test/test_utilities.rb
|
218
231
|
test/ts_rubysync.rb
|
data/README.txt
CHANGED
data/bin/rubysync
CHANGED
@@ -112,6 +112,18 @@ class Controller < SimpleConsole::Controller
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
+
def start
|
116
|
+
pipeline_name = params[:id]
|
117
|
+
pipeline = pipeline_called pipeline_name
|
118
|
+
if pipeline
|
119
|
+
pipeline.start
|
120
|
+
else
|
121
|
+
log.error "Couldn't find a pipeline called '#{pipeline_name}'"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
|
115
127
|
# Create a Rubysync project directory
|
116
128
|
def create
|
117
129
|
config_path = params[:id]
|
@@ -207,6 +219,8 @@ Usage:
|
|
207
219
|
* once {name}
|
208
220
|
; Execute the named pipeline within the current
|
209
221
|
; configuration directory once and then exit
|
222
|
+
|
223
|
+
* start {name} ; Execute the named pipeline
|
210
224
|
|
211
225
|
* example ; Show an example of how this command might be used
|
212
226
|
|
@@ -236,9 +250,13 @@ puts <<"END"
|
|
236
250
|
You would then edit the file pipelines/my_pipeline.rb to configure the
|
237
251
|
policy for synchronizing between the two connectors.
|
238
252
|
|
239
|
-
You may then execute the pipeline in one-shot mode
|
253
|
+
You may then execute the pipeline in one-shot mode:
|
240
254
|
|
241
255
|
$ rubysync once my
|
256
|
+
|
257
|
+
or continually:
|
258
|
+
|
259
|
+
$ rubysync start my
|
242
260
|
END
|
243
261
|
end
|
244
262
|
|
@@ -248,9 +266,6 @@ end
|
|
248
266
|
|
249
267
|
|
250
268
|
|
251
|
-
def start
|
252
|
-
puts "Not yet implemented"
|
253
|
-
end
|
254
269
|
|
255
270
|
end
|
256
271
|
|
@@ -266,7 +281,6 @@ class #{name.to_s.camelize}Connector < #{type_class_name}
|
|
266
281
|
end
|
267
282
|
end;
|
268
283
|
end
|
269
|
-
|
270
284
|
|
271
285
|
|
272
286
|
def pipeline_template name, vault_name, client_name
|
@@ -298,7 +312,7 @@ class #{name.to_s.camelize}Pipeline < RubySync::Pipelines::BasePipeline
|
|
298
312
|
# 'first name' => 'givenName'
|
299
313
|
# separate each mapping with a comma.
|
300
314
|
# The following fields were detected on the client:
|
301
|
-
# #{(client_fields.map {|f| "'#{f}'"}).join(",
|
315
|
+
# #{(client_fields.map {|f| "'#{f}'"}).join(",")}
|
302
316
|
map_vault_to_client({
|
303
317
|
#{(vault_fields.map {|f| "#'#{f}' => 'a_client_field'"}).join(",\n\t\t")}
|
304
318
|
})
|
data/bin/rubysync.rb
ADDED
@@ -0,0 +1,333 @@
|
|
1
|
+
#!/opt/local/bin/ruby
|
2
|
+
|
3
|
+
|
4
|
+
# == Synopsis
|
5
|
+
#
|
6
|
+
# Command line tool for running *rubysync* <em>A Free MetaDirectory.</em>
|
7
|
+
#
|
8
|
+
# == Usage
|
9
|
+
#
|
10
|
+
# rubysync command name [options]
|
11
|
+
#
|
12
|
+
# Valid commands are::
|
13
|
+
# * create {name}:: Create a rubysync configuration directory
|
14
|
+
#
|
15
|
+
# * connector {name} -t {type} [--vault {name}] [--client {name}]
|
16
|
+
# ; Create a connector of the given name in
|
17
|
+
# ; the current rubysync configuration directory
|
18
|
+
#
|
19
|
+
# * fields {name} ; list the fields detected by the named connector
|
20
|
+
#
|
21
|
+
# * pipeline {name} ; Create a rubysync pipeline of the given name
|
22
|
+
# ; in the current rubysync configuration directory
|
23
|
+
#
|
24
|
+
# * once {name}::
|
25
|
+
# Execute the named pipeline within the current configuration directory once and then exit
|
26
|
+
#
|
27
|
+
# * example:: Show an example of how this command might be used
|
28
|
+
#
|
29
|
+
# == Example
|
30
|
+
#
|
31
|
+
# This sets up the skeleton of a configuration for importing comma delimeted
|
32
|
+
# text files into an xml file.
|
33
|
+
# <tt>
|
34
|
+
# $ rubysync create xml_demo
|
35
|
+
# $ cd xml_demo
|
36
|
+
# $ rubysync connector my_csv -t csv_file
|
37
|
+
# $ rubysync connector my_xml -t xml
|
38
|
+
# </tt>
|
39
|
+
#
|
40
|
+
# You would then edit the files::
|
41
|
+
#
|
42
|
+
# * +connectors/my_csv_connector.rb+:: where to get the CSV files, field names, etc
|
43
|
+
# * +connectors/my_xml_connector.rb+:: how to connect to your XML file.
|
44
|
+
#
|
45
|
+
# And enter::
|
46
|
+
# <tt>
|
47
|
+
# $ rubysync pipeline my_pipeline -C my_csv -V my_xml
|
48
|
+
# </tt>
|
49
|
+
#
|
50
|
+
# You would then edit the file +pipelines/my_pipeline.rb+ to configure the
|
51
|
+
# policy for synchronizing between the two connectors.
|
52
|
+
#
|
53
|
+
# You may then execute the pipeline in one-shot mode (daemon mode is coming)::
|
54
|
+
#
|
55
|
+
# <tt>
|
56
|
+
# $ rubysync once my_pipeline
|
57
|
+
# </tt>
|
58
|
+
#
|
59
|
+
# == Author
|
60
|
+
# Ritchie Young, 9 to 5 Magic (http://9to5magic.com.au)
|
61
|
+
#
|
62
|
+
# == Copyright
|
63
|
+
# Copyright (c) 2007 Ritchie Young. All rights reserved.
|
64
|
+
#
|
65
|
+
# This file is part of RubySync.
|
66
|
+
#
|
67
|
+
# RubySync is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
|
68
|
+
# as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
69
|
+
#
|
70
|
+
# RubySync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
71
|
+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
72
|
+
#
|
73
|
+
# You should have received a copy of the GNU General Public License along with RubySync; if not, write to the
|
74
|
+
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
75
|
+
|
76
|
+
|
77
|
+
lib_path = File.dirname(__FILE__) + '/../lib'
|
78
|
+
$:.unshift lib_path unless $:.include?(lib_path) || $:.include?(File.expand_path(lib_path))
|
79
|
+
require "ruby_sync"
|
80
|
+
require "simpleconsole"
|
81
|
+
require 'rdoc/usage'
|
82
|
+
|
83
|
+
|
84
|
+
class Controller < SimpleConsole::Controller
|
85
|
+
|
86
|
+
include RubySync::Utilities
|
87
|
+
|
88
|
+
before_filter :configure_logging
|
89
|
+
|
90
|
+
params :string => {:p => :pipe,
|
91
|
+
:t => :type,
|
92
|
+
:V => :vault,
|
93
|
+
:C => :client},
|
94
|
+
:int =>{:v => :verbose}
|
95
|
+
|
96
|
+
def default
|
97
|
+
#RDoc::usage 'Usage'
|
98
|
+
end
|
99
|
+
|
100
|
+
def example
|
101
|
+
#RDoc::usage 'Example'
|
102
|
+
end
|
103
|
+
|
104
|
+
# Run specified pipeline once then exit
|
105
|
+
def once
|
106
|
+
pipeline_name = params[:id]
|
107
|
+
pipeline = pipeline_called pipeline_name
|
108
|
+
if pipeline
|
109
|
+
pipeline.run_once
|
110
|
+
else
|
111
|
+
log.error "Couldn't find a pipeline called '#{pipeline_name}'"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def start
|
116
|
+
pipeline_name = params[:id]
|
117
|
+
pipeline = pipeline_called pipeline_name
|
118
|
+
if pipeline
|
119
|
+
pipeline.start
|
120
|
+
else
|
121
|
+
log.error "Couldn't find a pipeline called '#{pipeline_name}'"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
# Create a Rubysync project directory
|
128
|
+
def create
|
129
|
+
config_path = params[:id]
|
130
|
+
ensure_dir_exists([
|
131
|
+
config_path,
|
132
|
+
"#{config_path}/pipelines",
|
133
|
+
"#{config_path}/connectors",
|
134
|
+
"#{config_path}/shared",
|
135
|
+
"#{config_path}/shared/pipelines",
|
136
|
+
"#{config_path}/shared/connectors",
|
137
|
+
"#{config_path}/shared/lib",
|
138
|
+
"#{config_path}/log",
|
139
|
+
"#{config_path}/db"
|
140
|
+
])
|
141
|
+
end
|
142
|
+
|
143
|
+
# Create a connector configuration file
|
144
|
+
def connector
|
145
|
+
name = params[:id]
|
146
|
+
type = params[:type]
|
147
|
+
unless name and type
|
148
|
+
puts "Usage: rubysync connector connector_name -t connector_type"
|
149
|
+
return
|
150
|
+
end
|
151
|
+
if base_path
|
152
|
+
File.open("#{base_path}/connectors/#{name}_connector.rb", "w") do |file|
|
153
|
+
file.puts connector_template(name, type)
|
154
|
+
end
|
155
|
+
else
|
156
|
+
puts 'Change into a config dir and try again or create a config dir with "rubysync create"'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# List the fields that the named connector can detect. This is
|
161
|
+
# a good way to test if a connector config is functional.
|
162
|
+
def fields
|
163
|
+
connector_name = params[:id]
|
164
|
+
connector = (connector_name)? ::RubySync::Connectors::BaseConnector.class_for(connector_name) : nil
|
165
|
+
@field_names = connector && connector.fields || []
|
166
|
+
end
|
167
|
+
|
168
|
+
def pipeline
|
169
|
+
name = params[:id]
|
170
|
+
vault_name = params[:vault]
|
171
|
+
client_name = params[:client]
|
172
|
+
unless name
|
173
|
+
puts "Usage: rubysync pipeline pipeline_name [-V vault] [-C client]"
|
174
|
+
return
|
175
|
+
end
|
176
|
+
if base_path
|
177
|
+
File.open("#{base_path}/pipelines/#{name}_pipeline.rb", "w") do |file|
|
178
|
+
file.puts pipeline_template(name, vault_name, client_name)
|
179
|
+
end
|
180
|
+
else
|
181
|
+
puts 'Change into a config dir and try again or create a config dir with "rubysync create"'
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
private
|
188
|
+
|
189
|
+
def configure_logging
|
190
|
+
log_levels = [Logger::WARN, Logger::INFO, Logger::DEBUG]
|
191
|
+
verbosity = [(params[:verbose]||0), log_levels.size-1].min
|
192
|
+
log.level = log_levels[verbosity]
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
class View < SimpleConsole::View
|
199
|
+
|
200
|
+
|
201
|
+
def default
|
202
|
+
puts <<"END"
|
203
|
+
Usage:
|
204
|
+
|
205
|
+
rubysync command name [options]
|
206
|
+
|
207
|
+
Valid commands are:
|
208
|
+
* create {name}: Create a rubysync configuration directory
|
209
|
+
|
210
|
+
* connector {name} -t {type} [--vault {name}] [--client {name}]
|
211
|
+
; Create a connector of the given name in
|
212
|
+
; the current rubysync configuration directory
|
213
|
+
|
214
|
+
* fields {name} ; list the fields detected by the named connector
|
215
|
+
|
216
|
+
* pipeline {name} ; Create a rubysync pipeline of the given name
|
217
|
+
; in the current rubysync configuration directory
|
218
|
+
|
219
|
+
* once {name}
|
220
|
+
; Execute the named pipeline within the current
|
221
|
+
; configuration directory once and then exit
|
222
|
+
|
223
|
+
* start {name} ; Execute the named pipeline
|
224
|
+
|
225
|
+
* example ; Show an example of how this command might be used
|
226
|
+
|
227
|
+
END
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
def example
|
232
|
+
puts <<"END"
|
233
|
+
This sets up the skeleton of a configuration for importing comma delimeted
|
234
|
+
text files into a database. Note, if the application happens to be a Rails
|
235
|
+
app then it can also export changes.
|
236
|
+
|
237
|
+
$ rubysync create db_demo
|
238
|
+
$ cd db_demo
|
239
|
+
$ rubysync connector my_csv -t csv_file
|
240
|
+
$ rubysync connector my_db -t active_record
|
241
|
+
|
242
|
+
You would then edit the files:
|
243
|
+
|
244
|
+
connectors/my_csv_connector.rb ;where to get CSV files, field names, etc
|
245
|
+
connectors/my_db_connector.rb ;how to connect to your DB or Rails app.
|
246
|
+
|
247
|
+
And enter:
|
248
|
+
$ rubysync pipeline my -C my_csv -V my_db
|
249
|
+
|
250
|
+
You would then edit the file pipelines/my_pipeline.rb to configure the
|
251
|
+
policy for synchronizing between the two connectors.
|
252
|
+
|
253
|
+
You may then execute the pipeline in one-shot mode:
|
254
|
+
|
255
|
+
$ rubysync once my
|
256
|
+
|
257
|
+
or continually:
|
258
|
+
|
259
|
+
$ rubysync start my
|
260
|
+
END
|
261
|
+
end
|
262
|
+
|
263
|
+
def fields
|
264
|
+
puts @field_names.join("\n")
|
265
|
+
end
|
266
|
+
|
267
|
+
|
268
|
+
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
def connector_template name, type
|
274
|
+
type_class_name = "RubySync::Connectors::#{type.to_s.camelize}Connector"
|
275
|
+
type_class = eval(type_class_name)
|
276
|
+
sample_config = (type_class && type_class.respond_to?("sample_config")) ?
|
277
|
+
type_class.sample_config : ""
|
278
|
+
return <<-"end;"
|
279
|
+
class #{name.to_s.camelize}Connector < #{type_class_name}
|
280
|
+
#{sample_config}
|
281
|
+
end
|
282
|
+
end;
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
def pipeline_template name, vault_name, client_name
|
287
|
+
vault = (vault_name)? ::RubySync::Connectors::BaseConnector.class_for(vault_name) : nil
|
288
|
+
vault_fields = vault && vault.fields || %w{allow these fields through}
|
289
|
+
possible_fields = (vault_fields.map {|n| ":#{n}"}).join(", ")
|
290
|
+
|
291
|
+
client = (client_name)? ::RubySync::Connectors::BaseConnector.class_for(client_name) : nil
|
292
|
+
client_fields = client && client.fields || []
|
293
|
+
|
294
|
+
vault_specifier = (vault_name)? "vault :#{vault_name}" : "#vault :vault_connector_name"
|
295
|
+
client_specifier = (client_name)? "client :#{client_name}" : "#client :client_connector_name"
|
296
|
+
return <<-"end;"
|
297
|
+
class #{name.to_s.camelize}Pipeline < RubySync::Pipelines::BasePipeline
|
298
|
+
|
299
|
+
#{client_specifier}
|
300
|
+
|
301
|
+
#{vault_specifier}
|
302
|
+
|
303
|
+
# Remove any fields that you don't want to set in the client from the vault
|
304
|
+
allow_out #{possible_fields}
|
305
|
+
|
306
|
+
# Remove any fields that you don't want to set in the vault from the client
|
307
|
+
allow_in #{possible_fields}
|
308
|
+
|
309
|
+
# If the client and vault have different names for the same field, define the
|
310
|
+
# the mapping here. For example, if the vault has a field called "first name" and
|
311
|
+
# the client has a field called givenName you may put:
|
312
|
+
# 'first name' => 'givenName'
|
313
|
+
# separate each mapping with a comma.
|
314
|
+
# The following fields were detected on the client:
|
315
|
+
# #{(client_fields.map {|f| "'#{f}'"}).join(",")}
|
316
|
+
map_vault_to_client({
|
317
|
+
#{(vault_fields.map {|f| "#'#{f}' => 'a_client_field'"}).join(",\n\t\t")}
|
318
|
+
})
|
319
|
+
|
320
|
+
# "in" means going from client to vault
|
321
|
+
#in_transform do
|
322
|
+
#end
|
323
|
+
|
324
|
+
# "out" means going from vault to client
|
325
|
+
#out_transform do
|
326
|
+
#end
|
327
|
+
|
328
|
+
end
|
329
|
+
end;
|
330
|
+
end
|
331
|
+
|
332
|
+
|
333
|
+
SimpleConsole::Application.run(ARGV, Controller, View)
|