seiso-import_master 0.0.6 → 0.0.7

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.
@@ -0,0 +1,40 @@
1
+ require_relative "base_importer"
2
+
3
+ module Seiso
4
+ class ImportMaster
5
+ module Importers
6
+
7
+ # Imports a service instance document into Seiso.
8
+ #
9
+ # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
10
+ # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
11
+ # License:: Apache 2.0
12
+ class ServiceInstanceImporter < BaseImporter
13
+
14
+ def initialize(mapper, seiso, uri_factory_v1, rest_connector_v1)
15
+ @mapper = mapper
16
+ @seiso = seiso
17
+ @uri_factory_v1 = uri_factory_v1
18
+ @rest_connector_v1 = rest_connector_v1
19
+ end
20
+
21
+ # Imports the service instance document
22
+ def import(doc)
23
+ service_instances = doc['items']
24
+ ports = detach_children(service_instances, 'serviceInstance', 'key', 'ports')
25
+ roles = detach_children(service_instances, 'serviceInstance', 'key', 'ipAddressRoles')
26
+
27
+ seiso_service_instances = service_instances.map { |si| @mapper.seiso_service_instance si }
28
+ service_instances_uri = @uri_factory_v1.service_instances_uri true
29
+ @rest_connector_v1.post(service_instances_uri, seiso_service_instances)
30
+
31
+ seiso_ports = ports.map { |p| @mapper.seiso_service_instance_port p }
32
+ @seiso.post_items('service-instance-ports', seiso_ports)
33
+
34
+ seiso_roles = roles.map { |r| @mapper.seiso_ip_address_role r }
35
+ @seiso.post_items('ip-address-roles', seiso_roles)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ require_relative "base_importer"
2
+
3
+ module Seiso
4
+ class ImportMaster
5
+ module Importers
6
+
7
+ # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
8
+ # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
9
+ # License:: Apache 2.0
10
+ class SimpleImporter < BaseImporter
11
+
12
+ def initialize(mapper, seiso, uri_factory_v1, rest_connector_v1)
13
+ @mapper = mapper
14
+ @seiso = seiso
15
+ @uri_factory_v1 = uri_factory_v1
16
+ @rest_connector_v1 = rest_connector_v1
17
+ end
18
+
19
+ def import(doc)
20
+ type = doc['type']
21
+ items = doc['items']
22
+ seiso_items = @mapper.map_all(type, items)
23
+ @seiso.post_items(type, seiso_items)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,189 @@
1
+ module Seiso
2
+ class ImportMaster
3
+ module Mappers
4
+
5
+ # Maps the data master format to the Seiso API format.
6
+ #
7
+ # Author:: Willie Wheeler
8
+ # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
9
+ # License:: Apache 2.0
10
+ class MasterItemMapper
11
+
12
+ def initialize
13
+ @mappers = {
14
+ 'data-centers' => data_center_mapper,
15
+ 'doc-links' => doc_link_mapper,
16
+ 'environments' => environment_mapper,
17
+ 'health-statuses' => health_status_mapper,
18
+ 'infrastructure-providers' => infrastructure_provider_mapper,
19
+ 'load-balancers' => load_balancer_mapper,
20
+ 'machines' => machine_mapper,
21
+ 'regions' => region_mapper,
22
+ 'rotation-statuses' => rotation_status_mapper,
23
+ 'service-groups' => service_group_mapper,
24
+ 'service-types' => service_type_mapper,
25
+ 'status-types' => status_type_mapper
26
+ }
27
+ end
28
+
29
+ # Maps a list of items.
30
+ # - type: Item type
31
+ # - items: Item list
32
+ def map_all(type, items)
33
+ mapper = mapper_for type
34
+ result = []
35
+ items.each { |i| result << mapper.call(i) }
36
+ result
37
+ end
38
+
39
+ # Maps a single item.
40
+ # - type: Item type
41
+ # - item: Item
42
+ def map_one(type, item)
43
+ mapper_for(type).call item
44
+ end
45
+
46
+ private
47
+
48
+ # Returns a mapper lambda for the specified type.
49
+ def mapper_for(type)
50
+ mapper = @mappers[type]
51
+ raise ArgumentError, "Unknown type: #{type}" if mapper.nil?
52
+ mapper
53
+ end
54
+
55
+ def data_center_mapper
56
+ ->(dc) {
57
+ {
58
+ 'key' => dc['key'],
59
+ 'name' => dc['name'],
60
+ 'region' => { 'key' => dc['region'] }
61
+ }
62
+ }
63
+ end
64
+
65
+ def doc_link_mapper
66
+ ->(dl) {
67
+ {
68
+ 'title' => dl['title'],
69
+ 'href' => dl['href'],
70
+ 'description' => dl['description']
71
+ }
72
+ }
73
+ end
74
+
75
+ def environment_mapper
76
+ ->(e) {
77
+ {
78
+ 'key' => e['key'],
79
+ 'name' => e['name'],
80
+ 'aka' => e['aka'],
81
+ 'description' => e['description'],
82
+
83
+ # FIXME Deprecated, don't use.
84
+ 'rank' => e['rank']
85
+ }
86
+ }
87
+ end
88
+
89
+ def health_status_mapper
90
+ ->(hs) {
91
+ {
92
+ 'key' => hs['key'],
93
+ 'name' => hs['name'],
94
+ 'statusType' => { 'key' => hs['statusType'] }
95
+ }
96
+ }
97
+ end
98
+
99
+ def infrastructure_provider_mapper
100
+ ->(ip) {
101
+ {
102
+ 'key' => ip['key'],
103
+ 'name' => ip['name']
104
+ }
105
+ }
106
+ end
107
+
108
+ def load_balancer_mapper
109
+ ->(lb) {
110
+ seiso_lb = {
111
+ 'name' => lb['name'],
112
+ 'type' => lb['type'],
113
+ 'ipAddress' => lb['ipAddress'],
114
+ 'apiUrl' => lb['apiUrl']
115
+ }
116
+
117
+ dc = lb['dataCenter']
118
+ seiso_lb['dataCenter'] = { 'key' => dc } unless dc.nil?
119
+
120
+ seiso_lb
121
+ }
122
+ end
123
+
124
+ def machine_mapper
125
+ ->(m) {
126
+ {
127
+ 'name' => m['name'],
128
+ 'ipAddress' => m['ipAddress'],
129
+ 'fqdn' => m['fqdn'],
130
+ 'hostname' => m['hostname'],
131
+ 'domain' => m['domain'],
132
+ 'os' => m['os'],
133
+ 'platform' => m['platform'],
134
+ 'platformVersion' => m['platformVersion']
135
+ }
136
+ }
137
+ end
138
+
139
+ def region_mapper
140
+ ->(r) {
141
+ {
142
+ 'key' => r['key'],
143
+ 'name' => r['name'],
144
+ 'regionKey' => r['regionKey'],
145
+ 'infrastructureProvider' => { 'key' => r['infrastructureProvider'] }
146
+ }
147
+ }
148
+ end
149
+
150
+ def rotation_status_mapper
151
+ ->(rs) {
152
+ {
153
+ 'key' => rs['key'],
154
+ 'name' => rs['name'],
155
+ 'statusType' => { 'key' => rs['statusType'] }
156
+ }
157
+ }
158
+ end
159
+
160
+ def service_group_mapper
161
+ ->(sg) {
162
+ {
163
+ 'key' => sg['key'],
164
+ 'name' => sg['name']
165
+ }
166
+ }
167
+ end
168
+
169
+ def service_type_mapper
170
+ ->(st) {
171
+ {
172
+ 'key' => st['key'],
173
+ 'name' => st['name']
174
+ }
175
+ }
176
+ end
177
+
178
+ def status_type_mapper
179
+ ->(st) {
180
+ {
181
+ 'key' => st['key'],
182
+ 'name' => st['name']
183
+ }
184
+ }
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,33 @@
1
+ module Seiso
2
+ class ImportMaster
3
+ module Mappers
4
+
5
+ # Maps a SDM node to a Seiso node.
6
+ #
7
+ # Author:: Willie Wheeler
8
+ # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
9
+ # License:: Apache 2.0
10
+ class NodeMapper
11
+
12
+ def seiso_node(n)
13
+ seiso_node = {
14
+ 'name' => n['name'],
15
+ 'serviceInstance' => { 'key' => n['serviceInstance'] }
16
+ }
17
+ machine = n['machine']
18
+ seiso_node['machine'] = { 'name' => machine } unless machine.nil?
19
+ seiso_node
20
+ end
21
+
22
+ def seiso_nip(nip)
23
+ # No rotation status or endpoints since we don't import those from master files.
24
+ {
25
+ 'node' => { 'name' => nip['node'] },
26
+ 'ipAddressRole' => { 'name' => nip['ipAddressRole'] },
27
+ 'ipAddress' => nip['ipAddress']
28
+ }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,62 @@
1
+ module Seiso
2
+ class ImportMaster
3
+ module Mappers
4
+
5
+ # Maps a SDM service instance to a Seiso service instance.
6
+ #
7
+ # Author:: Willie Wheeler
8
+ # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
9
+ # License:: Apache 2.0
10
+ class ServiceInstanceMapper
11
+
12
+ def seiso_ip_address_role(r)
13
+ # Suppressing IP addresses since we don't import those from master files.
14
+ {
15
+ 'serviceInstance' => { 'key' => r['serviceInstance'] },
16
+ 'name' => r['name'],
17
+ 'description' => r['description']
18
+ }
19
+ end
20
+
21
+ def seiso_service_instance(si)
22
+ key = si['key']
23
+ ip_address_roles = si['ipAddressRoles']
24
+ ports = si['ports']
25
+
26
+ seiso_si = {
27
+ 'key' => key,
28
+ 'service' => { 'key' => si['service'] },
29
+ 'environment' => { 'key' => si['environment'] },
30
+ 'loadBalanced' => si['loadBalanced'],
31
+ 'minCapacityDeploy' => si['minCapacityDeploy'],
32
+ 'minCapacityOps' => si['minCapacityOps'],
33
+
34
+ # FIXME Deprecated. This is a hardcoded field for an internal Expedia app, and we will remove it.
35
+ 'eosManaged' => (si['eosManaged'] || false),
36
+
37
+ # FIXME Deprecated. This is the old name for the minCapacityOps field.
38
+ 'requiredCapacity' => si['minCapacityOps']
39
+ }
40
+
41
+ data_center = si['dataCenter']
42
+ seiso_si['dataCenter'] = { 'key' => data_center } unless data_center.nil?
43
+
44
+ load_balancer = si['loadBalancer']
45
+ seiso_si['loadBalancer'] = { 'name' => load_balancer } unless load_balancer.nil?
46
+
47
+ seiso_si
48
+ end
49
+
50
+ def seiso_service_instance_port(p)
51
+ # Suppressing endpoints since we don't import those from master files.
52
+ {
53
+ 'serviceInstance' => { 'key' => p['serviceInstance'] },
54
+ 'number' => p['number'],
55
+ 'protocol' => p['protocol'],
56
+ 'description' => p['description']
57
+ }
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,35 @@
1
+ module Seiso
2
+ class ImportMaster
3
+ module Mappers
4
+
5
+ # Maps a SDM service to a Seiso service.
6
+ #
7
+ # Author:: Willie Wheeler
8
+ # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
9
+ # License:: Apache 2.0
10
+ class ServiceMapper
11
+
12
+ def seiso_service(s)
13
+ seiso_service = {
14
+ 'key' => s['key'],
15
+ 'name' => s['name'],
16
+ 'description' => s['description'],
17
+ 'platform' => s['platform'],
18
+ 'scmRepository' => s['scmRepository']
19
+ }
20
+
21
+ group = s['group']
22
+ seiso_service['group'] = { 'key' => group } unless group.nil?
23
+
24
+ type = s['type']
25
+ seiso_service['type'] = { 'key' => type } unless type.nil?
26
+
27
+ owner = s['owner']
28
+ seiso_service['owner'] = { 'username' => owner } unless owner.nil?
29
+
30
+ seiso_service
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,102 @@
1
+ require "json"
2
+ require "net/http"
3
+ require "openssl"
4
+
5
+ module Seiso
6
+ class ImportMaster
7
+ module Util
8
+
9
+ # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
10
+ # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
11
+ # License:: Apache 2.0
12
+ class RestConnector
13
+ HN_ACCEPT = "Accept"
14
+ HN_CONTENT_TYPE = "Content-Type"
15
+
16
+ def initialize(host, port, use_ssl, ignore_cert, username, password, media_type)
17
+ @host = host
18
+ @port = port
19
+ @use_ssl = use_ssl
20
+ @ignore_cert = ignore_cert
21
+ @username = username
22
+ @password = password
23
+ @media_type = media_type
24
+
25
+ # FIXME Not secure
26
+ @verify_mode = OpenSSL::SSL::VERIFY_NONE if @use_ssl
27
+ end
28
+
29
+ def get(uri)
30
+ request = Net::HTTP::Get.new uri.request_uri
31
+ request[HN_ACCEPT] = @media_type
32
+ request.basic_auth(@username, @password)
33
+ do_request(http, request)
34
+ end
35
+
36
+ def post(uri, resource)
37
+ request = Net::HTTP::Post.new uri.request_uri
38
+ request[HN_CONTENT_TYPE] = @media_type
39
+ request.basic_auth(@username, @password)
40
+ request.body = resource.to_json
41
+ do_request(http, request)
42
+ end
43
+
44
+ # Puts all resources using a keepalive connection
45
+ def put_all(uri_resource_pairs)
46
+ Net::HTTP.start(
47
+ @host,
48
+ @port,
49
+ :use_ssl => @use_ssl,
50
+ :verify_mode => @verify_mode) do |http|
51
+
52
+ uri_resource_pairs.each do |pair|
53
+ pair_uri = pair['uri']
54
+ pair_resource = pair['resource']
55
+ request = Net::HTTP::Put.new pair_uri.request_uri
56
+ request[HN_CONTENT_TYPE] = @media_type
57
+ request.basic_auth(@username, @password)
58
+ request.body = pair_resource.to_json
59
+ do_request(http, request)
60
+ end
61
+ end
62
+ end
63
+
64
+ def put(uri, resource)
65
+ request = Net::HTTP::Put.new uri.request_uri
66
+ request[HN_CONTENT_TYPE] = @media_type
67
+ request.basic_auth(@username, @password)
68
+ request.body = resource.to_json
69
+ do_request(http, request)
70
+ end
71
+
72
+ def delete(uri)
73
+ puts "DELETE #{uri}"
74
+ request = Net::HTTP::Delete.new uri.request_uri
75
+ request.basic_auth(@username, @password)
76
+ do_request(http, request)
77
+ end
78
+
79
+ private
80
+
81
+ def http
82
+ # Not sure if I can reuse this, so for now I'm just creating a new one every time.
83
+ http = Net::HTTP.new(@host, @port)
84
+ http.use_ssl = @use_ssl
85
+ http.verify_mode = @verify_mode
86
+ http
87
+ end
88
+
89
+ def do_request(http, request)
90
+ response = http.request request
91
+
92
+ if response.code.start_with?("4") || response.code.start_with?("5")
93
+ details = "(#{JSON.parse response.body})"
94
+ end
95
+ puts "#{request.method} #{request.path} => #{response.code} #{response.message} #{details}"
96
+ response
97
+ end
98
+
99
+ end # class RestConnector
100
+ end # module Util
101
+ end # class ImportMaster
102
+ end # module Seiso