rubysync 0.0.3 → 0.0.4
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 +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)
|