seiso-import_master 0.0.12 → 3.0.0.M1

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.
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
-