soar-registry-directory 3.0.0 → 4.0.3
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.
- 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:
|