soar-registry-directory 3.0.0 → 4.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +60 -8
- data/lib/soar/registry/directory/error.rb +1 -0
- data/lib/soar/registry/directory/model.rb +6 -1
- data/lib/soar/registry/directory/provider/dynamo_db.rb +63 -42
- data/lib/soar/registry/directory/provider/ldap.rb +73 -47
- data/lib/soar/registry/directory/provider/mysql.rb +116 -0
- data/lib/soar/registry/directory/provider/stub.rb +37 -17
- data/lib/soar/registry/directory/test/fixtures/data-dump.sql +91 -0
- data/lib/soar/registry/directory/test/orchestrator.rb +9 -0
- data/lib/soar/registry/directory/test/provider/dynamo_db.rb +33 -7
- data/lib/soar/registry/directory/test/provider/ldap.rb +38 -9
- data/lib/soar/registry/directory/test/provider/mysql.rb +137 -0
- data/lib/soar/registry/directory/test/provider/stub.rb +29 -7
- metadata +22 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c1833707950e957a90a1f7e4efe9b4694d74b93
|
4
|
+
data.tar.gz: 88ca6da07fd9378960eb968d8abe22c61da0a196
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a46377eb1b9158b9717c99e020f12843578ae880ce2a7b4489f4bf8748bde02b6620206ba1005a23d4218bdbc48d25284e2946097917bcca2d204e398135cbc1
|
7
|
+
data.tar.gz: 65254344d7334aa49ae4c03ea70de0d1faa18544a9cb9c02fa5138ea149feb42d6a782f81f52cbfdfedfd8179a1cba4410c3fcd09692cdda0da8781392ec36c2
|
data/README.md
CHANGED
@@ -43,14 +43,41 @@ Create an instance of the stub provider by passing in the name, primary key and
|
|
43
43
|
|
44
44
|
```
|
45
45
|
|
46
|
+
### MySQL/MariaDB Provider
|
47
|
+
|
48
|
+
Requires libmysqlclient-dev before running bundler.
|
49
|
+
```bash
|
50
|
+
$ sudo apt-get install libmysqlclient-dev
|
51
|
+
```
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
> provider = Soar::Registry::Directory::Provider::Mysql.new({
|
55
|
+
index: ['Client_Number', 'Notifyemail_Invoice', 'Login'],
|
56
|
+
config: {
|
57
|
+
database: 'konsoleh_genie'
|
58
|
+
table: 'Client'
|
59
|
+
host: '0.0.0.0'
|
60
|
+
port: 3306
|
61
|
+
},
|
62
|
+
attributes: ['Client_Number', 'Notifyemail_Invoice'],
|
63
|
+
credentials: {
|
64
|
+
username: 'genie'
|
65
|
+
password: 'secret'
|
66
|
+
}
|
67
|
+
})
|
68
|
+
```
|
69
|
+
|
70
|
+
Please note: The mysql dump of the genie database structure is out of date. Updating it should probably be automated. Since the directory is currently only used to search for Client_Number, it's not a priority.
|
71
|
+
|
46
72
|
### LDAP Provider
|
73
|
+
|
47
74
|
```ruby
|
48
75
|
> provider = Soar::Registry::Directory::Provider::Ldap.new({
|
49
76
|
base: 'dc=hetzner,dc=co,dc=za',
|
50
77
|
index: [:entryuuid, :mail],
|
51
78
|
config: {
|
52
79
|
host: 'localhost',
|
53
|
-
port:
|
80
|
+
port: 636
|
54
81
|
},
|
55
82
|
attributes: ['entryuuid', 'cn', 'mail', 'sn'],
|
56
83
|
credentials: {
|
@@ -59,7 +86,17 @@ Create an instance of the stub provider by passing in the name, primary key and
|
|
59
86
|
}
|
60
87
|
})
|
61
88
|
```
|
62
|
-
Please note: Primary key is assumed to be the first element of index array.
|
89
|
+
Please note: Primary key is assumed to be the first element of index array.
|
90
|
+
|
91
|
+
Command to test secure LDAP connection from terminal.
|
92
|
+
```bash
|
93
|
+
$ ldapsearch -H ldaps://ldap2.cpt1.host-h.net:636 -x -D "genieUser=charles.mulder@hetzner.co.za,ou=people,dc=hetzner,dc=co,dc=za" -b "ou=people,dc=hetzner,dc=co,dc=za" -s sub "(objectclass=*)" -W -v -d 5
|
94
|
+
```
|
95
|
+
|
96
|
+
Command to test LDAP connection from terminal.
|
97
|
+
```bash
|
98
|
+
$ ldapsearch -h ldapadmin.hetzner.co.za -p 389 -x -D "genieUser=charles.mulder@hetzner.co.za,ou=people,dc=hetzner,dc=co,dc=za" -b "dc=hetzner,dc=co,dc=za" -W
|
99
|
+
```
|
63
100
|
|
64
101
|
### The Model
|
65
102
|
```ruby
|
@@ -77,8 +114,8 @@ $ cucumber
|
|
77
114
|
|
78
115
|
#### CI
|
79
116
|
```bash
|
80
|
-
docker-compose --file docker-compose.stub.yml up --abort-on-container-exit --remove-orphans --build --force-recreate
|
81
|
-
EXIT_CODE=$(docker ps -a -f "name=
|
117
|
+
docker-compose --file docker-compose.stub.yml --project-name soar-registry-directory-provider-stub up --abort-on-container-exit --remove-orphans --build --force-recreate
|
118
|
+
EXIT_CODE=$(docker ps -a -f "name=soarregistrydirectoryproviderstub_tests" -q | xargs docker inspect -f "{{ .State.ExitCode }}")
|
82
119
|
exit $EXIT_CODE
|
83
120
|
```
|
84
121
|
|
@@ -92,8 +129,8 @@ $ CONFIG_FILE=config.dynamo_db.yml TEST_ORCHESTRATION_PROVIDER=DynamoDb cucumber
|
|
92
129
|
|
93
130
|
#### CI
|
94
131
|
```bash
|
95
|
-
docker-compose --file docker-compose.ci.dynamo_db.yml up --abort-on-container-exit --remove-orphans --build --force-recreate
|
96
|
-
EXIT_CODE=$(docker ps -a -f "name=
|
132
|
+
docker-compose --file docker-compose.ci.dynamo_db.yml --project-name soar-registry-directory-provider-dynamo_db up --abort-on-container-exit --remove-orphans --build --force-recreate
|
133
|
+
EXIT_CODE=$(docker ps -a -f "name=soarregistrydirectoryproviderdynamodb_tests" -q | xargs docker inspect -f "{{ .State.ExitCode }}")
|
97
134
|
exit $EXIT_CODE
|
98
135
|
```
|
99
136
|
|
@@ -107,8 +144,23 @@ $ CONFIG_FILE=config.ldap.yml TEST_ORCHESTRATION_PROVIDER=Ldap cucumber
|
|
107
144
|
|
108
145
|
#### CI
|
109
146
|
```bash
|
110
|
-
docker-compose --file docker-compose.ci.ldap.yml up --abort-on-container-exit --remove-orphans --build --force-recreate
|
111
|
-
EXIT_CODE=$(docker ps -a -f "name=
|
147
|
+
docker-compose --file docker-compose.ci.ldap.yml --project-name soar-registry-directory-provider-ldap up --abort-on-container-exit --remove-orphans --build --force-recreate
|
148
|
+
EXIT_CODE=$(docker ps -a -f "name=soarregistrydirectoryproviderldap_tests" -q | xargs docker inspect -f "{{ .State.ExitCode }}")
|
149
|
+
exit $EXIT_CODE
|
150
|
+
```
|
151
|
+
|
152
|
+
### MySQL provider
|
153
|
+
|
154
|
+
#### Local
|
155
|
+
```bash
|
156
|
+
$ docker-compose --file docker-compose.mysql.yml up --remove-orphans
|
157
|
+
$ CONFIG_FILE=config.mysql.yml TEST_ORCHESTRATION_PROVIDER=Mysql cucumber
|
158
|
+
```
|
159
|
+
|
160
|
+
#### CI
|
161
|
+
```bash
|
162
|
+
docker-compose --file docker-compose.ci.mysql.yml --project-name soar-registry-directory-provider-mysql up --abort-on-container-exit --remove-orphans --build --force-recreate
|
163
|
+
EXIT_CODE=$(docker ps -a -f "name=soarregistrydirectoryprovidermysql_tests" -q | xargs docker inspect -f "{{ .State.ExitCode }}")
|
112
164
|
exit $EXIT_CODE
|
113
165
|
```
|
114
166
|
|
@@ -2,6 +2,7 @@ require 'soar/registry/directory/error'
|
|
2
2
|
require 'soar/registry/directory/provider/stub'
|
3
3
|
require 'soar/registry/directory/provider/dynamo_db'
|
4
4
|
require 'soar/registry/directory/provider/ldap'
|
5
|
+
require 'soar/registry/directory/provider/mysql'
|
5
6
|
|
6
7
|
module Soar
|
7
8
|
module Registry
|
@@ -11,7 +12,7 @@ module Soar
|
|
11
12
|
attr_reader :provider
|
12
13
|
|
13
14
|
##
|
14
|
-
# @param provider [Soar::Registry::Directory::Provider::Stub
|
15
|
+
# @param provider [Soar::Registry::Directory::Provider::Stub, Soar::Registry::Directory::Provider::DynamoDb, Soar::Registry::Directory::Provider::Ldap, Soar::Registry::Directory::Provider::Mysql] object
|
15
16
|
##
|
16
17
|
def initialize(provider)
|
17
18
|
@provider = provider
|
@@ -19,6 +20,7 @@ module Soar
|
|
19
20
|
|
20
21
|
##
|
21
22
|
# @param entity [Hash]
|
23
|
+
# @raise [Soar::Registry::Directory::Error::NetworkingError]
|
22
24
|
##
|
23
25
|
def put(entity)
|
24
26
|
@provider.put(entity)
|
@@ -28,6 +30,7 @@ module Soar
|
|
28
30
|
# @param primary_key [String]
|
29
31
|
# @return [Hash] the identity
|
30
32
|
# @raise [Soar::Registry:::Directory::Error::NoEntriesFound] if primary key not found
|
33
|
+
# @raise [Soar::Registry::Directory::Error::NetworkingError]
|
31
34
|
##
|
32
35
|
def fetch(primary_key)
|
33
36
|
@provider.fetch(primary_key)
|
@@ -37,6 +40,7 @@ module Soar
|
|
37
40
|
# @param key [String] attribute name
|
38
41
|
# @param value [String] attribute value
|
39
42
|
# @return [Array] list of entries
|
43
|
+
# @raise [Soar::Registry::Directory::Error::NetworkingError]
|
40
44
|
##
|
41
45
|
def search(key, value)
|
42
46
|
@provider.search(key, value)
|
@@ -44,6 +48,7 @@ module Soar
|
|
44
48
|
|
45
49
|
##
|
46
50
|
# @return [Array] a list of primary keys and global secondary indexes
|
51
|
+
# @raise [Soar::Registry::Directory::Error::NetworkingError]
|
47
52
|
##
|
48
53
|
def index
|
49
54
|
@provider.index
|
@@ -9,7 +9,7 @@ module Soar
|
|
9
9
|
class DynamoDb
|
10
10
|
|
11
11
|
LIMIT = 10
|
12
|
-
|
12
|
+
attr_accessor :client
|
13
13
|
|
14
14
|
##
|
15
15
|
# @param credentials [Hash] { username: 'username', password: 'secret'}
|
@@ -29,10 +29,12 @@ module Soar
|
|
29
29
|
##
|
30
30
|
##
|
31
31
|
def put(entity)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
adapt_exceptions do
|
33
|
+
@client.put_item({
|
34
|
+
table_name: @table_name,
|
35
|
+
item: entity
|
36
|
+
})
|
37
|
+
end
|
36
38
|
end
|
37
39
|
|
38
40
|
##
|
@@ -41,15 +43,17 @@ module Soar
|
|
41
43
|
# @raise [Soar::Registry::Staff::Directory::DynamoDb::Error::UniqueIdentifierNotFoundError] if primary key not found
|
42
44
|
##
|
43
45
|
def fetch(primary_key)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
adapt_exceptions do
|
47
|
+
options = {
|
48
|
+
table_name: @table_name,
|
49
|
+
key: {
|
50
|
+
"#{@primary_key}": primary_key
|
51
|
+
}
|
48
52
|
}
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
+
identity = @client.get_item(options)
|
54
|
+
raise Soar::Registry::Directory::Error::NoEntriesFound, "No entries found for #{@primary_key} = #{primary_key}" if identity.item.nil?
|
55
|
+
identity.item
|
56
|
+
end
|
53
57
|
end
|
54
58
|
|
55
59
|
##
|
@@ -59,40 +63,44 @@ module Soar
|
|
59
63
|
# @raise [ArgumentError] if query or index is not specified
|
60
64
|
##
|
61
65
|
def search(key, value)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
adapt_exceptions do
|
67
|
+
options = {
|
68
|
+
table_name: @table_name,
|
69
|
+
select: 'ALL_ATTRIBUTES',
|
70
|
+
limit: LIMIT,
|
71
|
+
key_condition_expression: "#{key} = :value",
|
72
|
+
expression_attribute_values: {
|
73
|
+
":value": value
|
74
|
+
}
|
69
75
|
}
|
70
|
-
}
|
71
76
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
+
options.merge!({index_name: "#{key}-index"}) if @index.include?(key)
|
78
|
+
identity = @client.query(options)
|
79
|
+
identity.items.map { |item|
|
80
|
+
Hashie.stringify_keys(item)
|
81
|
+
}
|
82
|
+
end
|
77
83
|
end
|
78
84
|
|
79
85
|
##
|
80
86
|
# @return [Array] a list of primary keys and global secondary indexes
|
81
87
|
##
|
82
88
|
def index
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
}
|
90
|
-
resp['table']['global_secondary_indexes'].each { |index|
|
91
|
-
index['key_schema'].each { |key_schema|
|
89
|
+
adapt_exceptions do
|
90
|
+
resp = @client.describe_table({
|
91
|
+
table_name: @table_name
|
92
|
+
})
|
93
|
+
indexed_attributes = []
|
94
|
+
resp['table']['key_schema'].each { |key_schema|
|
92
95
|
indexed_attributes << key_schema['attribute_name']
|
93
96
|
}
|
94
|
-
|
95
|
-
|
97
|
+
resp['table']['global_secondary_indexes'].each { |index|
|
98
|
+
index['key_schema'].each { |key_schema|
|
99
|
+
indexed_attributes << key_schema['attribute_name']
|
100
|
+
}
|
101
|
+
}
|
102
|
+
indexed_attributes
|
103
|
+
end
|
96
104
|
end
|
97
105
|
|
98
106
|
##
|
@@ -102,12 +110,25 @@ module Soar
|
|
102
110
|
##
|
103
111
|
def recreate_table(name: nil, structure: nil)
|
104
112
|
|
105
|
-
|
106
|
-
@client.
|
107
|
-
|
108
|
-
|
113
|
+
adapt_exceptions do
|
114
|
+
if @client.list_tables.table_names.include?(name)
|
115
|
+
@client.delete_table({
|
116
|
+
table_name: name
|
117
|
+
})
|
118
|
+
end
|
119
|
+
@client.create_table(Hashie.symbolize_keys(structure))
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def adapt_exceptions
|
127
|
+
begin
|
128
|
+
yield
|
129
|
+
rescue Seahorse::Client::NetworkingError => e
|
130
|
+
raise Soar::Registry::Directory::Error::NetworkingError, e.message
|
109
131
|
end
|
110
|
-
@client.create_table(Hashie.symbolize_keys(structure))
|
111
132
|
end
|
112
133
|
|
113
134
|
end
|
@@ -8,6 +8,8 @@ module Soar
|
|
8
8
|
module Provider
|
9
9
|
class Ldap
|
10
10
|
|
11
|
+
attr_accessor :client
|
12
|
+
|
11
13
|
##
|
12
14
|
# @param config [Hash]
|
13
15
|
# @param base [String] ldap tree base eg 'dc=hetzner,dc=co,dc=za'
|
@@ -15,27 +17,34 @@ module Soar
|
|
15
17
|
# @param credentials [Hash]
|
16
18
|
##
|
17
19
|
def initialize(config: , base: , attributes: , index: , credentials: )
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
20
|
+
adapt_exceptions do
|
21
|
+
@index = index.map { |x| x.to_sym }
|
22
|
+
@attributes = attributes
|
23
|
+
@config = {
|
24
|
+
host: config[:host],
|
25
|
+
port: config[:port],
|
26
|
+
base: base,
|
27
|
+
auth: {
|
28
|
+
method: :simple,
|
29
|
+
username: credentials[:username],
|
30
|
+
password: credentials[:password]
|
31
|
+
},
|
32
|
+
encryption: {
|
33
|
+
method: :simple_tls
|
34
|
+
}
|
35
|
+
}
|
36
|
+
@client = Net::LDAP.new(@config)
|
37
|
+
@client.bind
|
38
|
+
end
|
32
39
|
end
|
33
40
|
|
34
41
|
def put(entry)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
42
|
+
adapt_exceptions do
|
43
|
+
@client.add({
|
44
|
+
dn: entry[:dn],
|
45
|
+
attributes: entry[:attributes]
|
46
|
+
})
|
47
|
+
end
|
39
48
|
end
|
40
49
|
|
41
50
|
##
|
@@ -45,19 +54,20 @@ module Soar
|
|
45
54
|
# @raise [Soar::Registry::Directory::Error::MultipleEntriesFound] if multiple matches found
|
46
55
|
##
|
47
56
|
def fetch(uuid)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
adapt_exceptions do
|
58
|
+
result = @client.search({
|
59
|
+
attributes: @attributes,
|
60
|
+
filter: Net::LDAP::Filter.eq(@index[0], uuid),
|
61
|
+
return_result: true
|
62
|
+
})
|
63
|
+
raise Soar::Registry::Directory::Error::NoEntriesFound, "No entries found for #{@index[0]} = #{uuid}" if result.empty?
|
64
|
+
raise Soar::Registry::Directory::Error::MultipleEntriesFound if result.length > 1
|
65
|
+
response = {}
|
66
|
+
@attributes.each { |attribute|
|
67
|
+
response[attribute.to_sym] = result[0][attribute.to_sym][0]
|
68
|
+
}
|
69
|
+
response
|
70
|
+
end
|
61
71
|
end
|
62
72
|
|
63
73
|
|
@@ -68,33 +78,49 @@ module Soar
|
|
68
78
|
# @raise [ArgumentError] if value or named index is not specified
|
69
79
|
##
|
70
80
|
def search(key, value)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
81
|
+
adapt_exceptions do
|
82
|
+
result = []
|
83
|
+
entries = @client.search({
|
84
|
+
filter: Net::LDAP::Filter.eq(key, value),
|
85
|
+
attributes: @attributes,
|
86
|
+
return_result: true
|
87
|
+
})
|
78
88
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
89
|
+
entries.each { |entry|
|
90
|
+
response = {}
|
91
|
+
@attributes.each { |attribute|
|
92
|
+
response[attribute.to_sym] = entry[attribute.to_sym][0]
|
93
|
+
}
|
94
|
+
result << response
|
83
95
|
}
|
84
|
-
result
|
85
|
-
|
86
|
-
return result
|
96
|
+
return result
|
97
|
+
end
|
87
98
|
end
|
88
99
|
|
89
100
|
##
|
90
101
|
# @return [Array] a list of primary keys and global secondary indexes
|
91
102
|
##
|
92
103
|
def index
|
93
|
-
|
104
|
+
adapt_exceptions do
|
105
|
+
@client.bind
|
106
|
+
@index
|
107
|
+
end
|
94
108
|
end
|
95
109
|
|
96
110
|
def delete(dn)
|
97
|
-
|
111
|
+
adapt_exceptions do
|
112
|
+
@client.delete(dn: dn)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def adapt_exceptions
|
119
|
+
begin
|
120
|
+
yield
|
121
|
+
rescue Net::LDAP::BindingInformationInvalidError, Net::LDAP::ConnectionRefusedError, Errno::ECONNREFUSED => e
|
122
|
+
raise Soar::Registry::Directory::Error::NetworkingError, e.message
|
123
|
+
end
|
98
124
|
end
|
99
125
|
|
100
126
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'soar/registry/directory/error'
|
2
|
+
require 'mysql'
|
3
|
+
|
4
|
+
module Soar
|
5
|
+
module Registry
|
6
|
+
module Directory
|
7
|
+
module Provider
|
8
|
+
class Mysql
|
9
|
+
|
10
|
+
attr_accessor :client
|
11
|
+
|
12
|
+
##
|
13
|
+
# @param config [Hash]
|
14
|
+
# @param base [String] ldap tree base eg 'dc=hetzner,dc=co,dc=za'
|
15
|
+
# @param attributes [Array] array of attributes to return for queries
|
16
|
+
# @param credentials [Hash]
|
17
|
+
##
|
18
|
+
def initialize(config: , attributes: '*', index: , credentials: )
|
19
|
+
adapt_exceptions do
|
20
|
+
@attributes = attributes.kind_of?(Array) ? attributes.join(', ') : attributes
|
21
|
+
@index = index
|
22
|
+
@table = config[:table]
|
23
|
+
@config = {
|
24
|
+
host: config[:host],
|
25
|
+
port: config[:port],
|
26
|
+
database: config[:database],
|
27
|
+
username: credentials[:username],
|
28
|
+
password: credentials[:password]
|
29
|
+
}
|
30
|
+
@client = ::Mysql.new(@config[:host], @config[:username], @config[:password], @config[:database])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def put(entry)
|
35
|
+
adapt_exceptions do
|
36
|
+
statement = @client.prepare("INSERT INTO #{@table} (#{entry.keys.join(', ')}) VALUES(#{entry.values.map { |s| "?" }.join(', ')})")
|
37
|
+
return statement.execute(*entry.values)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# @param [String] uuid primary key of the identity
|
43
|
+
# @return [Hash] the identity
|
44
|
+
# @raise [Soar::Registry::Directory::Error::NoEntriesFound] if primary key not found
|
45
|
+
# @raise [Soar::Registry::Directory::Error::MultipleEntriesFound] if multiple matches found
|
46
|
+
##
|
47
|
+
def fetch(uuid)
|
48
|
+
adapt_exceptions do
|
49
|
+
statement = @client.prepare("SELECT #{@attributes} FROM #{@table} WHERE #{@index[0]} = ? LIMIT 1")
|
50
|
+
mysql_statement = statement.execute(uuid)
|
51
|
+
raise Soar::Registry::Directory::Error::NoEntriesFound, "No entries found for #{@index[0]} = #{uuid}" if mysql_statement.num_rows == 0
|
52
|
+
mysql_result = mysql_statement.result_metadata
|
53
|
+
fields = mysql_result.fetch_fields
|
54
|
+
field_names = fields.map { |field|
|
55
|
+
field.name
|
56
|
+
}
|
57
|
+
result = mysql_statement.fetch
|
58
|
+
Hash[result.map.with_index { |value, index|
|
59
|
+
[field_names[index.to_i], value]
|
60
|
+
}].symbolize_keys
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# @param key, named index [String]
|
66
|
+
# @param value [String]
|
67
|
+
# @return [Array] list of identities
|
68
|
+
# @raise [ArgumentError] if value or named index is not specified
|
69
|
+
##
|
70
|
+
def search(key, value)
|
71
|
+
adapt_exceptions do
|
72
|
+
statement = @client.prepare("SELECT #{@attributes} FROM #{@table} WHERE #{key} = ?")
|
73
|
+
mysql_statement = statement.execute(value)
|
74
|
+
mysql_result = mysql_statement.result_metadata
|
75
|
+
fields = mysql_result.fetch_fields
|
76
|
+
field_names = fields.map { |field|
|
77
|
+
field.name
|
78
|
+
}
|
79
|
+
result = []
|
80
|
+
mysql_statement.each { |entry|
|
81
|
+
result << Hash[entry.map.with_index { |value, index|
|
82
|
+
[field_names[index.to_i], value]
|
83
|
+
}].symbolize_keys
|
84
|
+
}
|
85
|
+
result
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# @return [Array] a list of primary keys and global secondary indexes
|
91
|
+
##
|
92
|
+
def index
|
93
|
+
adapt_exceptions do
|
94
|
+
index = []
|
95
|
+
@client.query("SHOW INDEX FROM Client").each_hash { |entry|
|
96
|
+
index << entry['Column_name']
|
97
|
+
}
|
98
|
+
index
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def adapt_exceptions
|
105
|
+
begin
|
106
|
+
yield
|
107
|
+
rescue ::Mysql::Error => e
|
108
|
+
raise Soar::Registry::Directory::Error::NetworkingError, e.message
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -9,25 +9,26 @@ module Soar
|
|
9
9
|
module Provider
|
10
10
|
class Stub
|
11
11
|
|
12
|
-
@@interface = Mince::HashyDb::Interface
|
13
|
-
|
14
12
|
##
|
15
13
|
# @param table [String] table name
|
16
14
|
# @param primary_key [String]
|
17
15
|
# @param index [Array] primary key should be the first item
|
18
16
|
##
|
19
17
|
def initialize(table: , index: )
|
18
|
+
@interface = Mince::HashyDb::Interface
|
20
19
|
@table = table
|
21
20
|
@primary_key = index[0]
|
22
21
|
@index = index
|
23
|
-
|
22
|
+
@interface.clear
|
24
23
|
end
|
25
24
|
|
26
25
|
##
|
27
26
|
# @param entity [Hash]
|
28
27
|
##
|
29
28
|
def put(entity)
|
30
|
-
|
29
|
+
adapt_exceptions do
|
30
|
+
@interface.add(@table, entity)
|
31
|
+
end
|
31
32
|
end
|
32
33
|
|
33
34
|
##
|
@@ -36,9 +37,11 @@ module Soar
|
|
36
37
|
# @raise [Soar::Registry:::Directory::Error::NoEntriesFound] if primary key not found
|
37
38
|
##
|
38
39
|
def fetch(primary_key)
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
adapt_exceptions do
|
41
|
+
entry = @interface.get_for_key_with_value(@table, @primary_key, primary_key)
|
42
|
+
raise Soar::Registry::Directory::Error::NoEntriesFound, "No entries found for #{@primary_key} = #{primary_key}" if entry.nil?
|
43
|
+
entry
|
44
|
+
end
|
42
45
|
end
|
43
46
|
|
44
47
|
##
|
@@ -48,23 +51,40 @@ module Soar
|
|
48
51
|
# @raise [ArgumentError] if query or index is not specified
|
49
52
|
##
|
50
53
|
def search(key, value)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
54
|
+
adapt_exceptions do
|
55
|
+
identities = []
|
56
|
+
@interface.find_all(@table).each { |identity|
|
57
|
+
if identity[key] == value
|
58
|
+
identities << identity
|
59
|
+
else
|
60
|
+
next
|
61
|
+
end
|
62
|
+
}
|
63
|
+
identities
|
64
|
+
end
|
60
65
|
end
|
61
66
|
|
62
67
|
##
|
63
68
|
# @return [Array] a list of primary keys and global secondary indexes
|
64
69
|
##
|
65
70
|
def index
|
66
|
-
|
71
|
+
adapt_exceptions do
|
72
|
+
[@interface.primary_key.to_s]
|
73
|
+
@index
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def adapt_exceptions
|
81
|
+
begin
|
82
|
+
yield
|
83
|
+
rescue NoMethodError => e
|
84
|
+
raise Soar::Registry::Directory::Error::NetworkingError, 'Networking error'
|
85
|
+
end
|
67
86
|
end
|
87
|
+
|
68
88
|
end
|
69
89
|
|
70
90
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
DROP TABLE IF EXISTS `Client`;
|
2
|
+
CREATE TABLE `Client` (
|
3
|
+
`ID` int(11) NOT NULL AUTO_INCREMENT,
|
4
|
+
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
5
|
+
`Client_Number` varchar(15) NOT NULL DEFAULT '',
|
6
|
+
`Privil` varchar(15) NOT NULL DEFAULT '',
|
7
|
+
`Active` enum('0','1') NOT NULL DEFAULT '0',
|
8
|
+
`ActiveUntil` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
9
|
+
`MaxDomains` int(11) NOT NULL DEFAULT '100',
|
10
|
+
`Title` varchar(10) DEFAULT NULL,
|
11
|
+
`First_Name` varchar(70) DEFAULT NULL,
|
12
|
+
`Surname` varchar(70) DEFAULT NULL,
|
13
|
+
`Company` varchar(70) DEFAULT NULL,
|
14
|
+
`Street` varchar(70) DEFAULT NULL,
|
15
|
+
`Postal_Code` varchar(10) DEFAULT NULL,
|
16
|
+
`Suburb` varchar(70) NOT NULL DEFAULT '',
|
17
|
+
`Country` varchar(70) NOT NULL DEFAULT '0',
|
18
|
+
`City` varchar(70) NOT NULL DEFAULT '',
|
19
|
+
`CountryGroup` enum('0','1','2') NOT NULL DEFAULT '0',
|
20
|
+
`Telephone` varchar(50) DEFAULT NULL,
|
21
|
+
`Cellphone` varchar(50) NOT NULL DEFAULT '',
|
22
|
+
`ID_Number` varchar(30) DEFAULT NULL,
|
23
|
+
`Date_Of_Birth` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
24
|
+
`Fax` varchar(50) DEFAULT NULL,
|
25
|
+
`RipeHandle` varchar(16) NOT NULL DEFAULT '',
|
26
|
+
`Login` varchar(15) DEFAULT NULL,
|
27
|
+
`Password` varchar(30) DEFAULT NULL,
|
28
|
+
`FromEmail1` varchar(40) NOT NULL DEFAULT '',
|
29
|
+
`FromEmail2` varchar(40) DEFAULT NULL,
|
30
|
+
`FromEmail3` varchar(40) DEFAULT NULL,
|
31
|
+
`PublicKey` mediumtext NOT NULL,
|
32
|
+
`Newsletter` enum('0','1') NOT NULL DEFAULT '0',
|
33
|
+
`Notice` enum('0','1') NOT NULL DEFAULT '1',
|
34
|
+
`Notifyemail` varchar(100) DEFAULT NULL,
|
35
|
+
`Notifyemail_Robot` varchar(100) NOT NULL DEFAULT '',
|
36
|
+
`Notifyemail_Traffic` varchar(100) DEFAULT NULL,
|
37
|
+
`Notifyemail_Invoice` text,
|
38
|
+
`FreeTraffic` decimal(4,2) DEFAULT NULL,
|
39
|
+
`Bank_Branch_Code` varchar(8) DEFAULT NULL,
|
40
|
+
`Bank_Account_Number` varchar(30) DEFAULT NULL,
|
41
|
+
`Bank_Account_Holder` varchar(60) DEFAULT NULL,
|
42
|
+
`Bank_Account_Type` enum('0','1','2','3','4','5') NOT NULL DEFAULT '0',
|
43
|
+
`Bank_Name` varchar(60) NOT NULL DEFAULT '',
|
44
|
+
`Bank_Branch_Location` varchar(60) NOT NULL DEFAULT '',
|
45
|
+
`Reseller` enum('0','1') NOT NULL DEFAULT '0',
|
46
|
+
`Reseller_Proof` varchar(60) NOT NULL DEFAULT '',
|
47
|
+
`CreditCardNumber` varchar(30) NOT NULL DEFAULT '',
|
48
|
+
`CreditCardExpiration` varchar(6) NOT NULL DEFAULT '',
|
49
|
+
`CreditCardName` varchar(15) NOT NULL DEFAULT '',
|
50
|
+
`payment_method` enum('Unspecified','Cash','Debit Order') NOT NULL DEFAULT 'Unspecified',
|
51
|
+
`Mother_ID` varchar(12) NOT NULL DEFAULT '',
|
52
|
+
`ChargeVAT` enum('0','1') NOT NULL DEFAULT '1',
|
53
|
+
`Summary_Invoice` enum('0','1') NOT NULL DEFAULT '0',
|
54
|
+
`Separate_Invoice` enum('0','1') NOT NULL DEFAULT '0',
|
55
|
+
`Email_Format` enum('0','1','2','3') NOT NULL DEFAULT '1',
|
56
|
+
`Dedi_Graph` enum('0','1') NOT NULL DEFAULT '1',
|
57
|
+
`TaxID` varchar(20) NOT NULL DEFAULT '',
|
58
|
+
`Discount` decimal(4,2) DEFAULT NULL,
|
59
|
+
`ChargeRobotSetup` enum('0','1','2') DEFAULT NULL,
|
60
|
+
`ClientCreated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
61
|
+
`Comment` text,
|
62
|
+
`Advice` mediumtext NOT NULL,
|
63
|
+
`Vat_Number` varchar(30) DEFAULT NULL,
|
64
|
+
`Rejection_Counter` tinyint(11) DEFAULT '0',
|
65
|
+
`Marketing` enum('Print','Brainstorm','ComputerActive','Google','ITWeb','Mouth','Website','Search','Designer','Hetzner','Other','SA Computer Magazine','Entrepreneur Magazine','Financial Mail') DEFAULT NULL,
|
66
|
+
`Marketing_other` mediumtext,
|
67
|
+
`Billing_First_Name` varchar(70) NOT NULL DEFAULT '',
|
68
|
+
`Billing_Surname` varchar(70) NOT NULL DEFAULT '',
|
69
|
+
`Billing_Telephone` varchar(50) NOT NULL DEFAULT '',
|
70
|
+
`Billing_Cellphone` varchar(50) NOT NULL DEFAULT '',
|
71
|
+
`Tech_First_Name` varchar(70) NOT NULL DEFAULT '',
|
72
|
+
`Tech_Surname` varchar(70) NOT NULL DEFAULT '',
|
73
|
+
`Notifyemail_Tech` varchar(100) NOT NULL DEFAULT '',
|
74
|
+
`Tech_Telephone` varchar(50) NOT NULL DEFAULT '',
|
75
|
+
`Tech_Cellphone` varchar(50) NOT NULL DEFAULT '',
|
76
|
+
`Verified` enum('0','1') NOT NULL DEFAULT '1',
|
77
|
+
`mass_update_notification_sent` enum('1','2','3','more','no') NOT NULL DEFAULT 'no',
|
78
|
+
`mass_update_submission_sent` enum('yes','no') NOT NULL DEFAULT 'no',
|
79
|
+
`contact_Confirmed` enum('True','False') NOT NULL DEFAULT 'True',
|
80
|
+
`is_test_profile` enum('0','1') DEFAULT '0',
|
81
|
+
`Google` enum('None','Eligible','Emailed','Issued') NOT NULL DEFAULT 'None',
|
82
|
+
`Google_Value_ID` int(11) NOT NULL DEFAULT '0',
|
83
|
+
`Google_Expiry` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
84
|
+
`app_installer_active` tinyint(1) DEFAULT '1',
|
85
|
+
PRIMARY KEY (`ID`),
|
86
|
+
KEY `Login` (`Login`),
|
87
|
+
KEY `Password` (`Password`),
|
88
|
+
KEY `Notifyemail_Invoice` (`Notifyemail_Invoice`(20)),
|
89
|
+
KEY `Client_Number` (`Client_Number`)
|
90
|
+
) ENGINE=InnoDB AUTO_INCREMENT=185532 DEFAULT CHARSET=latin1;
|
91
|
+
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'soar/registry/directory/test/provider/stub'
|
2
|
+
require 'soar/registry/directory/test/provider/mysql'
|
2
3
|
require 'soar/registry/directory/test/provider/dynamo_db'
|
3
4
|
require 'soar/registry/directory/test/provider/ldap'
|
4
5
|
|
@@ -21,6 +22,10 @@ module Soar
|
|
21
22
|
@provider.given_configured_directory
|
22
23
|
end
|
23
24
|
|
25
|
+
def sabotage_network
|
26
|
+
@provider.sabotage_network
|
27
|
+
end
|
28
|
+
|
24
29
|
def put_entry
|
25
30
|
@provider.put_entry
|
26
31
|
end
|
@@ -61,6 +66,10 @@ module Soar
|
|
61
66
|
@provider.no_matching_entries?
|
62
67
|
end
|
63
68
|
|
69
|
+
def networking_error?
|
70
|
+
@provider.networking_error?
|
71
|
+
end
|
72
|
+
|
64
73
|
end
|
65
74
|
end
|
66
75
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'soar/registry/directory'
|
2
|
+
require 'aws-sdk'
|
3
|
+
require 'hashie'
|
4
|
+
require 'soar/registry/directory/error'
|
2
5
|
|
3
6
|
module Soar
|
4
7
|
module Registry
|
@@ -8,6 +11,7 @@ module Soar
|
|
8
11
|
class DynamoDb
|
9
12
|
|
10
13
|
def initialize
|
14
|
+
@retries = 5
|
11
15
|
@configuration = YAML.load_file("config/#{ENV['CONFIG_FILE']}")
|
12
16
|
@table = @configuration['provider']['table']['name']
|
13
17
|
@index = @configuration['provider']['table']['index']
|
@@ -34,23 +38,41 @@ module Soar
|
|
34
38
|
}
|
35
39
|
end
|
36
40
|
|
41
|
+
def sabotage_network
|
42
|
+
@configuration['provider']['config'][:credentials] = Aws::Credentials.new(@configuration['provider']['credentials']['username'], @configuration['provider']['credentials']['password'])
|
43
|
+
@configuration['provider']['config']['endpoint'] = 'http://does-not-exist'
|
44
|
+
@directory.provider.client = Aws::DynamoDB::Client.new(Hashie.symbolize_keys(@configuration['provider']['config']))
|
45
|
+
end
|
46
|
+
|
37
47
|
def put_entry
|
38
|
-
|
48
|
+
begin
|
49
|
+
@directory.put(@entries[0])
|
50
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
51
|
+
@error = e.message
|
52
|
+
end
|
39
53
|
end
|
40
54
|
|
41
55
|
def search_for_entry
|
42
|
-
|
56
|
+
begin
|
57
|
+
@result = @directory.search("email", @entries[0]['email'])
|
58
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
59
|
+
@error = e.message
|
60
|
+
end
|
43
61
|
end
|
44
62
|
|
45
63
|
def request_index
|
46
|
-
|
64
|
+
begin
|
65
|
+
@result = @directory.index
|
66
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
67
|
+
@error = e.message
|
68
|
+
end
|
47
69
|
end
|
48
70
|
|
49
71
|
def fetch_entry
|
50
72
|
begin
|
51
73
|
@result = @directory.fetch(@entries[0]['uuid'])
|
52
|
-
rescue Soar::Registry::Directory::Error::NoEntriesFound
|
53
|
-
@error =
|
74
|
+
rescue Soar::Registry::Directory::Error::NoEntriesFound, Soar::Registry::Directory::Error::NetworkingError => e
|
75
|
+
@error = e.message
|
54
76
|
end
|
55
77
|
end
|
56
78
|
|
@@ -63,7 +85,7 @@ module Soar
|
|
63
85
|
end
|
64
86
|
|
65
87
|
def index?
|
66
|
-
@
|
88
|
+
@index
|
67
89
|
end
|
68
90
|
|
69
91
|
def single_entry?
|
@@ -71,7 +93,11 @@ module Soar
|
|
71
93
|
end
|
72
94
|
|
73
95
|
def no_entries_found?
|
74
|
-
@error
|
96
|
+
!!(@error =~ /\ANo entries found for .+\z/)
|
97
|
+
end
|
98
|
+
|
99
|
+
def networking_error?
|
100
|
+
!!(@error =~ /\AFailed to open TCP connection to .+\z/)
|
75
101
|
end
|
76
102
|
|
77
103
|
def no_matching_entries?
|
@@ -52,25 +52,50 @@ module Soar
|
|
52
52
|
}
|
53
53
|
end
|
54
54
|
|
55
|
+
def sabotage_network
|
56
|
+
@directory.provider.client = Net::LDAP.new({
|
57
|
+
host: 'localhost',
|
58
|
+
port: @configuration['provider']['config']['config']['port'],
|
59
|
+
auth: {
|
60
|
+
method: :simple,
|
61
|
+
username: @configuration['provider']['config']['credentials']['username'],
|
62
|
+
password: @configuration['provider']['config']['credentials']['password']
|
63
|
+
}
|
64
|
+
})
|
65
|
+
|
66
|
+
end
|
67
|
+
|
55
68
|
def put_entry
|
56
|
-
|
57
|
-
|
58
|
-
|
69
|
+
begin
|
70
|
+
@directory.put(@entries[0])
|
71
|
+
result = @directory.search("mail", @entries[0][:attributes][:mail])
|
72
|
+
@entries[0][:attributes][:entryuuid] = result[0][@index[0]]
|
73
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
74
|
+
@error = e.message
|
75
|
+
end
|
59
76
|
end
|
60
77
|
|
61
78
|
def search_for_entry
|
62
|
-
|
79
|
+
begin
|
80
|
+
@result = @directory.search("mail", @entries[0][:attributes][:mail])
|
81
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
82
|
+
@error = e.message
|
83
|
+
end
|
63
84
|
end
|
64
85
|
|
65
86
|
def request_index
|
66
|
-
|
87
|
+
begin
|
88
|
+
@result = @directory.index
|
89
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
90
|
+
@error = e.message
|
91
|
+
end
|
67
92
|
end
|
68
93
|
|
69
94
|
def fetch_entry
|
70
95
|
begin
|
71
96
|
@result = @directory.fetch(@entries[0][:attributes][:entryuuid])
|
72
|
-
rescue Soar::Registry::Directory::Error::NoEntriesFound
|
73
|
-
@error =
|
97
|
+
rescue Soar::Registry::Directory::Error::NoEntriesFound, Soar::Registry::Directory::Error::NetworkingError => e
|
98
|
+
@error = e.message
|
74
99
|
end
|
75
100
|
end
|
76
101
|
|
@@ -88,7 +113,7 @@ module Soar
|
|
88
113
|
end
|
89
114
|
|
90
115
|
def index?
|
91
|
-
@
|
116
|
+
@index
|
92
117
|
end
|
93
118
|
|
94
119
|
def single_entry?
|
@@ -98,13 +123,17 @@ module Soar
|
|
98
123
|
end
|
99
124
|
|
100
125
|
def no_entries_found?
|
101
|
-
@error
|
126
|
+
!!(@error =~ /\ANo entries found for .+\z/)
|
102
127
|
end
|
103
128
|
|
104
129
|
def no_matching_entries?
|
105
130
|
@result == []
|
106
131
|
end
|
107
132
|
|
133
|
+
def networking_error?
|
134
|
+
!!(@error =~ /\A(Invalid binding information|Connection refused).*\z/)
|
135
|
+
end
|
136
|
+
|
108
137
|
end
|
109
138
|
end
|
110
139
|
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'soar/registry/directory'
|
2
|
+
require 'mysql'
|
3
|
+
# http://zetcode.com/db/mysqlrubytutorial/
|
4
|
+
|
5
|
+
module Soar
|
6
|
+
module Registry
|
7
|
+
module Directory
|
8
|
+
module Test
|
9
|
+
module Provider
|
10
|
+
class Mysql
|
11
|
+
|
12
|
+
PATH_TO_DATABASE_STRUCTURE_DUMP = "lib/soar/registry/directory/test/fixtures/data-dump.sql"
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@configuration = YAML.load_file("config/#{ENV['CONFIG_FILE']}")
|
16
|
+
@index = @configuration['provider']['config']['index']
|
17
|
+
@attributes = @configuration['provider']['config']['attributes']
|
18
|
+
@entries = [{
|
19
|
+
Client_Number: "C123456789",
|
20
|
+
Notifyemail_Invoice: "johnconner@example.com"
|
21
|
+
}, {
|
22
|
+
Client_Number: "C101112134",
|
23
|
+
Notifyemail_Invoice: "sarahconnor@example.com"
|
24
|
+
}]
|
25
|
+
end
|
26
|
+
|
27
|
+
def given_configured_directory
|
28
|
+
recreate_table({
|
29
|
+
host: @configuration['provider']['config']['config']['host'],
|
30
|
+
username: @configuration['provider']['config']['credentials']['username'],
|
31
|
+
password: @configuration['provider']['config']['credentials']['password'],
|
32
|
+
filepath: PATH_TO_DATABASE_STRUCTURE_DUMP
|
33
|
+
})
|
34
|
+
provider_class = Object.const_get(@configuration['provider']['class'])
|
35
|
+
provider = provider_class.new(Hashie.symbolize_keys(@configuration['provider']['config']))
|
36
|
+
@directory = Soar::Registry::Directory.new(provider)
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Adds @entries to datastore using ldap protocol
|
41
|
+
# Adds entryuuid to @entries
|
42
|
+
##
|
43
|
+
def given_existing_data
|
44
|
+
@entries.each{ |entry|
|
45
|
+
@directory.put(entry)
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def sabotage_network
|
50
|
+
@directory.provider.client.close
|
51
|
+
end
|
52
|
+
|
53
|
+
def put_entry
|
54
|
+
begin
|
55
|
+
@directory.put(@entries[0])
|
56
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
57
|
+
@error = e.message
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def search_for_entry
|
62
|
+
begin
|
63
|
+
@result = @directory.search("Notifyemail_Invoice", @entries[0][:Notifyemail_Invoice])
|
64
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
65
|
+
@error = e.message
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def request_index
|
70
|
+
begin
|
71
|
+
@result = @directory.index
|
72
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
73
|
+
@error = e.message
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def fetch_entry
|
78
|
+
begin
|
79
|
+
@result = @directory.fetch(@entries[0][:Client_Number])
|
80
|
+
rescue Soar::Registry::Directory::Error::NoEntriesFound, Soar::Registry::Directory::Error::NetworkingError => e
|
81
|
+
@error = e.message
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def persisted?
|
86
|
+
@directory.fetch(@entries[0][:Client_Number]) == @entries[0]
|
87
|
+
end
|
88
|
+
|
89
|
+
def returned?
|
90
|
+
@result == [@entries[0]]
|
91
|
+
end
|
92
|
+
|
93
|
+
def index?
|
94
|
+
@result
|
95
|
+
end
|
96
|
+
|
97
|
+
def single_entry?
|
98
|
+
@result == @entries[0]
|
99
|
+
end
|
100
|
+
|
101
|
+
def no_entries_found?
|
102
|
+
!!(@error =~ /\ANo entries found for .+\z/)
|
103
|
+
end
|
104
|
+
|
105
|
+
def no_matching_entries?
|
106
|
+
@result == []
|
107
|
+
end
|
108
|
+
|
109
|
+
def networking_error?
|
110
|
+
patterns = [
|
111
|
+
/\Aquery: not connected.*\z/,
|
112
|
+
/\AMySQL server has gone away\z/,
|
113
|
+
/\ACan't connect to local MySQL server through socket.*\z/,
|
114
|
+
/\AERROR 2003 (HY000): Can't connect to MySQL server on.*\z/,
|
115
|
+
/\ALost connection to MySQL server.*\z/
|
116
|
+
]
|
117
|
+
patterns.any? { |pattern|
|
118
|
+
break true if !!(@error =~ pattern)
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
##
|
125
|
+
# Execute command using mysql client on terminal
|
126
|
+
##
|
127
|
+
def recreate_table(host:, username:, password:, filepath:)
|
128
|
+
`mysql -h #{host} -u#{username} -p#{password} konsoleh_genie < '#{filepath}'`
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'soar/registry/directory'
|
2
|
+
require 'mince'
|
3
|
+
require 'hashy_db'
|
2
4
|
|
3
5
|
module Soar
|
4
6
|
module Registry
|
@@ -26,23 +28,39 @@ module Soar
|
|
26
28
|
@directory.put(@@entry)
|
27
29
|
end
|
28
30
|
|
31
|
+
def sabotage_network
|
32
|
+
@directory.provider.instance_variable_set(:@interface, Object.new)
|
33
|
+
end
|
34
|
+
|
29
35
|
def put_entry
|
30
|
-
|
36
|
+
begin
|
37
|
+
@directory.put(@@entry)
|
38
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
39
|
+
@error = e.message
|
40
|
+
end
|
31
41
|
end
|
32
42
|
|
33
43
|
def search_for_entry
|
34
|
-
|
44
|
+
begin
|
45
|
+
@entry = @directory.search("identifier", @@entry['identifier'])
|
46
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
47
|
+
@error = e.message
|
48
|
+
end
|
35
49
|
end
|
36
50
|
|
37
51
|
def request_index
|
38
|
-
|
52
|
+
begin
|
53
|
+
@index = @directory.index
|
54
|
+
rescue Soar::Registry::Directory::Error::NetworkingError => e
|
55
|
+
@error = e.message
|
56
|
+
end
|
39
57
|
end
|
40
58
|
|
41
59
|
def fetch_entry
|
42
60
|
begin
|
43
61
|
@entry = @directory.fetch(@@entry['uuid'])
|
44
|
-
rescue Soar::Registry::Directory::Error::NoEntriesFound
|
45
|
-
@error =
|
62
|
+
rescue Soar::Registry::Directory::Error::NoEntriesFound, Soar::Registry::Directory::Error::NetworkingError => e
|
63
|
+
@error = e.message
|
46
64
|
end
|
47
65
|
end
|
48
66
|
|
@@ -55,7 +73,7 @@ module Soar
|
|
55
73
|
end
|
56
74
|
|
57
75
|
def index?
|
58
|
-
@index
|
76
|
+
@index
|
59
77
|
end
|
60
78
|
|
61
79
|
def single_entry?
|
@@ -63,13 +81,17 @@ module Soar
|
|
63
81
|
end
|
64
82
|
|
65
83
|
def no_entries_found?
|
66
|
-
@error
|
84
|
+
!!(@error =~ /\ANo entries found for .+\z/)
|
67
85
|
end
|
68
86
|
|
69
87
|
def no_matching_entries?
|
70
88
|
@entry == []
|
71
89
|
end
|
72
90
|
|
91
|
+
def networking_error?
|
92
|
+
!!(@error =~ /\ANetworking error\z/)
|
93
|
+
end
|
94
|
+
|
73
95
|
end
|
74
96
|
end
|
75
97
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: soar-registry-directory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Mulder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashy_db
|
@@ -59,59 +59,59 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 2.6.6
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: hashie
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
67
|
+
version: '3.4'
|
68
68
|
- - ">="
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version:
|
70
|
+
version: 3.4.6
|
71
71
|
type: :runtime
|
72
72
|
prerelease: false
|
73
73
|
version_requirements: !ruby/object:Gem::Requirement
|
74
74
|
requirements:
|
75
75
|
- - "~>"
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: '
|
77
|
+
version: '3.4'
|
78
78
|
- - ">="
|
79
79
|
- !ruby/object:Gem::Version
|
80
|
-
version:
|
80
|
+
version: 3.4.6
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
|
-
name:
|
82
|
+
name: net-ldap
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
84
84
|
requirements:
|
85
85
|
- - "~>"
|
86
86
|
- !ruby/object:Gem::Version
|
87
|
-
version:
|
88
|
-
- - ">="
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
version: 3.4.6
|
87
|
+
version: 0.15.0
|
91
88
|
type: :runtime
|
92
89
|
prerelease: false
|
93
90
|
version_requirements: !ruby/object:Gem::Requirement
|
94
91
|
requirements:
|
95
92
|
- - "~>"
|
96
93
|
- !ruby/object:Gem::Version
|
97
|
-
version:
|
98
|
-
- - ">="
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
version: 3.4.6
|
94
|
+
version: 0.15.0
|
101
95
|
- !ruby/object:Gem::Dependency
|
102
|
-
name:
|
96
|
+
name: mysql
|
103
97
|
requirement: !ruby/object:Gem::Requirement
|
104
98
|
requirements:
|
105
99
|
- - "~>"
|
106
100
|
- !ruby/object:Gem::Version
|
107
|
-
version:
|
101
|
+
version: '2.9'
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 2.9.1
|
108
105
|
type: :runtime
|
109
106
|
prerelease: false
|
110
107
|
version_requirements: !ruby/object:Gem::Requirement
|
111
108
|
requirements:
|
112
109
|
- - "~>"
|
113
110
|
- !ruby/object:Gem::Version
|
114
|
-
version:
|
111
|
+
version: '2.9'
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 2.9.1
|
115
115
|
description: Directories for soar registries
|
116
116
|
email: charles.mulder@hetzner.co.za
|
117
117
|
executables: []
|
@@ -124,13 +124,16 @@ files:
|
|
124
124
|
- lib/soar/registry/directory/model.rb
|
125
125
|
- lib/soar/registry/directory/provider/dynamo_db.rb
|
126
126
|
- lib/soar/registry/directory/provider/ldap.rb
|
127
|
+
- lib/soar/registry/directory/provider/mysql.rb
|
127
128
|
- lib/soar/registry/directory/provider/stub.rb
|
129
|
+
- lib/soar/registry/directory/test/fixtures/data-dump.sql
|
128
130
|
- lib/soar/registry/directory/test/fixtures/entries.json
|
129
131
|
- lib/soar/registry/directory/test/fixtures/entries.ldif
|
130
132
|
- lib/soar/registry/directory/test/fixtures/table_structure.json
|
131
133
|
- lib/soar/registry/directory/test/orchestrator.rb
|
132
134
|
- lib/soar/registry/directory/test/provider/dynamo_db.rb
|
133
135
|
- lib/soar/registry/directory/test/provider/ldap.rb
|
136
|
+
- lib/soar/registry/directory/test/provider/mysql.rb
|
134
137
|
- lib/soar/registry/directory/test/provider/stub.rb
|
135
138
|
homepage: https://gitlab.host-h.net/registries/directory
|
136
139
|
licenses:
|