soar-registry-directory 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 74f2f96f3112e94b32dbdf1df3158d4a7c90c243
4
+ data.tar.gz: bc374da550aeac5dfb1141a3e306aa6d3c2e0bbc
5
+ SHA512:
6
+ metadata.gz: c685cac5ebf8519e8115d4f3fbb96860c3221caf1f01a4f60600e4700201f9effc54bd73cbe4fb80b1d0c8f493526f556ca59c720fd28f8db8260e81b01f2401
7
+ data.tar.gz: 598ec60e756b7a7d185d679632c7ea1649fee116d6e78d7792956ff1c824a277790fa9fedd9d3fe45dbe6e8fe33517549dacc0da999211ae42248c3eaa652f03
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Soar::Registry::Directory
2
+
3
+ Directory model and providers used by soar registries
4
+
5
+ ## Quick start
6
+
7
+ ### Example data
8
+
9
+ ```json
10
+ "mytable": [{
11
+ "uuid": "1",
12
+ "email": "test1@example.com"
13
+ }, {
14
+ "uuid": "2",
15
+ "email": "test2@example.com"
16
+ }]
17
+
18
+ ```
19
+
20
+ ### Stub provider
21
+ Create an instance of the stub provider by passing in the name, primary key and indexes of your table.
22
+ ```ruby
23
+ > require 'soar/registry/directory'
24
+ > provider = Soar::Registry::Directory::Provider::Stub.new({
25
+ table: "mytable",
26
+ primary_key: "uuid",
27
+ index: ["uuid", "email"]
28
+ })
29
+ ```
30
+ ### DynamodDb Provider
31
+ ```ruby
32
+ > provider = Soar::Registry::Directory::Provider::DynamoDb.new({
33
+ credentials: {
34
+ username: "username",
35
+ password: "secret"
36
+ },
37
+ table: "mytable",
38
+ index: ['uuid', 'email'],
39
+ primary_key: "uuid",
40
+ configuration: {
41
+ region: 'us-west-2'
42
+ endpoint: 'http://localhost:8000'
43
+ }
44
+ })
45
+
46
+ ```
47
+
48
+ ### The Model
49
+ ```ruby
50
+ > directory = Soar::Registry::Directory.new(provider: provider)
51
+ ```
52
+
53
+ ## Tests
54
+
55
+ ### Stub provider
56
+
57
+ #### Local
58
+ ```bash
59
+ $ cucumber
60
+ ```
61
+
62
+ #### CI
63
+ ```bash
64
+ docker-compose --file docker-compose.stub.yml up --abort-on-container-exit --remove-orphans --build --force-recreate
65
+ EXIT_CODE=$(docker ps -a -f "name=soar-registry-directory-test-provider-stub" -q | xargs docker inspect -f "{{ .State.ExitCode }}")
66
+ exit $EXIT_CODE
67
+ ```
68
+
69
+ ### DynamoDb provider
70
+
71
+ #### Local
72
+ ```bash
73
+ $ docker-compose --file docker-compose.dynamo_db.yml up
74
+ $ CONFIG_FILE=config.dynamo_db.yml TEST_PROVIDER=DynamoDb cucumber
75
+ ```
76
+
77
+ #### CI
78
+ ```bash
79
+ docker-compose --file docker-compose.ci.dynamo_db.yml up --abort-on-container-exit --remove-orphans --build --force-recreate
80
+ EXIT_CODE=$(docker ps -a -f "name=soar-registry-directory-test-provider-dynamo_db" -q | xargs docker inspect -f "{{ .State.ExitCode }}")
81
+ exit $EXIT_CODE
82
+ ```
@@ -0,0 +1,9 @@
1
+ module Soar
2
+ module Registry
3
+ module Directory
4
+ module Error
5
+ class NoEntriesFound < StandardError; end;
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,54 @@
1
+ require 'soar/registry/directory/error'
2
+ require 'soar/registry/directory/provider/stub'
3
+ require 'soar/registry/directory/provider/dynamo_db'
4
+
5
+ module Soar
6
+ module Registry
7
+ module Directory
8
+ class Model
9
+
10
+ attr_reader :provider
11
+
12
+ ##
13
+ # @param provider [Soar::Registry::Directory::Provider::Stub|Soar::Registry::Directory::Provider::DynamoDb] object
14
+ ##
15
+ def initialize(provider: nil)
16
+ @provider = provider
17
+ end
18
+
19
+ ##
20
+ # @param entity [Hash]
21
+ ##
22
+ def put(entity)
23
+ @provider.put(entity)
24
+ end
25
+
26
+ ##
27
+ # @param primary_key [String]
28
+ # @return [Hash] the identity
29
+ # @raise [Soar::Registry:::Directory::Error::NoEntriesFound] if primary key not found
30
+ ##
31
+ def fetch(primary_key)
32
+ @provider.fetch(primary_key)
33
+ end
34
+
35
+ ##
36
+ # @param key [String] attribute name
37
+ # @param value [String] attribute value
38
+ # @return [Array] list of entries
39
+ ##
40
+ def search(key, value)
41
+ @provider.search(key, value)
42
+ end
43
+
44
+ ##
45
+ # @return [Array] a list of primary keys and global secondary indexes
46
+ ##
47
+ def index
48
+ @provider.index
49
+ end
50
+
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,118 @@
1
+ require 'aws-sdk'
2
+ require 'hashie'
3
+ require 'soar/registry/directory/error'
4
+
5
+ module Soar
6
+ module Registry
7
+ module Directory
8
+ module Provider
9
+ class DynamoDb
10
+
11
+ LIMIT = 10
12
+ attr_reader :client
13
+
14
+ ##
15
+ # @param credentials [Hash] { username: 'username', password: 'secret'}
16
+ # @param table [String]
17
+ # @param primary_key [String]
18
+ # @param index [Array] primary key should be the first item
19
+ # @param configuration [Hash] { region: 'us-west-2', endpoint: 'http://localhost:8000' }
20
+ ##
21
+ def initialize(credentials: nil, table: nil, primary_key: nil, index: nil, configuration: nil)
22
+ @table_name = table
23
+ @primary_key = primary_key
24
+ @index = index
25
+ @credentials = Hashie.symbolize_keys(credentials)
26
+ configuration[:credentials] = Aws::Credentials.new(@credentials[:username], @credentials[:password])
27
+ @client = Aws::DynamoDB::Client.new(Hashie.symbolize_keys(configuration))
28
+ end
29
+
30
+ ##
31
+ ##
32
+ def put(entity)
33
+ @client.put_item({
34
+ table_name: @table_name,
35
+ item: entity
36
+ })
37
+ end
38
+
39
+ ##
40
+ # @param [String] identity_id primary key of the identity
41
+ # @return [Hash] the identity
42
+ # @raise [Soar::Registry::Staff::Directory::DynamoDb::Error::UniqueIdentifierNotFoundError] if primary key not found
43
+ ##
44
+ def fetch(primary_key)
45
+ options = {
46
+ table_name: @table_name,
47
+ key: {
48
+ "#{@primary_key}": primary_key
49
+ }
50
+ }
51
+ identity = @client.get_item(options)
52
+ raise Soar::Registry::Directory::Error::NoEntriesFound if identity.item.nil?
53
+ identity.item
54
+ end
55
+
56
+ ##
57
+ # @param [String] identifier_attribute
58
+ # @param [String] identifier_value
59
+ # @return [Array] list of identities
60
+ # @raise [ArgumentError] if query or index is not specified
61
+ ##
62
+ def search(key, value)
63
+ options = {
64
+ table_name: @table_name,
65
+ select: 'ALL_ATTRIBUTES',
66
+ limit: LIMIT,
67
+ key_condition_expression: "#{key} = :value",
68
+ expression_attribute_values: {
69
+ ":value": value
70
+ }
71
+ }
72
+
73
+ options.merge!({index_name: "#{key}_index"}) if @index.include?(key)
74
+ identity = @client.query(options)
75
+ identity.items.map { |item|
76
+ Hashie.stringify_keys(item)
77
+ }
78
+ end
79
+
80
+ ##
81
+ # @return [Array] a list of primary keys and global secondary indexes
82
+ ##
83
+ def index
84
+ resp = @client.describe_table({
85
+ table_name: @table_name
86
+ })
87
+ indexed_attributes = []
88
+ resp['table']['key_schema'].each { |key_schema|
89
+ indexed_attributes << key_schema['attribute_name']
90
+ }
91
+ resp['table']['global_secondary_indexes'].each { |index|
92
+ index['key_schema'].each { |key_schema|
93
+ indexed_attributes << key_schema['attribute_name']
94
+ }
95
+ }
96
+ indexed_attributes
97
+ end
98
+
99
+ ##
100
+ # Deletes existing table and creates a new one in its place
101
+ # @param name [String] table name
102
+ # @param structure [Hash] table structure
103
+ ##
104
+ def recreate_table(name: nil, structure: nil)
105
+
106
+ if @client.list_tables.table_names.include?(name)
107
+ @client.delete_table({
108
+ table_name: name
109
+ })
110
+ end
111
+ @client.create_table(Hashie.symbolize_keys(structure))
112
+ end
113
+
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,73 @@
1
+ require 'soar/registry/directory/error'
2
+ require 'hashie'
3
+ require 'mince'
4
+ require 'hashy_db'
5
+
6
+ module Soar
7
+ module Registry
8
+ module Directory
9
+ module Provider
10
+ class Stub
11
+
12
+ @@interface = Mince::HashyDb::Interface
13
+
14
+ ##
15
+ # @param table [String] table name
16
+ # @param primary_key [String]
17
+ # @param index [Array] primary key should be the first item
18
+ ##
19
+ def initialize(table: nil, primary_key: nil, index: nil)
20
+ @table = table
21
+ @primary_key = primary_key
22
+ @index = index
23
+ @@interface.clear
24
+ end
25
+
26
+ ##
27
+ # @param entity [Hash]
28
+ ##
29
+ def put(entity)
30
+ @@interface.add(@table, entity)
31
+ end
32
+
33
+ ##
34
+ # @param uuid [String]
35
+ # @return entry [Hash]
36
+ # @raise [Soar::Registry:::Directory::Error::NoEntriesFound] if primary key not found
37
+ ##
38
+ def fetch(primary_key)
39
+ entry = @@interface.get_for_key_with_value(@table, @primary_key, primary_key)
40
+ raise Soar::Registry::Directory::Error::NoEntriesFound if entry.nil?
41
+ entry
42
+ end
43
+
44
+ ##
45
+ # @param [String] identifier_attribute
46
+ # @param [String] identifier_value
47
+ # @return [Array] list of identities
48
+ # @raise [ArgumentError] if query or index is not specified
49
+ ##
50
+ def search(key, value)
51
+ identities = []
52
+ @@interface.find_all(@table).each { |identity|
53
+ if identity[key] == value
54
+ identities << identity
55
+ else
56
+ next
57
+ end
58
+ }
59
+ identities
60
+ end
61
+
62
+ ##
63
+ # @return [Array] a list of primary keys and global secondary indexes
64
+ ##
65
+ def index
66
+ @index
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,60 @@
1
+ [
2
+ {
3
+ "uuid": "identity-62936e70-1815-439b-bf89-8492855a7e6b",
4
+ "entity_id": "entity-2d931510-d99f-494a-8c67-87feb05e1594",
5
+ "email": "test+publisher@hetzner.co.za",
6
+ "roles": {
7
+ "staff": {
8
+ "department": "technical"
9
+ },
10
+ "configuration_publisher": {
11
+ "configuration_identifiers": ["*"]
12
+ }
13
+ }
14
+ },
15
+ {
16
+ "uuid": "identity-43353f18-8afe-11e6-ae22-56b6b6499611",
17
+ "entity_id": "entity-2d931510-d99f-494a-8c67-87feb05e1594",
18
+ "email": "test+consumer@hetzner.co.za",
19
+ "roles": {
20
+ "staff": {},
21
+ "configuration_consumer": {
22
+ "configuration_identifiers": ["*"]
23
+ }
24
+
25
+ }
26
+ },
27
+ {
28
+ "uuid": "identity-820d5660-2204-4f7d-8c04-746313439b81",
29
+ "entity_id": "entity-bad85eb9-0713-4da7-8d36-07a8e4b00eab",
30
+ "email": "admin@hetzner.co.za",
31
+ "roles": {
32
+ "staff": {},
33
+ "configuration_publisher": {
34
+ "configuration_identifiers": ["*"]
35
+ },
36
+ "configuration_consumer": {
37
+ "configuration_identifiers": ["*"]
38
+ }
39
+
40
+ },
41
+ "address": {
42
+ "detail": "Belvedere Office Park, Unit F",
43
+ "street": "Bella Rosa Street",
44
+ "suburb": "Tygervalley",
45
+ "city": "Durbanville",
46
+ "postal": "7550"
47
+ }
48
+ },
49
+ {
50
+ "uuid": "identity-1ff472a6-8df3-4f13-82c3-89fde26db3cf",
51
+ "entity_id": "entity-bad85eb9-0713-4da7-8d36-07a8e4b00eab",
52
+ "email": "none@example.com",
53
+ "client_nr": "C123456789",
54
+ "roles": {
55
+ "customer": {},
56
+ "reseller": {}
57
+ }
58
+ }
59
+ ]
60
+
@@ -0,0 +1,63 @@
1
+ {
2
+ "table_name": "identities",
3
+ "key_schema": [
4
+ {
5
+ "attribute_name": "uuid",
6
+ "key_type": "HASH"
7
+ }
8
+ ],
9
+ "attribute_definitions": [
10
+ {
11
+ "attribute_name": "uuid",
12
+ "attribute_type": "S"
13
+ },
14
+ {
15
+ "attribute_name": "entity_id",
16
+ "attribute_type": "S"
17
+ },
18
+ {
19
+ "attribute_name": "email",
20
+ "attribute_type": "S"
21
+ }
22
+ ],
23
+ "global_secondary_indexes": [
24
+ {
25
+ "index_name": "email_index",
26
+ "key_schema": [
27
+ {
28
+ "attribute_name": "email",
29
+ "key_type": "HASH"
30
+ }
31
+ ],
32
+ "projection": {
33
+ "projection_type": "ALL"
34
+
35
+ },
36
+ "provisioned_throughput": {
37
+ "read_capacity_units": 10,
38
+ "write_capacity_units": 10
39
+ }
40
+ },
41
+ {
42
+ "index_name": "entity_id_index",
43
+ "key_schema": [
44
+ {
45
+ "attribute_name": "entity_id",
46
+ "key_type": "HASH"
47
+ }
48
+ ],
49
+ "projection": {
50
+ "projection_type": "ALL"
51
+
52
+ },
53
+ "provisioned_throughput": {
54
+ "read_capacity_units": 10,
55
+ "write_capacity_units": 10
56
+ }
57
+ }
58
+ ],
59
+ "provisioned_throughput": {
60
+ "read_capacity_units": 10,
61
+ "write_capacity_units": 10
62
+ }
63
+ }
@@ -0,0 +1,67 @@
1
+ require 'soar/registry/directory/test/provider/stub'
2
+ require 'soar/registry/directory/test/provider/dynamo_db'
3
+
4
+ module Soar
5
+ module Registry
6
+ module Directory
7
+ module Test
8
+ class Orchestrator
9
+
10
+ def initialize(provider)
11
+ raise ArgumentError if provider.nil?
12
+ @provider = provider
13
+ end
14
+
15
+ def given_existing_data
16
+ @provider.given_existing_data
17
+ end
18
+
19
+ def given_configured_directory
20
+ @provider.given_configured_directory
21
+ end
22
+
23
+ def put_entry
24
+ @provider.put_entry
25
+ end
26
+
27
+ def search_for_entry
28
+ @provider.search_for_entry
29
+ end
30
+
31
+ def fetch_entry
32
+ @provider.fetch_entry
33
+ end
34
+
35
+ def request_index
36
+ @provider.request_index
37
+ end
38
+
39
+ def persisted?
40
+ @provider.persisted?
41
+ end
42
+
43
+ def returned?
44
+ @provider.returned?
45
+ end
46
+
47
+ def index?
48
+ @provider.index?
49
+ end
50
+
51
+ def single_entry?
52
+ @provider.single_entry?
53
+ end
54
+
55
+ def no_entries_found?
56
+ @provider.no_entries_found?
57
+ end
58
+
59
+ def no_matching_entries?
60
+ @provider.no_matching_entries?
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,89 @@
1
+ require 'soar/registry/directory'
2
+
3
+ module Soar
4
+ module Registry
5
+ module Directory
6
+ module Test
7
+ module Provider
8
+ class DynamoDb
9
+
10
+ def initialize
11
+ @configuration = YAML.load_file("config/#{ENV['CONFIG_FILE']}")
12
+ @table = @configuration['provider']['table']['name']
13
+ @index = @configuration['provider']['table']['index']
14
+ @entries = JSON.parse(File.read("lib/soar/registry/directory/test/fixtures/entries.json"))
15
+ end
16
+
17
+ def given_configured_directory
18
+ @directory = Soar::Registry::Directory.new({
19
+ provider: Soar::Registry::Directory::Provider::DynamoDb.new({
20
+ credentials: @configuration['provider']['credentials'],
21
+ table: @table,
22
+ index: @index,
23
+ primary_key: @index[0],
24
+ configuration: @configuration['provider']['config']
25
+ })
26
+ })
27
+ @directory.provider.recreate_table({
28
+ name: @table,
29
+ structure: JSON.parse(File.read("lib/soar/registry/directory/test/fixtures/table_structure.json"))
30
+ })
31
+ end
32
+
33
+ def given_existing_data
34
+ @entries.each{ |entry|
35
+ @directory.put(entry)
36
+ }
37
+ end
38
+
39
+ def put_entry
40
+ @directory.put(@entries[0])
41
+ end
42
+
43
+ def search_for_entry
44
+ @result = @directory.search("email", @entries[0]['email'])
45
+ end
46
+
47
+ def request_index
48
+ @result = @directory.index
49
+ end
50
+
51
+ def fetch_entry
52
+ begin
53
+ @result = @directory.fetch(@entries[0]['uuid'])
54
+ rescue Soar::Registry::Directory::Error::NoEntriesFound
55
+ @error = true
56
+ end
57
+ end
58
+
59
+ def persisted?
60
+ @entries[0] == @directory.fetch(@entries[0]["uuid"])
61
+ end
62
+
63
+ def returned?
64
+ @result == [@entries[0]]
65
+ end
66
+
67
+ def index?
68
+ @result == @index
69
+ end
70
+
71
+ def single_entry?
72
+ @result == @entries[0]
73
+ end
74
+
75
+ def no_entries_found?
76
+ @error
77
+ end
78
+
79
+ def no_matching_entries?
80
+ @result == []
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,81 @@
1
+ require 'soar/registry/directory'
2
+
3
+ module Soar
4
+ module Registry
5
+ module Directory
6
+ module Test
7
+ module Provider
8
+ class Stub
9
+
10
+ @@entry = {
11
+ "uuid" => SecureRandom.uuid,
12
+ "identifier" => SecureRandom.hex
13
+ }
14
+
15
+ @@index = ["identity_id", "email", "entity_id"]
16
+
17
+ def given_configured_directory
18
+ @directory = Soar::Registry::Directory.new({
19
+ provider: Soar::Registry::Directory::Provider::Stub.new({
20
+ table: "identities",
21
+ primary_key: "uuid",
22
+ index: @@index
23
+ })
24
+ })
25
+ end
26
+
27
+ def given_existing_data
28
+ @directory.put(@@entry)
29
+ end
30
+
31
+ def put_entry
32
+ @directory.put(@@entry)
33
+ end
34
+
35
+ def search_for_entry
36
+ @entry = @directory.search("identifier", @@entry['identifier'])
37
+ end
38
+
39
+ def request_index
40
+ @index = @directory.index
41
+ end
42
+
43
+ def fetch_entry
44
+ begin
45
+ @entry = @directory.fetch(@@entry['uuid'])
46
+ rescue Soar::Registry::Directory::Error::NoEntriesFound
47
+ @error = true
48
+ end
49
+ end
50
+
51
+ def persisted?
52
+ @@entry == @directory.fetch(@@entry["uuid"])
53
+ end
54
+
55
+ def returned?
56
+ @entry == [@@entry]
57
+ end
58
+
59
+ def index?
60
+ @index == @@index
61
+ end
62
+
63
+ def single_entry?
64
+ @entry == @@entry
65
+ end
66
+
67
+ def no_entries_found?
68
+ @error
69
+ end
70
+
71
+ def no_matching_entries?
72
+ @entry == []
73
+ end
74
+
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,11 @@
1
+ require "soar/registry/directory/model"
2
+
3
+ module Soar
4
+ module Registry
5
+ module Directory
6
+ def self.new(provider: nil)
7
+ Soar::Registry::Directory::Model.new(provider: provider)
8
+ end
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: soar-registry-directory
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Charles Mulder
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hashy_db
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mince
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: aws-sdk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.6'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 2.6.6
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '2.6'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 2.6.6
61
+ - !ruby/object:Gem::Dependency
62
+ name: aws-sdk-core
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.6'
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 2.6.28
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '2.6'
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 2.6.28
81
+ - !ruby/object:Gem::Dependency
82
+ name: hashie
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '3.4'
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 3.4.6
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '3.4'
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 3.4.6
101
+ description: Directories for soar registries
102
+ email: charles.mulder@hetzner.co.za
103
+ executables: []
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - README.md
108
+ - lib/soar/registry/directory.rb
109
+ - lib/soar/registry/directory/error.rb
110
+ - lib/soar/registry/directory/model.rb
111
+ - lib/soar/registry/directory/provider/dynamo_db.rb
112
+ - lib/soar/registry/directory/provider/stub.rb
113
+ - lib/soar/registry/directory/test/fixtures/entries.json
114
+ - lib/soar/registry/directory/test/fixtures/table_structure.json
115
+ - lib/soar/registry/directory/test/orchestrator.rb
116
+ - lib/soar/registry/directory/test/provider/dynamo_db.rb
117
+ - lib/soar/registry/directory/test/provider/stub.rb
118
+ homepage: https://gitlab.host-h.net/registries/directory
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 2.5.1
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Soar Registry Directory
142
+ test_files: []