seiso-import_master 0.0.12 → 3.0.0.M1

Sign up to get free protection for your applications and to get access to all the features.
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