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.
- checksums.yaml +8 -8
- data/README.md +14 -0
- data/Rakefile +3 -1
- data/lib/seiso/import_master.rb +61 -75
- data/lib/seiso/import_master/errors/invalid_document_error.rb +11 -0
- data/lib/seiso/import_master/importers/base_importer.rb +26 -0
- data/lib/seiso/import_master/importers/node_importer.rb +79 -0
- data/lib/seiso/import_master/importers/service_importer.rb +135 -0
- data/lib/seiso/import_master/importers/service_instance_importer.rb +40 -0
- data/lib/seiso/import_master/importers/simple_importer.rb +28 -0
- data/lib/seiso/import_master/mappers/master_item_mapper.rb +189 -0
- data/lib/seiso/import_master/mappers/node_mapper.rb +33 -0
- data/lib/seiso/import_master/mappers/service_instance_mapper.rb +62 -0
- data/lib/seiso/import_master/mappers/service_mapper.rb +35 -0
- data/lib/seiso/import_master/util/rest_connector.rb +102 -0
- data/lib/seiso/import_master/util/uri_factory_v1.rb +61 -0
- data/lib/seiso/import_master/util/uri_factory_v2.rb +34 -0
- data/lib/seiso/import_master/validators/base_validator.rb +19 -0
- data/lib/seiso/import_master/validators/node_validator.rb +46 -0
- data/lib/seiso/import_master/validators/service_validator.rb +45 -0
- data/seiso-import_master.gemspec +4 -1
- data/test/test_master_item_mapper.rb +5 -30
- data/test/test_node_mapper.rb +40 -0
- metadata +36 -6
- data/lib/seiso/import_master/master_item_mapper.rb +0 -295
- data/refresh +0 -2
@@ -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
|