rubysync 0.0.1 → 0.0.2
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/bin/rubysync +3 -3
- data/examples/ims2/connectors/hr_db_connector.rb +3 -5
- data/examples/my_ims/connectors/my_csv_connector.rb +10 -0
- data/examples/my_ims/connectors/my_db_connector.rb +7 -0
- data/examples/my_ims/pipelines/{finance_pipeline.rb → my_pipeline.rb} +9 -9
- data/lib/net/ldif.rb +302 -0
- data/lib/ruby_sync/connectors/active_record_connector.rb +33 -32
- data/lib/ruby_sync/connectors/base_connector.rb +21 -10
- data/lib/ruby_sync/connectors/csv_file_connector.rb +17 -22
- data/lib/ruby_sync/connectors/file_connector.rb +11 -11
- data/lib/ruby_sync/connectors/ldap_connector.rb +206 -53
- data/lib/ruby_sync/connectors/memory_connector.rb +5 -8
- data/lib/ruby_sync/event.rb +11 -3
- data/lib/ruby_sync/operation.rb +1 -1
- data/lib/ruby_sync/pipelines/base_pipeline.rb +6 -0
- data/lib/ruby_sync/util/utilities.rb +22 -3
- data/lib/ruby_sync.rb +25 -2
- data/test/data/example1.ldif +20 -0
- data/test/data/example2.ldif +14 -0
- data/test/data/example3.ldif +13 -0
- data/test/data/example4.ldif +55 -0
- data/test/data/example5.ldif +12 -0
- data/test/data/example6.ldif +62 -0
- data/test/data/example7.ldif +8 -0
- data/test/test_active_record_vault.rb +3 -4
- data/test/test_base_pipeline.rb +58 -0
- data/test/test_csv_file_connector.rb +7 -7
- data/test/test_ldap_connector.rb +71 -13
- data/test/test_ldap_vault.rb +91 -0
- data/test/test_ldif.rb +122 -0
- data/test/test_utilities.rb +63 -0
- metadata +19 -7
- data/examples/my_ims/connectors/corp_directory_connector.rb +0 -12
- data/examples/my_ims/connectors/finance_connector.rb +0 -7
- data/examples/my_ims/connectors/hr_db_connector.rb +0 -7
- data/examples/my_ims/pipelines/hr_import_pipeline.rb +0 -29
@@ -0,0 +1,13 @@
|
|
1
|
+
version: 1
|
2
|
+
dn: cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com
|
3
|
+
objectclass: top
|
4
|
+
objectclass: person
|
5
|
+
objectclass: organizationalPerson
|
6
|
+
cn: Gern Jensen
|
7
|
+
cn: Gern O Jensen
|
8
|
+
sn: Jensen
|
9
|
+
uid: gernj
|
10
|
+
telephonenumber: +1 408 555 1212
|
11
|
+
description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVlIGlzIGJ
|
12
|
+
hc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdGVyIGluIGl0ICh
|
13
|
+
hIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQgb3V0IG1vcmUu
|
@@ -0,0 +1,55 @@
|
|
1
|
+
version: 1
|
2
|
+
dn:: b3U95Za25qWt6YOoLG89QWlyaXVz
|
3
|
+
# dn:: ou=<JapaneseOU>,o=Airius
|
4
|
+
objectclass: top
|
5
|
+
objectclass: organizationalUnit
|
6
|
+
ou:: 5Za25qWt6YOo
|
7
|
+
# ou:: <JapaneseOU>
|
8
|
+
ou;lang-ja:: 5Za25qWt6YOo
|
9
|
+
# ou;lang-ja:: <JapaneseOU>
|
10
|
+
ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2
|
11
|
+
|
12
|
+
# ou;lang-ja:: <JapaneseOU_in_phonetic_representation>
|
13
|
+
ou;lang-en: Sales
|
14
|
+
description: Japanese office
|
15
|
+
|
16
|
+
dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
|
17
|
+
# dn:: uid=<uid>,ou=<JapaneseOU>,o=Airius
|
18
|
+
userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
|
19
|
+
objectclass: top
|
20
|
+
objectclass: person
|
21
|
+
objectclass: organizationalPerson
|
22
|
+
objectclass: inetOrgPerson
|
23
|
+
uid: rogasawara
|
24
|
+
mail: rogasawara@airius.co.jp
|
25
|
+
givenname;lang-ja:: 44Ot44OJ44OL44O8
|
26
|
+
# givenname;lang-ja:: <JapaneseGivenname>
|
27
|
+
sn;lang-ja:: 5bCP56yg5Y6f
|
28
|
+
# sn;lang-ja:: <JapaneseSn>
|
29
|
+
cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
|
30
|
+
# cn;lang-ja:: <JapaneseCn>
|
31
|
+
title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
|
32
|
+
# title;lang-ja:: <JapaneseTitle>
|
33
|
+
preferredlanguage: ja
|
34
|
+
givenname:: 44Ot44OJ44OL44O8
|
35
|
+
# givenname:: <JapaneseGivenname>
|
36
|
+
sn:: 5bCP56yg5Y6f
|
37
|
+
# sn:: <JapaneseSn>
|
38
|
+
cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
|
39
|
+
# cn:: <JapaneseCn>
|
40
|
+
title:: 5Za25qWt6YOoIOmDqOmVtw==
|
41
|
+
# title:: <JapaneseTitle>
|
42
|
+
givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
|
43
|
+
# givenname;lang-ja;phonetic::
|
44
|
+
<JapaneseGivenname_in_phonetic_representation_kana>
|
45
|
+
sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
|
46
|
+
# sn;lang-ja;phonetic:: <JapaneseSn_in_phonetic_representation_kana>
|
47
|
+
cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
|
48
|
+
# cn;lang-ja;phonetic:: <JapaneseCn_in_phonetic_representation_kana>
|
49
|
+
title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
|
50
|
+
# title;lang-ja;phonetic::
|
51
|
+
# <JapaneseTitle_in_phonetic_representation_kana>
|
52
|
+
givenname;lang-en: Rodney
|
53
|
+
sn;lang-en: Ogasawara
|
54
|
+
cn;lang-en: Rodney Ogasawara
|
55
|
+
title;lang-en: Sales, Director
|
@@ -0,0 +1,12 @@
|
|
1
|
+
version: 1
|
2
|
+
dn: cn=Horatio Jensen, ou=Product Testing, dc=airius, dc=com
|
3
|
+
objectclass: top
|
4
|
+
objectclass: person
|
5
|
+
objectclass: organizationalPerson
|
6
|
+
cn: Horatio Jensen
|
7
|
+
|
8
|
+
cn: Horatio N Jensen
|
9
|
+
sn: Jensen
|
10
|
+
uid: hjensen
|
11
|
+
telephonenumber: +1 408 555 1212
|
12
|
+
jpegphoto:< file:///usr/local/directory/photos/hjensen.jpg
|
@@ -0,0 +1,62 @@
|
|
1
|
+
version: 1
|
2
|
+
# Add a new entry
|
3
|
+
dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
|
4
|
+
changetype: add
|
5
|
+
objectclass: top
|
6
|
+
objectclass: person
|
7
|
+
objectclass: organizationalPerson
|
8
|
+
cn: Fiona Jensen
|
9
|
+
sn: Jensen
|
10
|
+
uid: fiona
|
11
|
+
telephonenumber: +1 408 555 1212
|
12
|
+
jpegphoto:< file:///etc/hosts
|
13
|
+
|
14
|
+
# Delete an existing entry
|
15
|
+
dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
|
16
|
+
changetype: delete
|
17
|
+
|
18
|
+
# Modify an entry's relative distinguished name
|
19
|
+
dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
|
20
|
+
changetype: modrdn
|
21
|
+
newrdn: cn=Paula Jensen
|
22
|
+
deleteoldrdn: 1
|
23
|
+
|
24
|
+
# Rename an entry and move all of its children to a new location in
|
25
|
+
# the directory tree (only implemented by LDAPv3 servers).
|
26
|
+
dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
|
27
|
+
changetype: modrdn
|
28
|
+
newrdn: ou=Product Development Accountants
|
29
|
+
deleteoldrdn: 0
|
30
|
+
newsuperior: ou=Accounting, dc=airius, dc=com
|
31
|
+
|
32
|
+
# Modify an entry: add an additional value to the postaladdress
|
33
|
+
# attribute, completely delete the description attribute, replace
|
34
|
+
# the telephonenumber attribute with two values, and delete a specific
|
35
|
+
# value from the facsimiletelephonenumber attribute
|
36
|
+
dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
|
37
|
+
changetype: modify
|
38
|
+
add: postaladdress
|
39
|
+
postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
|
40
|
+
-
|
41
|
+
|
42
|
+
delete: description
|
43
|
+
-
|
44
|
+
replace: telephonenumber
|
45
|
+
telephonenumber: +1 408 555 1234
|
46
|
+
telephonenumber: +1 408 555 5678
|
47
|
+
-
|
48
|
+
delete: facsimiletelephonenumber
|
49
|
+
facsimiletelephonenumber: +1 408 555 9876
|
50
|
+
-
|
51
|
+
|
52
|
+
# Modify an entry: replace the postaladdress attribute with an empty
|
53
|
+
# set of values (which will cause the attribute to be removed), and
|
54
|
+
# delete the entire description attribute. Note that the first will
|
55
|
+
# always succeed, while the second will only succeed if at least
|
56
|
+
# one value for the description attribute is present.
|
57
|
+
dn: cn=Ingrid Jensen, ou=Product Support, dc=airius, dc=com
|
58
|
+
changetype: modify
|
59
|
+
replace: postaladdress
|
60
|
+
-
|
61
|
+
delete: description
|
62
|
+
-
|
@@ -0,0 +1,8 @@
|
|
1
|
+
version: 1
|
2
|
+
# Delete an entry. The operation will attach the LDAPv3
|
3
|
+
# Tree Delete Control defined in [9]. The criticality
|
4
|
+
# field is "true" and the controlValue field is
|
5
|
+
# absent, as required by [9].
|
6
|
+
dn: ou=Product Development, dc=airius, dc=com
|
7
|
+
control: 1.2.840.113556.1.4.805 true
|
8
|
+
changetype: delete
|
@@ -20,11 +20,10 @@ $:.unshift lib_path unless $:.include?(lib_path) || $:.include?(File.expand_path
|
|
20
20
|
require 'ruby_sync_test'
|
21
21
|
|
22
22
|
class MyActiveRecordConnector < RubySync::Connectors::ActiveRecordConnector
|
23
|
-
|
24
|
-
|
25
|
-
:application=>"#{File.dirname(__FILE__)}/../examples/ar_webapp"
|
26
|
-
)
|
23
|
+
model :person
|
24
|
+
application "#{File.dirname(__FILE__)}/../examples/ar_webapp"
|
27
25
|
end
|
26
|
+
|
28
27
|
class MyMemoryConnector < RubySync::Connectors::MemoryConnector; end
|
29
28
|
|
30
29
|
class TestPipeline < RubySync::Pipelines::BasePipeline
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
#
|
3
|
+
# Copyright (c) 2007 Ritchie Young. All rights reserved.
|
4
|
+
#
|
5
|
+
# This file is part of RubySync.
|
6
|
+
#
|
7
|
+
# RubySync is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
|
8
|
+
# as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# RubySync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
11
|
+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License along with RubySync; if not, write to the
|
14
|
+
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
15
|
+
|
16
|
+
|
17
|
+
lib_path = File.dirname(__FILE__) + '/../lib'
|
18
|
+
$:.unshift lib_path unless $:.include?(lib_path) || $:.include?(File.expand_path(lib_path))
|
19
|
+
|
20
|
+
require 'ruby_sync'
|
21
|
+
require 'test/unit'
|
22
|
+
|
23
|
+
class ClientConnector < RubySync::Connectors::MemoryConnector
|
24
|
+
end
|
25
|
+
|
26
|
+
class VaultConnector < RubySync::Connectors::MemoryConnector
|
27
|
+
end
|
28
|
+
|
29
|
+
class TestPipeline < RubySync::Pipelines::BasePipeline
|
30
|
+
|
31
|
+
client :client
|
32
|
+
vault :vault
|
33
|
+
|
34
|
+
allow_in :cn, :givenName, :sn
|
35
|
+
allow_out :id, :name
|
36
|
+
|
37
|
+
# This is experimental at this stage
|
38
|
+
# map_vault_to_client :cn => :id,
|
39
|
+
# :givenName => calc { :name.split(/\w+/)[0] },
|
40
|
+
# :sn => calc { :name.split(/\w+/)[1] }
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
class TestBasePipeline < Test::Unit::TestCase
|
45
|
+
|
46
|
+
|
47
|
+
def setup
|
48
|
+
@pipeline = TestPipeline.new
|
49
|
+
@client = @pipeline.client
|
50
|
+
@vault = @pipeline.vault
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_mappings
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
end
|
@@ -23,6 +23,10 @@ require 'csv'
|
|
23
23
|
|
24
24
|
|
25
25
|
class TestCsvFileConnector < RubySync::Connectors::CsvFileConnector
|
26
|
+
field_names ['id', 'given name', 'last name', 'email']
|
27
|
+
path_field 'id'
|
28
|
+
in_path File.expand_path("~/rubysync/csv_test/in")
|
29
|
+
out_path File.expand_path("~/rubysync/csv_test/out")
|
26
30
|
end
|
27
31
|
|
28
32
|
class TestMemoryConnector < RubySync::Connectors::MemoryConnector
|
@@ -30,11 +34,7 @@ end
|
|
30
34
|
|
31
35
|
|
32
36
|
class TestPipeline < RubySync::Pipelines::BasePipeline
|
33
|
-
client :test_csv_file
|
34
|
-
:field_names => ['id', 'given name', 'last name', 'email'],
|
35
|
-
:path_field => 'id',
|
36
|
-
:in_path => File.expand_path("~/rubysync/csv_test/in"),
|
37
|
-
:out_path => File.expand_path("~/rubysync/csv_test/out")
|
37
|
+
client :test_csv_file
|
38
38
|
|
39
39
|
vault :test_memory
|
40
40
|
|
@@ -67,9 +67,9 @@ class TestCsvConnector < Test::Unit::TestCase
|
|
67
67
|
assert_nil @vault["bob"], "Vault already contains bob"
|
68
68
|
@pipeline.run_once
|
69
69
|
assert_not_nil @vault["bob"], "Bob wasn't created in vault"
|
70
|
-
modded_bob={}; @bob_details.each_pair {|k,v| modded_bob[k]=v.as_array}
|
70
|
+
modded_bob={}; @bob_details.each_pair {|k,v| modded_bob[k.to_s]=v.as_array}
|
71
71
|
assert_equal modded_bob, @vault["bob"].reject {|k,v| ['modifier',:association].include? k}
|
72
72
|
@pipeline.run_once
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
end
|
data/test/test_ldap_connector.rb
CHANGED
@@ -23,18 +23,30 @@ require 'ruby_sync/connectors/ldap_connector'
|
|
23
23
|
require 'ruby_sync/connectors/memory_connector'
|
24
24
|
|
25
25
|
|
26
|
-
class
|
26
|
+
class ChangeLogConnector < RubySync::Connectors::LdapConnector
|
27
|
+
host '10.1.1.4'
|
28
|
+
port 389
|
29
|
+
username 'cn=directory manager'
|
30
|
+
password 'password'
|
31
|
+
changelog_dn 'cn=changelog'
|
32
|
+
search_filter "cn=*"
|
33
|
+
search_base "ou=people,dc=9to5magic,dc=com,dc=au"
|
34
|
+
end
|
35
|
+
|
36
|
+
class MyLdapConnector < RubySync::Connectors::LdapConnector
|
37
|
+
host 'localhost'
|
38
|
+
port 10389
|
39
|
+
username 'uid=admin,ou=system'
|
40
|
+
password 'secret'
|
41
|
+
search_filter "cn=*"
|
42
|
+
search_base "dc=example,dc=com"
|
43
|
+
end
|
44
|
+
|
27
45
|
class MyMemoryConnector < RubySync::Connectors::MemoryConnector; end
|
28
46
|
|
29
47
|
class TestPipeline < RubySync::Pipelines::BasePipeline
|
30
48
|
|
31
|
-
client :my_ldap
|
32
|
-
:host=>'localhost',
|
33
|
-
:port=>10389,
|
34
|
-
:username=>'uid=admin,ou=system',
|
35
|
-
:password=>'secret',
|
36
|
-
:search_filter=>"cn=*",
|
37
|
-
:search_base=>"dc=example,dc=com"
|
49
|
+
client :my_ldap
|
38
50
|
|
39
51
|
vault :my_memory
|
40
52
|
|
@@ -73,17 +85,63 @@ class TestLdapConnector < Test::Unit::TestCase
|
|
73
85
|
|
74
86
|
def test_ldap_add
|
75
87
|
assert_nil @client[client_path], "#{client_path} already exists on client"
|
76
|
-
|
88
|
+
@client.add client_path, @client.create_operations_for(ldap_attr)
|
89
|
+
assert_not_nil @client[client_path], "#{client_path} wasn't created"
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_client_to_vault
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
# Add various types of record and verifies that the appropriate
|
97
|
+
# changelog entries appear.
|
98
|
+
# Other activity on the LDAP server may interfere with this test.
|
99
|
+
def test_get_changes
|
100
|
+
banner "test_get_changes"
|
101
|
+
c = ChangeLogConnector.new
|
102
|
+
path = "cn=bob,#{c.search_base}"
|
103
|
+
c.delete(path) if c[path]
|
104
|
+
c.each_change do |event|
|
105
|
+
end # Ignore up til now
|
106
|
+
|
107
|
+
|
108
|
+
c.add(path, c.create_operations_for(ldap_attr))
|
109
|
+
assert_event :add, c, path
|
110
|
+
|
111
|
+
c.modify(path, [
|
112
|
+
RubySync::Operation.replace('mail', "bob@fischer.com"),
|
113
|
+
RubySync::Operation.add('givenName', "Robert")
|
114
|
+
])
|
115
|
+
event = assert_event :modify, c, path
|
116
|
+
puts event.payload.inspect
|
117
|
+
|
118
|
+
c.delete(path)
|
119
|
+
assert_event :delete, c, path
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def ldap_attr
|
125
|
+
{
|
77
126
|
"objectclass"=>['inetOrgPerson'],
|
78
127
|
"cn"=>'bob',
|
79
128
|
"sn"=>'roberts',
|
80
129
|
"mail"=>"bob@roberts.com"
|
81
130
|
}
|
82
|
-
@client.add client_path, @client.create_operations_for(ldap_attr)
|
83
|
-
assert_not_nil @client[client_path], "#{client_path} wasn't created"
|
84
131
|
end
|
85
132
|
|
86
|
-
def
|
133
|
+
def assert_event type, connector, path
|
134
|
+
events = 0
|
135
|
+
the_event=nil
|
136
|
+
connector.each_change do |event|
|
137
|
+
the_event = event
|
138
|
+
events += 1
|
139
|
+
assert_equal type.to_sym, event.type
|
140
|
+
assert_equal connector, event.source
|
141
|
+
assert_equal path, event.source_path
|
142
|
+
end
|
143
|
+
assert_equal 1, events, "wrong number of events on #{type.to_s}"
|
144
|
+
the_event
|
87
145
|
end
|
88
146
|
|
89
|
-
end
|
147
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
#
|
3
|
+
# Copyright (c) 2007 Ritchie Young. All rights reserved.
|
4
|
+
#
|
5
|
+
# This file is part of RubySync.
|
6
|
+
#
|
7
|
+
# RubySync is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
|
8
|
+
# as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# RubySync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
11
|
+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License along with RubySync; if not, write to the
|
14
|
+
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
15
|
+
|
16
|
+
|
17
|
+
lib_path = File.dirname(__FILE__) + '/../lib'
|
18
|
+
$:.unshift lib_path unless $:.include?(lib_path) || $:.include?(File.expand_path(lib_path))
|
19
|
+
|
20
|
+
require 'ruby_sync_test'
|
21
|
+
require 'hashlike_tests'
|
22
|
+
require 'ruby_sync/connectors/ldap_connector'
|
23
|
+
require 'ruby_sync/connectors/memory_connector'
|
24
|
+
|
25
|
+
|
26
|
+
class MyLdapConnector < RubySync::Connectors::LdapConnector
|
27
|
+
host '10.1.1.4'
|
28
|
+
port 389
|
29
|
+
username 'cn=directory manager'
|
30
|
+
password 'password'
|
31
|
+
changelog_dn 'cn=changelog'
|
32
|
+
search_filter "cn=*"
|
33
|
+
search_base "ou=people,dc=9to5magic,dc=com,dc=au"
|
34
|
+
|
35
|
+
def initialize options={}
|
36
|
+
super(options)
|
37
|
+
skip_existing_changelog_entries
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class MyMemoryConnector < RubySync::Connectors::MemoryConnector; end
|
43
|
+
|
44
|
+
class TestPipeline < RubySync::Pipelines::BasePipeline
|
45
|
+
|
46
|
+
client :my_memory
|
47
|
+
|
48
|
+
vault :my_ldap
|
49
|
+
|
50
|
+
allow_out :cn, :givenName, :sn
|
51
|
+
allow_in :cn, :givenName, :sn, :objectclass
|
52
|
+
|
53
|
+
def in_place(event)
|
54
|
+
event.target_path = "cn=#{event.source_path},ou=people,dc=9to5magic,dc=com,dc=au"
|
55
|
+
end
|
56
|
+
|
57
|
+
def out_place(event)
|
58
|
+
event.target_path =~ /cn=(.+?),/oi
|
59
|
+
event.source_path = $1
|
60
|
+
end
|
61
|
+
|
62
|
+
in_transform do
|
63
|
+
if type == :add or type == :modify
|
64
|
+
each_operation_on("givenName") { |operation| append operation.same_but_on('cn') }
|
65
|
+
append RubySync::Operation.new(:add, "objectclass", ['inetOrgPerson', 'organizationalPerson', 'person', 'top', 'RubySyncSynchable'])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
class TestLdapVault < Test::Unit::TestCase
|
73
|
+
|
74
|
+
include RubySyncTest
|
75
|
+
include HashlikeTests
|
76
|
+
|
77
|
+
|
78
|
+
def unsynchable
|
79
|
+
["objectclass", "interests", "cn", "dn", "rubysyncassociation"]
|
80
|
+
end
|
81
|
+
|
82
|
+
def client_path
|
83
|
+
'bob'
|
84
|
+
end
|
85
|
+
|
86
|
+
def vault_path
|
87
|
+
'cn=bob,ou=people,dc=9to5magic,dc=com,dc=au'
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
end
|
data/test/test_ldif.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
#
|
3
|
+
# Copyright (c) 2007 Ritchie Young. All rights reserved.
|
4
|
+
#
|
5
|
+
# This file is part of RubySync.
|
6
|
+
#
|
7
|
+
# RubySync is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
|
8
|
+
# as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# RubySync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
11
|
+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License along with RubySync; if not, write to the
|
14
|
+
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
15
|
+
|
16
|
+
|
17
|
+
lib_path = File.dirname(__FILE__) + '/../lib'
|
18
|
+
$:.unshift lib_path unless $:.include?(lib_path) || $:.include?(File.expand_path(lib_path))
|
19
|
+
|
20
|
+
require 'net/ldif'
|
21
|
+
require 'test/unit'
|
22
|
+
|
23
|
+
# TODO: Work out a cross platform method for testing file:// URL imports
|
24
|
+
class TestLDIF < Test::Unit::TestCase
|
25
|
+
|
26
|
+
def setup
|
27
|
+
@ldif = Net::LDIF
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_tokenizer
|
31
|
+
a = array_for_file "example1.ldif"
|
32
|
+
#a.each_index {|i| puts "#{i}\t#{a[i][0]}:#{a[i][1]}"}
|
33
|
+
assert_equal ["version", "1"], a[0]
|
34
|
+
assert_equal ["dn", "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com"],a[1]
|
35
|
+
assert_equal [nil,nil], a[12], "Blank line didn't yield nil name"
|
36
|
+
assert_equal ["telephonenumber", "+1 408 555 1212"], a[19]
|
37
|
+
|
38
|
+
a = array_for_file "example2.ldif"
|
39
|
+
assert_equal ["description", "Babs is a big sailing fan, and travels extensively in search of perfect sailing conditions."],a[11]
|
40
|
+
assert_equal ["title", "Product Manager, Rod and Reel Division"],a[12]
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_tokenize_base64
|
44
|
+
a = array_for_file "example3.ldif"
|
45
|
+
#a.each_index {|i| puts "#{i}\t#{a[i][0]}:#{a[i][1]}"}
|
46
|
+
assert_equal ["description", "What a careful reader you are! This value is"+
|
47
|
+
" base-64-encoded because it has a control character in it (a CR).\r"+
|
48
|
+
" By the way, you should really get out more."], a[10]
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def test_tokenize_hyphens
|
53
|
+
a = array_for_file "example6.ldif"
|
54
|
+
#a.each_index {|i| puts "#{i}\t#{a[i][0]}:#{a[i][1]}"}
|
55
|
+
assert_equal ["telephonenumber","+1 408 555 1212"], a[9]
|
56
|
+
[30,33,37,40,45,47].each {|i| assert_equal ["-","-"], a[i]}
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_parse_simple_content
|
61
|
+
c = changes_for("example1.ldif")
|
62
|
+
assert_equal 2, c.length
|
63
|
+
assert_equal 'add', c[0].changetype
|
64
|
+
assert_equal 'cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com', c[0].dn
|
65
|
+
assert_equal ['top','person','organizationalPerson'], c[0].data['objectclass']
|
66
|
+
assert_equal ['Barbara Jensen','Barbara J Jensen','Babs Jensen'], c[0].data['cn']
|
67
|
+
assert_equal 'Jensen', c[0].data['sn']
|
68
|
+
assert_equal 'A big sailing fan.', c[0].data['description']
|
69
|
+
|
70
|
+
assert_equal 'add', c[1].changetype
|
71
|
+
assert_equal "cn=Bjorn Jensen, ou=Accounting, dc=airius, dc=com", c[1].dn
|
72
|
+
assert_equal '+1 408 555 1212', c[1].data['telephonenumber']
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_parse_change_records
|
76
|
+
c = changes_for("example6.ldif")
|
77
|
+
assert_equal 6, c.length
|
78
|
+
#puts c.join("\n---\n")
|
79
|
+
assert_equal "cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com", c[0].dn
|
80
|
+
assert_equal 'add', c[0].changetype
|
81
|
+
assert_equal ['top', 'person', 'organizationalPerson'], c[0].data['objectclass']
|
82
|
+
|
83
|
+
assert_equal "Fiona Jensen", c[0].data['cn']
|
84
|
+
assert_equal "+1 408 555 1212", c[0].data['telephonenumber']
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def changes_for(filename)
|
91
|
+
content = []
|
92
|
+
with_file(filename) do |file|
|
93
|
+
@ldif.parse(file) do |record|
|
94
|
+
assert_kind_of Net::ChangeRecord, record
|
95
|
+
content << record
|
96
|
+
end
|
97
|
+
end
|
98
|
+
content
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
def array_for_file filename
|
103
|
+
array = []
|
104
|
+
tokenize_file(filename) {|name, value| array << [name, value]}
|
105
|
+
array
|
106
|
+
end
|
107
|
+
|
108
|
+
def tokenize_file filename
|
109
|
+
with_file(filename) do |file|
|
110
|
+
@ldif.tokenize(file) { |name, value| yield name,value }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def with_file(filename)
|
115
|
+
File.open(path_for(filename), 'r') {|file| yield file}
|
116
|
+
end
|
117
|
+
|
118
|
+
def path_for filename
|
119
|
+
"#{File.dirname(__FILE__)}/data/#{filename}"
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
#
|
3
|
+
# Copyright (c) 2007 Ritchie Young. All rights reserved.
|
4
|
+
#
|
5
|
+
# This file is part of RubySync.
|
6
|
+
#
|
7
|
+
# RubySync is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
|
8
|
+
# as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# RubySync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
11
|
+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License along with RubySync; if not, write to the
|
14
|
+
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
15
|
+
|
16
|
+
|
17
|
+
lib_path = File.dirname(__FILE__) + '/../lib'
|
18
|
+
$:.unshift lib_path unless $:.include?(lib_path) || $:.include?(File.expand_path(lib_path))
|
19
|
+
|
20
|
+
require 'ruby_sync'
|
21
|
+
require 'test/unit'
|
22
|
+
|
23
|
+
RIGHT = "this is right"
|
24
|
+
WRONG = "this is wrong"
|
25
|
+
|
26
|
+
class A
|
27
|
+
include RubySync::Utilities
|
28
|
+
|
29
|
+
option :just_one
|
30
|
+
option :pet, :just_default, :with_default
|
31
|
+
just_default RIGHT
|
32
|
+
with_default WRONG
|
33
|
+
end
|
34
|
+
|
35
|
+
class B < A
|
36
|
+
pet RIGHT
|
37
|
+
with_default RIGHT
|
38
|
+
just_one RIGHT
|
39
|
+
end
|
40
|
+
|
41
|
+
class C < A
|
42
|
+
pet WRONG
|
43
|
+
with_default WRONG
|
44
|
+
just_one WRONG
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
class TestUtilities < Test::Unit::TestCase
|
49
|
+
|
50
|
+
def test_class_option
|
51
|
+
b = B.new
|
52
|
+
assert_equal RIGHT, b.pet
|
53
|
+
assert_equal RIGHT, b.just_default
|
54
|
+
assert_equal RIGHT, b.with_default
|
55
|
+
assert_equal RIGHT, b.just_one
|
56
|
+
c = C.new
|
57
|
+
assert_equal WRONG, c.pet
|
58
|
+
assert_equal RIGHT, c.just_default
|
59
|
+
assert_equal WRONG, c.with_default
|
60
|
+
assert_equal WRONG, c.just_one
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|