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,31 @@
1
+ class Seiso::ImportMaster
2
+ class Importers::DataCenterImporter < Importers::BaseImporter
3
+
4
+ def initialize(api, rest_util, resolver)
5
+ @log = Util::Logger.new "DataCenterImporter"
6
+
7
+ self.api = api
8
+ self.rest_util = rest_util
9
+ self.mapper = Mappers::DataCenterMapper.new resolver
10
+ self.repo_resource = api.dataCenters.get
11
+
12
+ @log.info "Getting /dataCenters/search"
13
+ @search_resource = repo_resource.search.get
14
+ end
15
+
16
+ def import(doc)
17
+ @log.info "Importing data centers"
18
+ import_items(doc['items'], {})
19
+ end
20
+
21
+ def to_search_params(doc_dc, context)
22
+ { 'key' => doc_dc['key'] }
23
+ end
24
+
25
+ def find_resource(search_params)
26
+ key = search_params['key']
27
+ @log.info "Getting /dataCenters/search/findByKey?key=#{key}"
28
+ @search_resource.findByKey(key: key).get
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,25 @@
1
+ class Seiso::ImportMaster
2
+ class Importers::EnvironmentImporter < Importers::BaseImporter
3
+
4
+ def initialize(api, rest_util, resolver)
5
+ self.api = api
6
+ self.rest_util = rest_util
7
+ self.mapper = Mappers::EnvironmentMapper.new resolver
8
+ self.repo_resource = api.environments.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_env, context)
18
+ { 'key' => doc_env['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::HealthStatusImporter < Importers::BaseImporter
3
+
4
+ def initialize(api, rest_util, resolver)
5
+ self.api = api
6
+ self.rest_util = rest_util
7
+ self.mapper = Mappers::HealthStatusMapper.new resolver
8
+ self.repo_resource = api.healthStatuses.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_hs, context)
18
+ { 'key' => doc_hs['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::InfrastructureProviderImporter < Importers::BaseImporter
3
+
4
+ def initialize(api, rest_util, resolver)
5
+ self.api = api
6
+ self.rest_util = rest_util
7
+ self.mapper = Mappers::InfrastructureProviderMapper.new resolver
8
+ self.repo_resource = api.infrastructureProviders.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_ip, context)
18
+ { 'key' => doc_ip['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,41 @@
1
+ # TODO Reinstate the autocreation that Chris Brown wrote
2
+
3
+ class Seiso::ImportMaster
4
+ # Imports IP address roles into Seiso. This importer handles:
5
+ # - orphan removal
6
+ # - POSTing new IP address roles
7
+ # - PUTting existing IP address roles
8
+ #
9
+ # Author:: Willie Wheeler
10
+ # Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
11
+ # License:: Apache 2.0
12
+ class Importers::IpAddressRoleImporter < Importers::BaseImporter
13
+
14
+ def initialize(api, rest_util)
15
+ self.api = api
16
+ self.rest_util = rest_util
17
+ self.mapper = Mappers::IpAddressRoleMapper.new
18
+ self.repo_resource = api.ipAddressRoles.get
19
+
20
+ @search_resource = repo_resource.search.get
21
+ end
22
+
23
+ # Can't make these protected, because that prevents BaseImporter from seeing them.
24
+ # protected
25
+
26
+ # BaseImporter callback
27
+ def to_search_params(doc_ipr, context)
28
+ {
29
+ 'si' => context['serviceInstance'].key,
30
+ 'name' => doc_ipr['name']
31
+ }
32
+ end
33
+
34
+ # BaseImporter callback
35
+ def find_resource(search_params)
36
+ si = search_params['si']
37
+ name = search_params['name']
38
+ @search_resource.findByServiceInstanceKeyAndName(si: si, name: name).get
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,25 @@
1
+ class Seiso::ImportMaster
2
+ class Importers::LoadBalancerImporter < Importers::BaseImporter
3
+
4
+ def initialize(api, rest_util, resolver)
5
+ self.api = api
6
+ self.rest_util = rest_util
7
+ self.mapper = Mappers::LoadBalancerMapper.new resolver
8
+ self.repo_resource = api.loadBalancers.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_lb, context)
18
+ { 'name' => doc_lb['name'] }
19
+ end
20
+
21
+ def find_resource(search_params)
22
+ @search_resource.findByName(name: search_params['name']).get
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ class Seiso::ImportMaster
2
+ class Importers::MachineImporter < Importers::BaseImporter
3
+
4
+ def initialize(api, rest_util, resolver)
5
+ self.api = api
6
+ self.rest_util = rest_util
7
+ self.mapper = Mappers::MachineMapper.new resolver
8
+ self.repo_resource = api.machines.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_machine, context)
18
+ { 'name' => doc_machine['name'] }
19
+ end
20
+
21
+ def find_resource(search_params)
22
+ @search_resource.findByName(name: search_params['name']).get
23
+ end
24
+ end
25
+ end
@@ -1,69 +1,107 @@
1
- require_relative "base_importer"
2
-
3
- module Seiso
4
- class ImportMaster
5
- module Importers
6
-
7
- # Imports a node document into Seiso.
8
- #
9
- # Each node doc corresponds to a service instance. This importer compares the nodes in Seiso with the
10
- # nodes in the node doc, and removes anything from Seiso that isn't in the node doc. Then it imports
11
- # the nodes from the node doc into Seiso.
12
- #
13
- # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
14
- # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
15
- # License:: Apache 2.0
16
- class NodeImporter < BaseImporter
17
-
18
- def initialize(mapper, uri_factory_v1, rest_connector_v1)
19
- @mapper = mapper
20
- @uri_factory_v1 = uri_factory_v1
21
- @rest_connector_v1 = rest_connector_v1
22
- end
1
+ class Seiso::ImportMaster
2
+ # Imports a node document into Seiso.
3
+ #
4
+ # Each node doc corresponds to a service instance. This importer compares the nodes in Seiso with the nodes in the
5
+ # node doc and removes anything from Seiso that isn't in the node doc. Then it imports the nodes from the node doc
6
+ # into Seiso.
7
+ #
8
+ # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
9
+ # Author:: Chris Brown
10
+ # Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
11
+ # License:: Apache 2.0
12
+ class Importers::NodeImporter < Importers::BaseImporter
23
13
 
24
- # Imports the node document.
25
- def import(doc)
26
- si_key = doc['serviceInstance']
27
- nodes = doc['items']
28
- puts "Importing node document for service instance #{si_key}"
14
+ def initialize(api, rest_util, resolver)
15
+ self.api = api
16
+ self.rest_util = rest_util
17
+ self.mapper = Mappers::NodeMapper.new resolver
18
+ self.repo_resource = api.nodes.get
29
19
 
30
- delete_stale_nodes_from_seiso
20
+ @validator = Validators::NodeValidator.new
21
+ @nip_importer = Importers::NodeIpAddressImporter.new(api, rest_util)
22
+ @search_resource = repo_resource.search.get
31
23
 
32
- # Node masters contain the service instance at the top-level, so enrich the nodes themselves
33
- # with the service instance.
34
- nodes.each do |n|
35
- n['serviceInstance'] = si_key
36
- end
24
+ @machine_search_resource = api.machines.search.get
25
+ end
37
26
 
38
- nips = detach_children(nodes, 'node', 'name', 'ipAddresses')
27
+ def import(doc)
28
+ @validator.validate doc
29
+ doc_nodes = doc['items']
30
+ si_key = doc['serviceInstance']
31
+ si_proxy = api.serviceInstances.search.findByKey(key: si_key)
32
+ si = rest_util.get_or_nil(si_proxy, si_key)
39
33
 
40
- seiso_nodes = nodes.map { |n| @mapper.seiso_node n }
41
- nodes_uri = @uri_factory_v1.nodes_uri true
42
- @rest_connector_v1.post(nodes_uri, seiso_nodes)
34
+ if si.nil?
35
+ raise Util::InvalidDocumentError.new "Service instance #{si_key} not found."
36
+ end
43
37
 
44
- import_nips nips
45
- end
38
+ seiso_nodes = si.nodes.get
39
+ delete_orphans(doc_nodes, seiso_nodes)
40
+ import_items(doc_nodes, { 'serviceInstance' => si })
41
+ end
46
42
 
47
- private
43
+ # Can't make these protected, because that prevents BaseImporter from seeing them.
44
+ # protected
48
45
 
49
- def delete_stale_nodes_from_seiso
50
- # TODO
51
- # puts "TODO Delete stale nodes from seiso"
52
- end
46
+ # BaseImporter callback
47
+ def to_search_params(doc_node, context)
48
+ { 'name' => doc_node['name'] }
49
+ end
50
+
51
+ # BaseImporter callback
52
+ def find_resource(search_params)
53
+ @search_resource.findByName(name: search_params['name']).get
54
+ end
55
+
56
+ # BaseImporter callback
57
+ def context_for(parent_resource, parent_context)
58
+ {
59
+ 'serviceInstance' => parent_context['serviceInstance'],
60
+ 'node' => parent_resource
61
+ }
62
+ end
53
63
 
54
- def import_nips(nips)
55
- seiso_nip_pairs = nips.map do |nip|
56
- node_name = nip['node']
57
- ip_address = nip['ipAddress']
58
- {
59
- "uri" => @uri_factory_v1.node_ip_address_uri(node_name, ip_address),
60
- "resource" => @mapper.seiso_nip(nip)
61
- }
62
- end
63
- # Uses keepalive
64
- @rest_connector_v1.put_all seiso_nip_pairs
64
+ # BaseImporter callback
65
+ def import_children_of(doc_node, context)
66
+ doc_nips = doc_node['ipAddresses']
67
+
68
+ # If there aren't any IP addresses explicitly set, then derive one from the machine.
69
+ if doc_nips.nil? || doc_nips.empty?
70
+ doc_nips = create_default_doc_nips(doc_node, context)
71
+ end
72
+
73
+ @nip_importer.import_items(doc_nips, context)
74
+ end
75
+
76
+ private
77
+
78
+ def delete_orphans(doc_nodes, seiso_nodes)
79
+ doc_node_names = doc_nodes.map { |doc_node| doc_node['name'] }
80
+ seiso_nodes.each do |seiso_node|
81
+ orphan = !doc_node_names.include?(seiso_node.name)
82
+ if orphan
83
+ params = { 'name' => seiso_node.name }
84
+ rest_util.delete(seiso_node, params)
65
85
  end
66
86
  end
67
87
  end
68
- end
88
+
89
+ def create_default_doc_nips(doc_node, context)
90
+ node_name = doc_node['name']
91
+ machine_name = doc_node['machine']
92
+ machine_search_params = { 'name' => machine_name }
93
+ machine_proxy = @machine_search_resource.findByName machine_search_params
94
+ machine_resource = @rest_util.get_or_nil(machine_proxy, machine_search_params)
95
+
96
+ if machine_resource.nil?
97
+ err_msg = "Node #{node_name} references nonexistent machine #{machine_name}."
98
+ fail Util::InvalidDocumentError.new err_msg
99
+ end
100
+
101
+ [ {
102
+ 'ipAddressRole' => 'default',
103
+ 'ipAddress' => machine_resource.body['ipAddress']
104
+ } ]
105
+ end
106
+ end
69
107
  end
@@ -0,0 +1,46 @@
1
+ class Seiso::ImportMaster
2
+ # Imports a node IP address into Seiso.
3
+ #
4
+ # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
5
+ # Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
6
+ # License:: Apache 2.0
7
+ class Importers::NodeIpAddressImporter < Importers::BaseImporter
8
+
9
+ def initialize(api, rest_util)
10
+ self.api = api
11
+ self.rest_util = rest_util
12
+ self.mapper = Mappers::NodeIpAddressMapper.new api
13
+ self.repo_resource = api.nodeIpAddresses.get
14
+
15
+ @search_resource = repo_resource.search.get
16
+ end
17
+
18
+ # Can't make these protected, because that prevents BaseImporter from seeing them.
19
+ # protected
20
+
21
+ # BaseImporter callback
22
+ def to_search_params(doc_nip, context)
23
+
24
+ # FIXME For new nodes, we shouldn't have to look these up at all: nodes own NIPs, so the NIPs would be new too.
25
+ # So there ought to be a way to suppress NIP do-we-post-or-put lookups when we already know that we're creating a
26
+ # new node (and hence NIP).
27
+ #
28
+ # There is a case where we do need to look up the NIP. It's where we have an existing NIP and we want to change
29
+ # the IP address role. This feels a little weird to me since it seems like NIPs ought to be identified by
30
+ # <node, ipAddressRole> rathen than by <node, ipAddress>, but that's not how we've been doing it. [WLW]
31
+
32
+ {
33
+ 'node' => context['node'].name,
34
+ 'ipAddress' => doc_nip['ipAddress']
35
+ }
36
+ end
37
+
38
+ # BaseImporter callback
39
+ def find_resource(search_params)
40
+ node = search_params['node']
41
+ ip_addr = search_params['ipAddress']
42
+ # The .get is necessary to replace the finder URI with the canonical URI.
43
+ @search_resource.findByNodeNameAndIpAddress(node: node, ipAddress: ip_addr).get
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,31 @@
1
+ class Seiso::ImportMaster
2
+ class Importers::RegionImporter < Importers::BaseImporter
3
+
4
+ def initialize(api, rest_util, resolver)
5
+ @log = Util::Logger.new "RegionImporter"
6
+
7
+ self.api = api
8
+ self.rest_util = rest_util
9
+ self.mapper = Mappers::RegionMapper.new resolver
10
+ self.repo_resource = api.regions.get
11
+
12
+ @log.info "Getting /regions/search"
13
+ @search_resource = repo_resource.search.get
14
+ end
15
+
16
+ def import(doc)
17
+ @log.info "Importing regions"
18
+ import_items(doc['items'], {})
19
+ end
20
+
21
+ def to_search_params(doc_region, context)
22
+ { 'key' => doc_region['key'] }
23
+ end
24
+
25
+ def find_resource(search_params)
26
+ key = search_params['key']
27
+ @log.info "Getting /regions/search/findByKey?key=#{key}"
28
+ @search_resource.findByKey(key: key).get
29
+ end
30
+ end
31
+ end