seiso-import_master 0.0.6 → 0.0.7

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