seiso-import_master 0.0.12 → 3.0.0.M1

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.
Files changed (63) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -0
  4. data/README.md +12 -11
  5. data/Rakefile +3 -3
  6. data/bin/seiso-import-master +30 -13
  7. data/lib/seiso/import_master.rb +114 -90
  8. data/lib/seiso/import_master/importers.rb +5 -0
  9. data/lib/seiso/import_master/importers/base_importer.rb +91 -30
  10. data/lib/seiso/import_master/importers/data_center_importer.rb +31 -0
  11. data/lib/seiso/import_master/importers/environment_importer.rb +25 -0
  12. data/lib/seiso/import_master/importers/health_status_importer.rb +25 -0
  13. data/lib/seiso/import_master/importers/infrastructure_provider_importer.rb +25 -0
  14. data/lib/seiso/import_master/importers/ip_address_role_importer.rb +41 -0
  15. data/lib/seiso/import_master/importers/load_balancer_importer.rb +25 -0
  16. data/lib/seiso/import_master/importers/machine_importer.rb +25 -0
  17. data/lib/seiso/import_master/importers/node_importer.rb +94 -56
  18. data/lib/seiso/import_master/importers/node_ip_address_importer.rb +46 -0
  19. data/lib/seiso/import_master/importers/region_importer.rb +31 -0
  20. data/lib/seiso/import_master/importers/rotation_status_importer.rb +25 -0
  21. data/lib/seiso/import_master/importers/service_group_importer.rb +25 -0
  22. data/lib/seiso/import_master/importers/service_importer.rb +38 -143
  23. data/lib/seiso/import_master/importers/service_instance_importer.rb +60 -213
  24. data/lib/seiso/import_master/importers/service_instance_port_importer.rb +41 -0
  25. data/lib/seiso/import_master/importers/service_type_importer.rb +25 -0
  26. data/lib/seiso/import_master/importers/status_type_importer.rb +25 -0
  27. data/lib/seiso/import_master/mappers.rb +1 -0
  28. data/lib/seiso/import_master/mappers/data_center_mapper.rb +19 -0
  29. data/lib/seiso/import_master/mappers/environment_mapper.rb +20 -0
  30. data/lib/seiso/import_master/mappers/health_status_mapper.rb +20 -0
  31. data/lib/seiso/import_master/mappers/infrastructure_provider_mapper.rb +18 -0
  32. data/lib/seiso/import_master/mappers/ip_address_role_mapper.rb +18 -0
  33. data/lib/seiso/import_master/mappers/load_balancer_mapper.rb +21 -0
  34. data/lib/seiso/import_master/mappers/machine_mapper.rb +27 -0
  35. data/lib/seiso/import_master/mappers/node_ip_address_mapper.rb +38 -0
  36. data/lib/seiso/import_master/mappers/node_mapper.rb +31 -31
  37. data/lib/seiso/import_master/mappers/region_mapper.rb +20 -0
  38. data/lib/seiso/import_master/mappers/rotation_status_mapper.rb +20 -0
  39. data/lib/seiso/import_master/mappers/service_group_mapper.rb +18 -0
  40. data/lib/seiso/import_master/mappers/service_instance_mapper.rb +26 -73
  41. data/lib/seiso/import_master/mappers/service_instance_port_mapper.rb +19 -0
  42. data/lib/seiso/import_master/mappers/service_mapper.rb +23 -32
  43. data/lib/seiso/import_master/mappers/service_type_mapper.rb +19 -0
  44. data/lib/seiso/import_master/mappers/status_type_mapper.rb +18 -0
  45. data/lib/seiso/import_master/util.rb +1 -0
  46. data/lib/seiso/import_master/util/invalid_document_error.rb +9 -0
  47. data/lib/seiso/import_master/util/item_resolver.rb +54 -0
  48. data/lib/seiso/import_master/util/logger.rb +59 -0
  49. data/lib/seiso/import_master/util/rest_util.rb +49 -0
  50. data/lib/seiso/import_master/validators.rb +1 -0
  51. data/lib/seiso/import_master/validators/base_validator.rb +11 -18
  52. data/lib/seiso/import_master/validators/node_validator.rb +54 -45
  53. data/lib/seiso/import_master/validators/service_validator.rb +38 -44
  54. data/sample_conf/seiso3.yml.sample +6 -0
  55. data/seiso-import_master.gemspec +16 -13
  56. data/test/seiso/import_master/importers/test_node_importer.rb +21 -0
  57. metadata +66 -21
  58. data/lib/seiso/import_master/errors/invalid_document_error.rb +0 -11
  59. data/lib/seiso/import_master/importers/simple_importer.rb +0 -28
  60. data/lib/seiso/import_master/mappers/master_item_mapper.rb +0 -194
  61. data/sample_conf/seiso.yml.sample +0 -9
  62. data/test/test_master_item_mapper.rb +0 -257
  63. data/test/test_node_mapper.rb +0 -40
@@ -0,0 +1,25 @@
1
+ class Seiso::ImportMaster
2
+ class Importers::RotationStatusImporter < Importers::BaseImporter
3
+
4
+ def initialize(api, rest_util, resolver)
5
+ self.api = api
6
+ self.rest_util = rest_util
7
+ self.mapper = Mappers::RotationStatusMapper.new resolver
8
+ self.repo_resource = api.rotationStatuses.get
9
+
10
+ @search_resource = repo_resource.search.get
11
+ end
12
+
13
+ def import(doc)
14
+ import_items(doc['items'], {})
15
+ end
16
+
17
+ def to_search_params(doc_rs, context)
18
+ { 'key' => doc_rs['key'] }
19
+ end
20
+
21
+ def find_resource(search_params)
22
+ @search_resource.findByKey(key: search_params['key']).get
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ class Seiso::ImportMaster
2
+ class Importers::ServiceGroupImporter < Importers::BaseImporter
3
+
4
+ def initialize(api, rest_util, resolver)
5
+ self.api = api
6
+ self.rest_util = rest_util
7
+ self.mapper = Mappers::ServiceGroupMapper.new resolver
8
+ self.repo_resource = api.serviceGroups.get
9
+
10
+ @search_resource = repo_resource.search.get
11
+ end
12
+
13
+ def import(doc)
14
+ import_items(doc['items'], {})
15
+ end
16
+
17
+ def to_search_params(doc_sg, context)
18
+ { 'key' => doc_sg['key'] }
19
+ end
20
+
21
+ def find_resource(search_params)
22
+ @search_resource.findByKey(key: search_params['key']).get
23
+ end
24
+ end
25
+ end
@@ -1,143 +1,38 @@
1
- require_relative "base_importer"
2
-
3
- module Seiso
4
- class ImportMaster
5
- module Importers
6
-
7
- # TODO Clean this up. Just use v2 URI factory and connector.
8
-
9
- # Imports a service document into Seiso.
10
- #
11
- # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
12
- # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
13
- # License:: Apache 2.0
14
- class ServiceImporter < BaseImporter
15
-
16
- def initialize(
17
- basic_mapper,
18
- service_mapper,
19
- uri_factory_v1,
20
- uri_factory_v2,
21
- rest_connector_v1,
22
- rest_connector_v2)
23
-
24
- @service_mapper = service_mapper
25
- @basic_mapper = basic_mapper
26
- @uri_factory_v1 = uri_factory_v1
27
- @uri_factory_v2 = uri_factory_v2
28
- @rest_connector_v1 = rest_connector_v1
29
- @rest_connector_v2 = rest_connector_v2
30
- end
31
-
32
- # Imports the service document
33
- def import(doc)
34
- services = doc['items']
35
- puts "Importing service document"
36
-
37
- sdm_doc_links = detach_children(services, 'service', 'key', 'docLinks')
38
-
39
- seiso_services = services.map { |s| @service_mapper.seiso_service s }
40
- services_uri = @uri_factory_v1.services_uri true
41
- @rest_connector_v1.post(services_uri, seiso_services)
42
-
43
- import_doc_links(services, sdm_doc_links)
44
- end
45
-
46
- private
47
-
48
- # - services: services
49
- # - doc_links: SDM doc links
50
- def import_doc_links(services, doc_links)
51
-
52
- # We can't simply infer the services from the doc links, because we have to handle the case
53
- # where we remove all doc links from a service instance that formerly had some.
54
-
55
- doc_links_by_service = group_doc_links_by_service doc_links
56
- services.each do |service|
57
- service_key = service['key']
58
- service_doc_links = doc_links_by_service[service_key] || []
59
- doc_links_uri = @uri_factory_v2.doc_links_uri service_key
60
-
61
- # Get service's doc links so we can
62
- # 1) Delete stale doc links
63
- # 2) Avoid duplicate imports
64
- seiso_doc_links_response = @rest_connector_v2.get doc_links_uri
65
- seiso_doc_links = JSON.parse seiso_doc_links_response.body
66
-
67
- # Delete stale doc links
68
- to_delete = seiso_doc_links_to_delete(service_doc_links, seiso_doc_links)
69
- to_delete.each do |seiso_doc_link|
70
- href = seiso_doc_link['_links']['self']['href']
71
- uri = URI.parse href
72
- @rest_connector_v2.delete(uri)
73
- end
74
-
75
- # Classify remaining links as post or put
76
- to_post = []
77
- to_put = []
78
- service_doc_links.each do |sdm_doc_link|
79
- sdm_title = sdm_doc_link['title']
80
- post_it = true
81
- seiso_doc_links.each do |seiso_doc_link|
82
- seiso_title = seiso_doc_link['title']
83
- if sdm_title == seiso_title
84
- href = seiso_doc_link['_links']['self']['href']
85
- uri = URI.parse href
86
- new_seiso_doc_link = @basic_mapper.map_one('doc-links', sdm_doc_link)
87
- to_put << {
88
- "uri" => uri,
89
- "resource" => new_seiso_doc_link
90
- }
91
- post_it = false
92
- break
93
- end
94
- end
95
- to_post << sdm_doc_link if post_it
96
- end
97
-
98
- # Post new links
99
- to_post.each do |sdm_doc_link|
100
- seiso_doc_link = @basic_mapper.map_one('doc-links', sdm_doc_link)
101
- @rest_connector_v2.post(doc_links_uri, seiso_doc_link)
102
- end
103
-
104
- # Put existing links
105
- @rest_connector_v2.put_all(to_put)
106
- end
107
- end
108
-
109
- def group_doc_links_by_service(doc_links)
110
- doc_links_by_service = {}
111
- doc_links.each do |dl|
112
- service_key = dl['service']
113
- service_doc_links = doc_links_by_service[service_key]
114
- if service_doc_links.nil?
115
- service_doc_links = []
116
- doc_links_by_service[service_key] = service_doc_links
117
- end
118
- service_doc_links << dl
119
- end
120
- doc_links_by_service
121
- end
122
-
123
- def seiso_doc_links_to_delete(sdm_doc_links, seiso_doc_links)
124
- to_delete = []
125
- seiso_doc_links.each do |seiso_doc_link|
126
- seiso_title = seiso_doc_link['title']
127
- delete_it = true
128
- sdm_doc_links.each do |sdm_doc_link|
129
- sdm_title = sdm_doc_link['title']
130
- if sdm_title == seiso_title
131
- delete_it = false
132
- break
133
- end
134
- end
135
- to_delete << seiso_doc_link if delete_it
136
- end
137
- to_delete
138
- end
139
-
140
- end # class ServiceImporter
141
- end # module Importers
142
- end # class ImportMaster
143
- end # module Seiso
1
+ class Seiso::ImportMaster
2
+ # Imports a service document into Seiso.
3
+ #
4
+ # Author:: Willie Wheeler
5
+ # Author:: Ian McCunn
6
+ # Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
7
+ # License:: Apache 2.0
8
+ class Importers::ServiceImporter < Importers::BaseImporter
9
+
10
+ def initialize(api, rest_util, resolver)
11
+ self.api = api
12
+ self.rest_util = rest_util
13
+ self.mapper = Mappers::ServiceMapper.new resolver
14
+ self.repo_resource = api.services.get
15
+
16
+ @validator = Validators::ServiceValidator.new
17
+ @search_resource = repo_resource.search.get
18
+ end
19
+
20
+ def import(doc)
21
+ @validator.validate doc
22
+ import_items(doc['items'], {})
23
+ end
24
+
25
+ # Can't make these protected, because that prevents BaseImporter from seeing them.
26
+ # protected
27
+
28
+ # BaseImporter callback
29
+ def to_search_params(doc_service, context)
30
+ { 'key' => doc_service['key'] }
31
+ end
32
+
33
+ # BaseImporter callback
34
+ def find_resource(search_params)
35
+ @search_resource.findByKey(key: search_params['key']).get
36
+ end
37
+ end
38
+ end
@@ -1,213 +1,60 @@
1
- require "uri"
2
- require_relative "base_importer"
3
-
4
- module Seiso
5
- class ImportMaster
6
- module Importers
7
-
8
- # TODO Clean this up. Just use v2 URI factory and connector.
9
- # Right now we're using three separate Seiso connectors (and two versions of the Seiso API)
10
- # and this sucks. [WLW]
11
-
12
- # Imports a service instance document into Seiso.
13
- #
14
- # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
15
- # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
16
- # License:: Apache 2.0
17
- class ServiceInstanceImporter < BaseImporter
18
-
19
- def initialize(
20
- service_instance_mapper,
21
- uri_factory_v1,
22
- uri_factory_v2,
23
- seiso,
24
- rest_connector_v1,
25
- rest_connector_v2)
26
-
27
- @service_instance_mapper = service_instance_mapper
28
- @uri_factory_v1 = uri_factory_v1
29
- @uri_factory_v2 = uri_factory_v2
30
- @seiso = seiso
31
- @rest_connector_v1 = rest_connector_v1
32
- @rest_connector_v2 = rest_connector_v2
33
- end
34
-
35
- # Imports the service instance document
36
- def import(doc)
37
- sdm_service_instances = doc['items']
38
- sdm_ports = detach_children(sdm_service_instances, 'serviceInstance', 'key', 'ports')
39
- sdm_roles = detach_children(sdm_service_instances, 'serviceInstance', 'key', 'ipAddressRoles')
40
- sdm_dependencies = detach_children(sdm_service_instances, 'serviceInstance', 'key', 'dependencies')
41
- sdm_seyren_checks = detach_children(sdm_service_instances, 'serviceInstance', 'key', 'seyrenChecks')
42
-
43
- import_service_instances sdm_service_instances
44
- import_ports sdm_ports
45
- import_ip_address_roles sdm_roles
46
- import_dependencies sdm_dependencies
47
- import_seyren_checks sdm_seyren_checks
48
- end
49
-
50
- private
51
-
52
- def import_service_instances(sdm_service_instances)
53
- seiso_service_instances = sdm_service_instances.map do |si|
54
- @service_instance_mapper.seiso_service_instance si
55
- end
56
- service_instances_uri = @uri_factory_v1.service_instances_uri true
57
- @rest_connector_v1.post(service_instances_uri, seiso_service_instances)
58
- end
59
-
60
- def import_ports(sdm_ports)
61
- seiso_ports = sdm_ports.map do |p|
62
- @service_instance_mapper.seiso_service_instance_port p
63
- end
64
- @seiso.post_items('service-instance-ports', seiso_ports)
65
- end
66
-
67
- def import_ip_address_roles(sdm_roles)
68
- seiso_roles = sdm_roles.map do |r|
69
- @service_instance_mapper.seiso_ip_address_role r
70
- end
71
- @seiso.post_items('ip-address-roles', seiso_roles)
72
- end
73
-
74
- def import_dependencies(sdm_dependencies)
75
- puts "Importing dependencies"
76
- seiso_dependencies = @service_instance_mapper.seiso_service_instance_dependencies sdm_dependencies
77
- grouped_seiso_dependencies = group_dependencies_by_service_instance seiso_dependencies
78
-
79
- # Iterate over the groups, deleting stale dependencies and importing the rest
80
- grouped_seiso_dependencies.each do |key, group|
81
- puts "key=#{key}, group=#{group}"
82
- delete_stale_dependencies(key, group)
83
-
84
- # Import the dependencies.
85
- group.each do |d|
86
- dependent_key = d['dependent']['key']
87
- dependency_key = d['dependency']['key']
88
- puts "Importing dependency: dependent=#{dependent_key}, dependency=#{dependency_key}"
89
- search_uri = @uri_factory_v2.uri "/service-instance-dependencies/search/find-by-keys?dependent=#{dependent_key}&dependency=#{dependency_key}"
90
-
91
- # TODO 404 means POST, 200 means PUT
92
- seiso_sid_response = @rest_connector_v2.get search_uri
93
-
94
- if seiso_sid_response.code == "200"
95
- # Found it, so PUT
96
- seiso_sid = JSON.parse seiso_sid_response.body
97
- dep_uri = URI.parse(seiso_sid['_links']['self']['href'])
98
- # puts "dep_uri=#{dep_uri}"
99
- # puts JSON.pretty_generate(d)
100
- @rest_connector_v2.put(dep_uri, d)
101
- elsif seiso_sid_response.code == "404"
102
- # Not found, so POST
103
- deps_uri = @uri_factory_v2.uri "/service-instance-dependencies"
104
- @rest_connector_v2.post(deps_uri, d)
105
- else
106
- puts "Don't know how to handle response code #{seiso_sid.code}; skipping."
107
- end
108
- end
109
- end
110
- end
111
-
112
- # Helper for import_dependencies
113
- def group_dependencies_by_service_instance(seiso_dependencies)
114
- grouped_seiso_dependencies = {}
115
- seiso_dependencies.each do |d|
116
- dependent_key = d['dependent']['key']
117
- puts "dependent_key=#{dependent_key}"
118
- group = grouped_seiso_dependencies[dependent_key]
119
- if group.nil?
120
- group = []
121
- grouped_seiso_dependencies[dependent_key] = group
122
- end
123
- group << d
124
- end
125
- grouped_seiso_dependencies
126
- end
127
-
128
- # Helper for import_dependencies
129
- #
130
- # - dependent_key: Key of the dependent service instance.
131
- # - local_dependencies: List of local dependencies (in Seiso format) associated with
132
- # the specified dependent.
133
- def delete_stale_dependencies(dependent_key, local_dependencies)
134
- puts "Deleting stale dependencies for service instance #{dependent_key}"
135
-
136
- local_dependency_keys = local_dependencies.map do |local|
137
- # TODO Will need to update when I update the v2 API
138
- local['dependency']['key']
139
- end
140
-
141
- # FIXME This isn't accounting for pagination!
142
- # If there are a lot of remote dependencies, some may not be marked as stale.
143
- # Just need to implement it. [WLW]
144
- remote_dependencies_uri =
145
- @uri_factory_v2.uri "/service-instance-dependencies/search/find-by-dependent?key=#{dependent_key}"
146
- remote_dependencies_response = @rest_connector_v2.get remote_dependencies_uri
147
- remote_dependencies = JSON.parse(remote_dependencies_response.body)['_embedded']['items']
148
-
149
- # Identify stale dependencies
150
- stale_remote_dependencies = remote_dependencies.reject do |remote|
151
- local_dependency_keys.include? remote['_embedded']['dependency']['key']
152
- end
153
-
154
- # Delete stale dependencies from Seiso
155
- if stale_remote_dependencies.empty?
156
- puts "No stale dependencies for service instance #{dependent_key}"
157
- else
158
- stale_remote_dependencies.each do |stale|
159
- uri = URI.parse stale['_links']['self']['href']
160
- @rest_connector_v2.delete uri
161
- end
162
- end
163
- end
164
-
165
- def import_seyren_checks(sdm_checks)
166
- puts "Importing Seyren checks"
167
-
168
- # Group checks by service instance
169
- checks_by_service_instance = {}
170
- sdm_checks.each do |c|
171
- si_key = c['serviceInstance']
172
- checks = checks_by_service_instance[si_key]
173
- if checks.nil?
174
- checks = []
175
- checks_by_service_instance[si_key] = checks
176
- end
177
- checks << c
178
- end
179
-
180
- # Iterate over service instances, posting the checks for each one.
181
- # TODO Need to handle stale checks and separate POST/PUT
182
- checks_by_service_instance.each do |si_key, si_checks|
183
- puts "Importing Seyren checks: serviceInstance=#{si_key}"
184
-
185
- # checks_uri is the Seiso collection resource for posting checks to a service instance
186
- checks_uri = @uri_factory_v2.service_instance_seyren_checks_uri si_key
187
-
188
- # Build the list of Seiso Seyren check URIs that we want to post to checks_uri
189
- uri_list = []
190
- si_checks.each do |sdm_check|
191
-
192
- # Look up the Seiso Seyren check URI, since we don't know it in advance.
193
- # If it exists, add it to the URI list.
194
- seyren_base_url = sdm_check['baseUrl']
195
- seyren_id = sdm_check['id']
196
- search_uri = @uri_factory_v2.find_seyren_check_uri(seyren_base_url, seyren_id)
197
- response = @rest_connector_v2.get search_uri
198
- if response.code == "200"
199
- seiso_check = JSON.parse response.body
200
- uri_list << seiso_check['_links']['self']['href']
201
- end
202
- # TODO Log a warning or something if the response code is 404 or other problem.
203
- end
204
-
205
- # Post the URI list to checks_uri
206
- @rest_connector_v2.post_uri_list(checks_uri, uri_list)
207
- end
208
-
209
- end
210
- end # class ServiceInstanceImporter
211
- end # module Importers
212
- end # class ImportMaster
213
- end # module Seiso
1
+ class Seiso::ImportMaster
2
+ # Imports a service instance document into Seiso.
3
+ #
4
+ # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
5
+ # Author:: Chris Brown
6
+ # Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
7
+ # License:: Apache 2.0
8
+ class Importers::ServiceInstanceImporter < Importers::BaseImporter
9
+
10
+ def initialize(api, rest_util, resolver)
11
+ self.api = api
12
+ self.rest_util = rest_util
13
+ self.mapper = Mappers::ServiceInstanceMapper.new resolver
14
+ self.repo_resource = api.serviceInstances.get
15
+
16
+ @ipr_importer = Importers::IpAddressRoleImporter.new(api, rest_util)
17
+ @sip_importer = Importers::ServiceInstancePortImporter.new(api, rest_util)
18
+ @search_resource = repo_resource.search.get
19
+ end
20
+
21
+ def import(doc)
22
+ import_items(doc['items'], {})
23
+ end
24
+
25
+ # Can't make these protected, because that prevents BaseImporter from seeing them.
26
+ # protected
27
+
28
+ # BaseImporter callback
29
+ def to_search_params(doc_si, context)
30
+ { 'key' => doc_si['key'] }
31
+ end
32
+
33
+ # BaseImporter callback
34
+ def find_resource(search_params)
35
+ @search_resource.findByKey(key: search_params['key']).get
36
+ end
37
+
38
+ # BaseImporter callback
39
+ def context_for(parent_resource, parent_context)
40
+ { 'serviceInstance' => parent_resource }
41
+ end
42
+
43
+ # BaseImporter callback
44
+ def import_children_of(doc_si, context)
45
+
46
+ # Create a default IP address role if one doesn't exist. Its name is "default".
47
+ doc_iprs = doc_si['ipAddressRoles']
48
+ if doc_iprs.nil? || doc_iprs.empty?
49
+ doc_iprs = [ { 'name' => 'default', 'description' => 'Default role' } ]
50
+ end
51
+
52
+ # This doesn't have to be defined. For example, agents won't have ports.
53
+ # If it's not defined, we don't need to create an empty list over it.
54
+ doc_sips = doc_si['ports']
55
+
56
+ @ipr_importer.import_items(doc_iprs, context)
57
+ @sip_importer.import_items(doc_sips, context) unless doc_sips.nil?
58
+ end
59
+ end
60
+ end