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.
- checksums.yaml +8 -8
- data/.gitignore +1 -0
- data/.travis.yml +3 -0
- data/README.md +12 -11
- data/Rakefile +3 -3
- data/bin/seiso-import-master +30 -13
- data/lib/seiso/import_master.rb +114 -90
- data/lib/seiso/import_master/importers.rb +5 -0
- data/lib/seiso/import_master/importers/base_importer.rb +91 -30
- data/lib/seiso/import_master/importers/data_center_importer.rb +31 -0
- data/lib/seiso/import_master/importers/environment_importer.rb +25 -0
- data/lib/seiso/import_master/importers/health_status_importer.rb +25 -0
- data/lib/seiso/import_master/importers/infrastructure_provider_importer.rb +25 -0
- data/lib/seiso/import_master/importers/ip_address_role_importer.rb +41 -0
- data/lib/seiso/import_master/importers/load_balancer_importer.rb +25 -0
- data/lib/seiso/import_master/importers/machine_importer.rb +25 -0
- data/lib/seiso/import_master/importers/node_importer.rb +94 -56
- data/lib/seiso/import_master/importers/node_ip_address_importer.rb +46 -0
- data/lib/seiso/import_master/importers/region_importer.rb +31 -0
- data/lib/seiso/import_master/importers/rotation_status_importer.rb +25 -0
- data/lib/seiso/import_master/importers/service_group_importer.rb +25 -0
- data/lib/seiso/import_master/importers/service_importer.rb +38 -143
- data/lib/seiso/import_master/importers/service_instance_importer.rb +60 -213
- data/lib/seiso/import_master/importers/service_instance_port_importer.rb +41 -0
- data/lib/seiso/import_master/importers/service_type_importer.rb +25 -0
- data/lib/seiso/import_master/importers/status_type_importer.rb +25 -0
- data/lib/seiso/import_master/mappers.rb +1 -0
- data/lib/seiso/import_master/mappers/data_center_mapper.rb +19 -0
- data/lib/seiso/import_master/mappers/environment_mapper.rb +20 -0
- data/lib/seiso/import_master/mappers/health_status_mapper.rb +20 -0
- data/lib/seiso/import_master/mappers/infrastructure_provider_mapper.rb +18 -0
- data/lib/seiso/import_master/mappers/ip_address_role_mapper.rb +18 -0
- data/lib/seiso/import_master/mappers/load_balancer_mapper.rb +21 -0
- data/lib/seiso/import_master/mappers/machine_mapper.rb +27 -0
- data/lib/seiso/import_master/mappers/node_ip_address_mapper.rb +38 -0
- data/lib/seiso/import_master/mappers/node_mapper.rb +31 -31
- data/lib/seiso/import_master/mappers/region_mapper.rb +20 -0
- data/lib/seiso/import_master/mappers/rotation_status_mapper.rb +20 -0
- data/lib/seiso/import_master/mappers/service_group_mapper.rb +18 -0
- data/lib/seiso/import_master/mappers/service_instance_mapper.rb +26 -73
- data/lib/seiso/import_master/mappers/service_instance_port_mapper.rb +19 -0
- data/lib/seiso/import_master/mappers/service_mapper.rb +23 -32
- data/lib/seiso/import_master/mappers/service_type_mapper.rb +19 -0
- data/lib/seiso/import_master/mappers/status_type_mapper.rb +18 -0
- data/lib/seiso/import_master/util.rb +1 -0
- data/lib/seiso/import_master/util/invalid_document_error.rb +9 -0
- data/lib/seiso/import_master/util/item_resolver.rb +54 -0
- data/lib/seiso/import_master/util/logger.rb +59 -0
- data/lib/seiso/import_master/util/rest_util.rb +49 -0
- data/lib/seiso/import_master/validators.rb +1 -0
- data/lib/seiso/import_master/validators/base_validator.rb +11 -18
- data/lib/seiso/import_master/validators/node_validator.rb +54 -45
- data/lib/seiso/import_master/validators/service_validator.rb +38 -44
- data/sample_conf/seiso3.yml.sample +6 -0
- data/seiso-import_master.gemspec +16 -13
- data/test/seiso/import_master/importers/test_node_importer.rb +21 -0
- metadata +66 -21
- data/lib/seiso/import_master/errors/invalid_document_error.rb +0 -11
- data/lib/seiso/import_master/importers/simple_importer.rb +0 -28
- data/lib/seiso/import_master/mappers/master_item_mapper.rb +0 -194
- data/sample_conf/seiso.yml.sample +0 -9
- data/test/test_master_item_mapper.rb +0 -257
- data/test/test_node_mapper.rb +0 -40
@@ -0,0 +1,19 @@
|
|
1
|
+
class Seiso::ImportMaster
|
2
|
+
# Maps a SDM IP address role to a Seiso IP address role.
|
3
|
+
#
|
4
|
+
# Author:: Willie Wheeler
|
5
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
6
|
+
# License:: Apache 2.0
|
7
|
+
class Mappers::ServiceInstancePortMapper
|
8
|
+
|
9
|
+
def map(doc_sip, context)
|
10
|
+
si_uri = context['serviceInstance'].href
|
11
|
+
{
|
12
|
+
'serviceInstance' => si_uri,
|
13
|
+
'number' => doc_sip['number'],
|
14
|
+
'protocol' => doc_sip['protocol'],
|
15
|
+
'description' => doc_sip['description']
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,35 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
class Seiso::ImportMaster
|
2
|
+
# Author:: Willie Wheeler
|
3
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
4
|
+
# License:: Apache 2.0
|
5
|
+
class Mappers::ServiceMapper
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
|
9
|
-
# License:: Apache 2.0
|
10
|
-
class ServiceMapper
|
7
|
+
def initialize(resolver)
|
8
|
+
@resolver = resolver
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
11
|
+
# Maps a document service to a Seiso service.
|
12
|
+
#
|
13
|
+
# - doc_service : document service
|
14
|
+
def map(doc_service, context)
|
15
|
+
{
|
16
|
+
'key' => doc_service['key'],
|
17
|
+
'name' => doc_service['name'],
|
18
|
+
'platform' => doc_service['platform'],
|
19
|
+
'scmRepository' => doc_service['scmRepository'],
|
20
|
+
'group' => @resolver.item_uri('serviceGroups', doc_service['group']),
|
21
|
+
'type' => @resolver.item_uri('serviceTypes', doc_service['type']),
|
22
|
+
'owner' => @resolver.item_uri('persons', doc_service['owner'])
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
35
26
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Seiso::ImportMaster
|
2
|
+
# Author:: Willie Wheeler
|
3
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
4
|
+
# License:: Apache 2.0
|
5
|
+
class Mappers::ServiceTypeMapper
|
6
|
+
|
7
|
+
def initialize(resolver)
|
8
|
+
@resolver = resolver
|
9
|
+
end
|
10
|
+
|
11
|
+
def map(doc_st, context)
|
12
|
+
{
|
13
|
+
'key' => doc_st['key'],
|
14
|
+
'name' => doc_st['name'],
|
15
|
+
'description' => doc_st['description']
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Seiso::ImportMaster
|
2
|
+
# Author:: Willie Wheeler
|
3
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
4
|
+
# License:: Apache 2.0
|
5
|
+
class Mappers::StatusTypeMapper
|
6
|
+
|
7
|
+
def initialize(resolver)
|
8
|
+
@resolver = resolver
|
9
|
+
end
|
10
|
+
|
11
|
+
def map(doc_st, context)
|
12
|
+
{
|
13
|
+
'key' => doc_st['key'],
|
14
|
+
'name' => doc_st['name']
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
module Seiso::ImportMaster::Util; end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Seiso::ImportMaster
|
2
|
+
|
3
|
+
# Resolves item keys to their URIs.
|
4
|
+
#
|
5
|
+
# Author:: Willie Wheeler
|
6
|
+
# Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
|
7
|
+
# License:: Apache 2.0
|
8
|
+
#
|
9
|
+
class Util::ItemResolver
|
10
|
+
|
11
|
+
def initialize(api)
|
12
|
+
@log = Util::Logger.new "ItemResolver"
|
13
|
+
@api = api
|
14
|
+
|
15
|
+
# Note that this initialization doesn't generate any HTTP requests.
|
16
|
+
@special_searches = {
|
17
|
+
# http://ruby-journal.com/becareful-with-space-in-lambda-hash-rocket-syntax-between-ruby-1-dot-9-and-2-dot-0/
|
18
|
+
'loadBalancers' => ->(k) { @api.loadBalancers.search.findByName(name: k) },
|
19
|
+
'machines' => ->(k) { @api.machines.search.findByName(name: k) },
|
20
|
+
'persons' => ->(k) { @api.persons.search.findByUsername(username: k) }
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the item URI, or nil if either key is nil or the item doesn't exist.
|
25
|
+
def item_uri(type, key)
|
26
|
+
@log.info "Getting item URI: type=#{type}, key=#{key}"
|
27
|
+
return nil if key.nil?
|
28
|
+
search = @special_searches[type]
|
29
|
+
|
30
|
+
if search == nil
|
31
|
+
item = @api.send(type).search.findByKey(key: key)
|
32
|
+
else # special search
|
33
|
+
item = search.call key
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
# This returns the item's canonical URI, which is what we want.
|
38
|
+
item.links.self.href
|
39
|
+
rescue HyperResource::ClientError => e
|
40
|
+
status = e.response.status
|
41
|
+
body = e.response.body
|
42
|
+
raise "Response error: status=#{status}, body=#{body}" unless status == 404
|
43
|
+
@log.warn "#{type}/#{key} not found. Returning nil."
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# TODO Implementation based on HTTP 1.1 keepalive. The resolution above is too slow.
|
49
|
+
def item_uri_via_keepalive(type, key)
|
50
|
+
@log.info "Getting item URL: type=#{type}, key=#{key}"
|
51
|
+
# TODO
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class Seiso::ImportMaster
|
2
|
+
|
3
|
+
# TODO Allow clients to enable/disable color codes. [WLW]
|
4
|
+
class Util::Logger
|
5
|
+
|
6
|
+
def initialize(name)
|
7
|
+
@name = name
|
8
|
+
end
|
9
|
+
|
10
|
+
def info(message)
|
11
|
+
puts "[INFO] #{@name} : #{message}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def success(message)
|
15
|
+
puts "[SUCCESS] #{@name} : #{message}".green
|
16
|
+
end
|
17
|
+
|
18
|
+
def warn(message)
|
19
|
+
puts "[WARN] #{@name} : #{message}".yellow
|
20
|
+
end
|
21
|
+
|
22
|
+
def error(message)
|
23
|
+
STDERR.puts "[ERROR] #{@name} : #{message}".red
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# http://stackoverflow.com/questions/1489183/colorized-ruby-output
|
29
|
+
# FIXME Move to more appropriate location. Not sure where something like this should go. [WLW]
|
30
|
+
class String
|
31
|
+
|
32
|
+
def colorize(color_code)
|
33
|
+
"\e[#{color_code}m#{self}\e[0m"
|
34
|
+
end
|
35
|
+
|
36
|
+
def red
|
37
|
+
colorize(31)
|
38
|
+
end
|
39
|
+
|
40
|
+
def green
|
41
|
+
colorize(32)
|
42
|
+
end
|
43
|
+
|
44
|
+
def yellow
|
45
|
+
colorize(33)
|
46
|
+
end
|
47
|
+
|
48
|
+
def blue
|
49
|
+
colorize(34)
|
50
|
+
end
|
51
|
+
|
52
|
+
def pink
|
53
|
+
colorize(35)
|
54
|
+
end
|
55
|
+
|
56
|
+
def light_blue
|
57
|
+
colorize(36)
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'awesome_print'
|
2
|
+
|
3
|
+
class Seiso::ImportMaster
|
4
|
+
# Author:: Willie Wheeler
|
5
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
6
|
+
# License:: Apache 2.0
|
7
|
+
class Util::RestUtil
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@log = Util::Logger.new "RestUtil"
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_or_nil(resource, description)
|
14
|
+
resource_uri = resource.links.self.href
|
15
|
+
begin
|
16
|
+
@log.info "GET #{resource_uri} (#{description})"
|
17
|
+
return resource.get
|
18
|
+
rescue HyperResource::ClientError => e
|
19
|
+
status = e.response.status
|
20
|
+
body = e.response.body
|
21
|
+
raise "Response error: status=#{status}, body=#{body}" unless status == 404
|
22
|
+
@log.warn "Resource #{description} not found. Returning nil."
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def post(repo_resource, data, description)
|
28
|
+
repo_resource_uri = repo_resource.links.self.href
|
29
|
+
@log.info "POST #{repo_resource_uri} (#{description})"
|
30
|
+
response = repo_resource.post data
|
31
|
+
# TODO Read the status from the response if possible. [WLW]
|
32
|
+
@log.info " 201 Created: #{response.href}"
|
33
|
+
# response.href
|
34
|
+
response
|
35
|
+
end
|
36
|
+
|
37
|
+
def put(resource, data, description)
|
38
|
+
resource_uri = resource.links.self.href
|
39
|
+
@log.info "PUT #{resource_uri} (#{description})"
|
40
|
+
resource.put data
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete(resource, description)
|
44
|
+
resource_uri = resource.links.self.href
|
45
|
+
@log.info "DELETE #{resource_uri} (#{description})"
|
46
|
+
resource.delete
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
module Seiso::ImportMaster::Validators; end
|
@@ -1,19 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
# Raises an InvalidDocumentError with the given message.
|
13
|
-
def error(msg)
|
14
|
-
raise Seiso::ImportMaster::Errors::InvalidDocumentError.new msg
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
1
|
+
class Seiso::ImportMaster
|
2
|
+
# Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
|
3
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
4
|
+
# License:: Apache 2.0
|
5
|
+
class Validators::BaseValidator
|
6
|
+
# Raises an InvalidDocumentError with the given message.
|
7
|
+
# TODO Move to module method instead?
|
8
|
+
def error(msg)
|
9
|
+
fail Util::InvalidDocumentError.new msg
|
10
|
+
end
|
11
|
+
end
|
19
12
|
end
|
@@ -1,46 +1,55 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
1
|
+
module Seiso::ImportMaster::Validators
|
2
|
+
# Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
|
3
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
4
|
+
# License:: Apache 2.0
|
5
|
+
class NodeValidator < BaseValidator
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@log = Seiso::ImportMaster::Util::Logger.new "NodeValidator"
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate(doc)
|
12
|
+
# @log.info "Validating nodes"
|
13
|
+
validate_si_key doc
|
14
|
+
validate_nodes doc
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def validate_si_key(doc)
|
20
|
+
si_key = doc['serviceInstance']
|
21
|
+
|
22
|
+
if si_key.nil?
|
23
|
+
error 'Node document must contain a serviceInstance field containing the service instance key.'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate_nodes(doc)
|
28
|
+
nodes = doc['items']
|
29
|
+
|
30
|
+
if nodes.nil?
|
31
|
+
error "Node document must contain an items field containing the service instance's nodes."
|
32
|
+
end
|
33
|
+
|
34
|
+
nodes.each do |n|
|
35
|
+
node_name = n['name']
|
36
|
+
|
37
|
+
if node_name.nil?
|
38
|
+
error "Every node must have a name."
|
39
|
+
end
|
40
|
+
|
41
|
+
# Fail if the node has a serviceInstance field. This is legacy, and we don't want it anymore, because
|
42
|
+
# people will think that they can move a node from one service instance to another by changing this field.
|
43
|
+
if n['serviceInstance']
|
44
|
+
error "Node #{node_name} must not contain a serviceInstance field. " \
|
45
|
+
"Specify the service instance using the document-level serviceInstance field."
|
46
|
+
end
|
47
|
+
|
48
|
+
if n['machine'].nil?
|
49
|
+
error "Node #{node_name} must have a machine."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
46
55
|
end
|
@@ -1,45 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
1
|
+
module Seiso::ImportMaster::Validators
|
2
|
+
# Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
|
3
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
4
|
+
# License:: Apache 2.0
|
5
|
+
class ServiceValidator < BaseValidator
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@log = Seiso::ImportMaster::Util::Logger.new "ServiceValidator"
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate(doc)
|
12
|
+
# @log.info "Validating services"
|
13
|
+
validate_services doc
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def validate_services(doc)
|
19
|
+
services = doc['items']
|
20
|
+
|
21
|
+
if services.nil?
|
22
|
+
error 'Service document must contain an items field containing the services.'
|
23
|
+
end
|
24
|
+
|
25
|
+
services.each { |s| validate_service s }
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate_service(s)
|
29
|
+
key = s['key']
|
30
|
+
error 'Service must have a key' if key.nil?
|
31
|
+
name = s['name']
|
32
|
+
error 'Service must have a name' if name.nil?
|
33
|
+
|
34
|
+
# This isn't required!
|
35
|
+
# type = s['type']
|
36
|
+
# error 'Service must have a type' if type.nil?
|
37
|
+
end
|
38
|
+
end
|
44
39
|
end
|
45
|
-
|