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,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
- module Seiso
2
- class ImportMaster
3
- module Mappers
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
- # 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
7
+ def initialize(resolver)
8
+ @resolver = resolver
9
+ end
11
10
 
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
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,9 @@
1
+ # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
2
+ # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
3
+ # License:: Apache 2.0
4
+ class Seiso::ImportMaster::Util::InvalidDocumentError < StandardError
5
+
6
+ def initialize(message)
7
+ super
8
+ end
9
+ 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
- require_relative "../errors/invalid_document_error"
2
-
3
- module Seiso
4
- class ImportMaster
5
- module Validators
6
-
7
- # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
8
- # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
9
- # License:: Apache 2.0
10
- class BaseValidator
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
- require_relative "base_validator"
2
-
3
- module Seiso
4
- class ImportMaster
5
- module Validators
6
-
7
- # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
8
- # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
9
- # License:: Apache 2.0
10
- class NodeValidator < BaseValidator
11
-
12
- def validate(doc)
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
- # Fail if the node has a serviceInstance field. This is legacy, and we don't want it anymore, because
35
- # people will think that they can move a node from one service instance to another by changing this field.
36
- nodes.each do |n|
37
- if n['serviceInstance']
38
- error "Individual nodes must not contain a serviceInstance field. " \
39
- "Specify the service instance using the document-level serviceInstance field."
40
- end
41
- end
42
- end
43
- end
44
- end
45
- 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 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
- require_relative "base_validator"
2
-
3
- module Seiso
4
- class ImportMaster
5
- module Validators
6
-
7
- # Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
8
- # Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
9
- # License:: Apache 2.0
10
- class ServiceValidator < BaseValidator
11
-
12
- def validate(doc)
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
-
31
- if key.nil?
32
- error "Service must have a key"
33
- end
34
-
35
- name = s['name']
36
-
37
- if name.nil?
38
- error "Service must have a name"
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
-