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.
- 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
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MTk2ZjJlYzk0YTA2YzVhN2IwOWEyZWM3NWM3Y2MwMjc3MjI0ZTNkOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTM0NDk1MTQ1YmIxM2Y5OTdmMzc4ZTE4MWY5ZmU0NjM4MjcxYmY3Ng==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YTkwNmE2N2E5M2FlMzZkN2FmNGZjOGEyODFjNmNmOTJmMWMxMThiYmJmMTY2
|
10
|
+
ZGY2YmQwZTIxMjU3MTkwYWJjMGFlYjU0YWI3ZjM3MjRlYmVlYTUyMGVkY2Ux
|
11
|
+
MDQ0NDUzODhlZmVjYjFkNDJhNGQ5Mjk3N2Q5YjRmNTNjMTc5MDM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTI5ZGI3Y2E4NmFkMzg4YjlkMGRjNWQwMDcyODMxMWQxZGU0ZTIxNjU2OWQw
|
14
|
+
OGE5YjM4YTEwNzhlNzM1NjhjMDcyMTdjNGNjNzM3YzA4MDMzNTcxMmM4M2Yx
|
15
|
+
MmZmMjFmOTk4MDRlMDFlZjllN2I3NTRhOThjMDk3YWNmYzBjNTc=
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -10,26 +10,20 @@ See [Manage Your Service Data with GitHub, Jenkins & Seiso](http://seiso.io/guid
|
|
10
10
|
|
11
11
|
See [Seiso Data Master Schemas](http://seiso.io/docs/current/user-manual/sdm-schemas/) for the data master schemas.
|
12
12
|
|
13
|
-
## Installation
|
14
|
-
|
15
|
-
Add this line to your application's Gemfile:
|
13
|
+
## Installation preliminaries
|
16
14
|
|
17
|
-
|
18
|
-
gem 'seiso-import_master'
|
19
|
-
```
|
15
|
+
First, I recommend using [RVM](http://rvm.io/) to install/manage your rubies so you can run multiple rubies without conflict.
|
20
16
|
|
21
|
-
|
17
|
+
You will need Ruby 1.9.3 as well as [Bundler](http://bundler.io).
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
Or install it yourself as:
|
19
|
+
## Installation
|
26
20
|
|
27
21
|
$ gem install seiso-import_master
|
28
22
|
|
29
23
|
## Usage
|
30
24
|
|
31
25
|
1. Create a directory `~/.seiso-importers`
|
32
|
-
2. Place appropriately modified copy of `
|
26
|
+
2. Place appropriately modified copy of `seiso3.yml.sample` in there. Note that you will need to get Seiso credentials from your Seiso administrator.
|
33
27
|
3. Run `seiso-import-master file [, file2, ...]` to perform the import. Note that you can use `-f yaml` for YAML files (the default is `-f json`).
|
34
28
|
|
35
29
|
## Contributing
|
@@ -53,3 +47,10 @@ In particular, run the unit tests using
|
|
53
47
|
Build and install the gem using Rake:
|
54
48
|
|
55
49
|
$ rake install
|
50
|
+
|
51
|
+
For local snapshot installations, you may want to clear out existing versions of the gem first.
|
52
|
+
|
53
|
+
## TODO
|
54
|
+
|
55
|
+
Figure out whether we want to use dependency injection for this project. There's debate within the Ruby community
|
56
|
+
whether DI makes sense for Ruby.
|
data/Rakefile
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
3
|
|
4
4
|
task :default => [ :test ]
|
5
5
|
|
@@ -11,7 +11,7 @@ end
|
|
11
11
|
|
12
12
|
Rake::TestTask.new do |t|
|
13
13
|
t.libs << 'test'
|
14
|
-
t.test_files = FileList[ 'test
|
14
|
+
t.test_files = FileList[ 'test/**/test_*.rb' ]
|
15
15
|
t.verbose = true
|
16
16
|
t.warning = true
|
17
17
|
end
|
data/bin/seiso-import-master
CHANGED
@@ -3,31 +3,33 @@
|
|
3
3
|
# vi: set ft=ruby :
|
4
4
|
|
5
5
|
require 'optparse'
|
6
|
-
require 'seiso/import_master'
|
7
6
|
require 'yaml'
|
7
|
+
require 'seiso/import_master'
|
8
8
|
|
9
9
|
# Imports Seiso data master files into Seiso.
|
10
10
|
#
|
11
11
|
# Author:: Willie Wheeler
|
12
|
-
# Copyright:: Copyright (c) 2014-
|
12
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
13
13
|
# License:: Apache 2.0
|
14
14
|
|
15
|
+
log = Seiso::ImportMaster::Util::Logger.new "seiso-import-master"
|
16
|
+
|
15
17
|
options = {}
|
16
18
|
option_parser = OptionParser.new do |opts|
|
17
19
|
executable_name = File.basename $PROGRAM_NAME
|
18
20
|
opts.banner = "Import one or more Seiso data master files into Seiso.
|
19
21
|
|
20
22
|
Usage: #{executable_name} [options] master_file ..."
|
21
|
-
options[:
|
22
|
-
opts.on("--
|
23
|
-
options[:
|
23
|
+
options[:seiso3_settings_path] = "#{Dir.home}/.seiso-importers/seiso3.yml"
|
24
|
+
opts.on("--seiso3 SEISO3_SETTINGS_PATH", "Path to Seiso API v3 settings file") do |path|
|
25
|
+
options[:seiso3_settings_path] = path
|
24
26
|
end
|
25
27
|
|
26
28
|
options[:format] = 'json'
|
27
29
|
opts.on("-f FORMAT", "--format FORMAT", "Document format, either 'json' (default) or 'yaml'") do |format|
|
28
30
|
options[:format] = format
|
29
31
|
end
|
30
|
-
|
32
|
+
|
31
33
|
opts.on("-h", "--help", "Display this screen") do
|
32
34
|
puts opts
|
33
35
|
exit
|
@@ -37,15 +39,30 @@ end
|
|
37
39
|
begin
|
38
40
|
option_parser.parse!
|
39
41
|
rescue OptionParser::InvalidOption => e
|
40
|
-
|
42
|
+
log.error "Invalid option."
|
43
|
+
puts option_parser.help
|
44
|
+
abort
|
41
45
|
end
|
42
46
|
|
43
|
-
|
44
|
-
|
47
|
+
log.info "Using: #{options[:seiso3_settings_path]}"
|
48
|
+
log.info "Using: format=#{options[:format]}"
|
45
49
|
|
46
50
|
files = ARGV
|
47
|
-
|
51
|
+
if files.empty?
|
52
|
+
log.error "You must supply a master file."
|
53
|
+
puts option_parser.help
|
54
|
+
abort
|
55
|
+
end
|
56
|
+
|
57
|
+
seiso3_settings = YAML.load_file(options[:seiso3_settings_path])
|
58
|
+
importer = Seiso::ImportMaster.new seiso3_settings
|
59
|
+
result = importer.import_files(files, options[:format])
|
48
60
|
|
49
|
-
|
50
|
-
|
51
|
-
|
61
|
+
if result == "success"
|
62
|
+
log.success "Import succeeded."
|
63
|
+
elsif result == "partial"
|
64
|
+
log.warn "Import succeeded, but with issues."
|
65
|
+
else
|
66
|
+
log.error "Import failed."
|
67
|
+
abort
|
68
|
+
end
|
data/lib/seiso/import_master.rb
CHANGED
@@ -1,114 +1,138 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
|
6
|
-
require_rel "import_master"
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
require 'hyper_resource'
|
4
|
+
require 'require_all'
|
5
|
+
require_rel './import_master'
|
7
6
|
|
7
|
+
# Imports Seiso data master files into Seiso.
|
8
|
+
#
|
9
|
+
# Author:: Willie Wheeler
|
10
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
11
|
+
# License:: Apache 2.0
|
8
12
|
module Seiso
|
9
|
-
|
10
|
-
# Imports Seiso data master files into Seiso.
|
11
|
-
#
|
12
|
-
# Author:: Willie Wheeler (mailto:wwheeler@expedia.com)
|
13
|
-
# Copyright:: Copyright (c) 2014-2015 Expedia, Inc.
|
14
|
-
# License:: Apache 2.0
|
15
13
|
class ImportMaster
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
|
15
|
+
def initialize(seiso3_settings)
|
16
|
+
@log = Util::Logger.new "ImportMaster"
|
19
17
|
@loaders = {
|
20
18
|
'json' => ->(file) { JSON.parse(IO.read(file)) },
|
21
19
|
'yaml' => ->(file) { YAML.load_file file }
|
22
20
|
}
|
21
|
+
@v3_api = HyperResource.new(
|
22
|
+
root: seiso3_settings['base_uri'],
|
23
|
+
headers: {
|
24
|
+
'Accept' => 'application/hal+json',
|
25
|
+
'Content-Type' => 'application/hal+json'
|
26
|
+
},
|
27
|
+
auth: {
|
28
|
+
basic: [ seiso3_settings['username'], seiso3_settings['password'] ]
|
29
|
+
}
|
30
|
+
)
|
31
|
+
@resolver = Util::ItemResolver.new @v3_api
|
32
|
+
@rest_util = Util::RestUtil.new
|
23
33
|
|
24
|
-
#
|
25
|
-
@
|
26
|
-
'nodes' => Validators::NodeValidator.new,
|
27
|
-
'services' => Validators::ServiceValidator.new
|
28
|
-
}
|
29
|
-
|
30
|
-
basic_mapper = Mappers::MasterItemMapper.new
|
31
|
-
node_mapper = Mappers::NodeMapper.new
|
32
|
-
service_mapper = Mappers::ServiceMapper.new
|
33
|
-
service_instance_mapper = Mappers::ServiceInstanceMapper.new
|
34
|
-
|
35
|
-
seiso = Seiso::Connector.new seiso_settings
|
36
|
-
uri_factory_v1 = uri_factory_v1 seiso_settings
|
37
|
-
uri_factory_v2 = uri_factory_v2 seiso_settings
|
38
|
-
rest_connector_v1 = rest_connector(seiso_settings, "application/json")
|
39
|
-
rest_connector_v2 = rest_connector(seiso_settings, "application/hal+json")
|
40
|
-
|
41
|
-
@simple_importer = Importers::SimpleImporter.new(basic_mapper, seiso, uri_factory_v1, rest_connector_v1)
|
42
|
-
|
43
|
-
# TODO Clean this up. Just use v2 URI factory and connector.
|
44
|
-
@importers = {
|
45
|
-
'nodes' => Importers::NodeImporter.new(node_mapper, uri_factory_v1, rest_connector_v1),
|
46
|
-
'services' => Importers::ServiceImporter.new(
|
47
|
-
basic_mapper,
|
48
|
-
service_mapper,
|
49
|
-
uri_factory_v1,
|
50
|
-
uri_factory_v2,
|
51
|
-
rest_connector_v1,
|
52
|
-
rest_connector_v2),
|
53
|
-
'service-instances' => Importers::ServiceInstanceImporter.new(
|
54
|
-
service_instance_mapper,
|
55
|
-
uri_factory_v1,
|
56
|
-
uri_factory_v2,
|
57
|
-
seiso,
|
58
|
-
rest_connector_v1,
|
59
|
-
rest_connector_v2)
|
60
|
-
}
|
34
|
+
# Importer cache, since they're expensive to initialize
|
35
|
+
@importers = {}
|
61
36
|
end
|
62
37
|
|
63
38
|
# Imports a list of master files in order. Legal formats are 'json' (default) and 'yaml'.
|
39
|
+
# Returns true if all file imports succeeded and false otherwise.
|
64
40
|
def import_files(files, format = 'json')
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
41
|
+
begin
|
42
|
+
all_failed = true
|
43
|
+
all_success = true
|
44
|
+
loop do
|
45
|
+
file = files.pop
|
46
|
+
success = import_file(file, format)
|
47
|
+
if success
|
48
|
+
all_failed = false
|
49
|
+
else
|
50
|
+
all_success = false
|
51
|
+
end
|
52
|
+
break if files.empty?
|
53
|
+
end
|
54
|
+
if all_success
|
55
|
+
return "success"
|
56
|
+
elsif all_failed
|
57
|
+
return "failed"
|
58
|
+
else
|
59
|
+
return "partial"
|
60
|
+
end
|
61
|
+
rescue Interrupt => e
|
62
|
+
@log.error "Import interrupted."
|
63
|
+
return "failed"
|
70
64
|
end
|
71
65
|
end
|
72
|
-
|
66
|
+
|
67
|
+
private
|
68
|
+
|
73
69
|
# Imports a data master file. Legal formats are 'json' (default) and 'yaml'.
|
70
|
+
# Returns true if the import succeeded and false otherwise.
|
74
71
|
def import_file(file, format = 'json')
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
validator = @validators[type]
|
80
|
-
validator.validate(doc) unless validator.nil?
|
81
|
-
(@importers[type] || @simple_importer).import doc
|
82
|
-
end
|
72
|
+
@log.info "Importing file #{file}"
|
73
|
+
begin
|
74
|
+
# Include this in the begin/rescue as it can raise a JSON::ParserError
|
75
|
+
loader = @loaders[format]
|
83
76
|
|
84
|
-
|
77
|
+
fail ArgumentError, "Illegal format: #{format}" if loader.nil?
|
85
78
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
scheme = use_ssl ? "https" : "http"
|
91
|
-
base_uri = "#{scheme}://#{host}:#{port}/v1"
|
92
|
-
Seiso::Connector::UriFactoryV1.new base_uri
|
93
|
-
end
|
79
|
+
doc = loader.call file
|
80
|
+
type = doc['type']
|
81
|
+
get_importer(type).import doc
|
82
|
+
return true
|
94
83
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
84
|
+
# Rescue StandardError here, not Exception, since we want ctrl-c to stop the program.
|
85
|
+
rescue StandardError => e
|
86
|
+
@log.error "Failed to import file #{file}: #{e.message}"
|
87
|
+
|
88
|
+
# FIXME For now, just re-raise the exception, as we want to see where the bugs are.
|
89
|
+
return false
|
90
|
+
# raise e
|
91
|
+
end
|
102
92
|
end
|
103
93
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
94
|
+
def get_importer(type)
|
95
|
+
# TODO Do a cleaner impl here--one that doesn't violate the open-closed principle. Note that we *don't* want to
|
96
|
+
# create these eagerly, as each one involves an expensive initialization.
|
97
|
+
importer = @importers[type]
|
98
|
+
|
99
|
+
if importer.nil?
|
100
|
+
importer = case type
|
101
|
+
when 'data-centers'
|
102
|
+
Importers::DataCenterImporter.new(@v3_api, @rest_util, @resolver)
|
103
|
+
when 'environments'
|
104
|
+
Importers::EnvironmentImporter.new(@v3_api, @rest_util, @resolver)
|
105
|
+
when 'health-statuses'
|
106
|
+
Importers::HealthStatusImporter.new(@v3_api, @rest_util, @resolver)
|
107
|
+
when 'infrastructure-providers'
|
108
|
+
Importers::InfrastructureProviderImporter.new(@v3_api, @rest_util, @resolver)
|
109
|
+
when 'load-balancers'
|
110
|
+
Importers::LoadBalancerImporter.new(@v3_api, @rest_util, @resolver)
|
111
|
+
when 'machines'
|
112
|
+
Importers::MachineImporter.new(@v3_api, @rest_util, @resolver)
|
113
|
+
when 'nodes'
|
114
|
+
Importers::NodeImporter.new(@v3_api, @rest_util, @resolver)
|
115
|
+
when 'regions'
|
116
|
+
Importers::RegionImporter.new(@v3_api, @rest_util, @resolver)
|
117
|
+
when 'rotation-statuses'
|
118
|
+
Importers::RotationStatusImporter.new(@v3_api, @rest_util, @resolver)
|
119
|
+
when 'services'
|
120
|
+
Importers::ServiceImporter.new(@v3_api, @rest_util, @resolver)
|
121
|
+
when 'service-groups'
|
122
|
+
Importers::ServiceGroupImporter.new(@v3_api, @rest_util, @resolver)
|
123
|
+
when 'service-instances'
|
124
|
+
Importers::ServiceInstanceImporter.new(@v3_api, @rest_util, @resolver)
|
125
|
+
when 'service-types'
|
126
|
+
Importers::ServiceTypeImporter.new(@v3_api, @rest_util, @resolver)
|
127
|
+
when 'status-types'
|
128
|
+
Importers::StatusTypeImporter.new(@v3_api, @rest_util, @resolver)
|
129
|
+
else
|
130
|
+
raise ArgumentError, "Illegal type: #{type}"
|
131
|
+
end
|
132
|
+
@importers['type'] = importer
|
133
|
+
end
|
134
|
+
|
135
|
+
importer
|
112
136
|
end
|
113
137
|
end
|
114
138
|
end
|
@@ -1,31 +1,92 @@
|
|
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
|
-
|
1
|
+
require 'hyper_resource'
|
2
|
+
|
3
|
+
class Seiso::ImportMaster
|
4
|
+
|
5
|
+
# Base importer for type-specific importers.
|
6
|
+
#
|
7
|
+
# Subclasses must set the @repo_resource variable to point to the type's repository resource.
|
8
|
+
#
|
9
|
+
# Additionally, subclasses must provide the following type-specific callback implementations:
|
10
|
+
#
|
11
|
+
# - to_search_params(doc_item, context) : Returns a hash containing HTTP params for the resource search.
|
12
|
+
# - find_resource(search_params) : Takes the search params above and returns the corresponding resource.
|
13
|
+
#
|
14
|
+
# If the type in question has child resources (e.g., service instances have IP address roles and service instance
|
15
|
+
# ports), then subclasses should provide the following callback implementations to handle them:
|
16
|
+
#
|
17
|
+
# - context_for(parent_resource, parent_context) : Returns a new context to support importing child resources.
|
18
|
+
# - import_children_of(doc_item, context) : Imports the child resources.
|
19
|
+
#
|
20
|
+
# See service_instance_importer.rb for an example that includes all four callbacks.
|
21
|
+
#
|
22
|
+
# Author:: Willie Wheeler
|
23
|
+
# Copyright:: Copyright (c) 2014-2016 Expedia, Inc.
|
24
|
+
# License:: Apache 2.0
|
25
|
+
class Importers::BaseImporter
|
26
|
+
|
27
|
+
# Imports a list of document items into Seiso.
|
28
|
+
#
|
29
|
+
# - items : Items in document format
|
30
|
+
# - context : Import context
|
31
|
+
def import_items(doc_items, context)
|
32
|
+
# TODO Perform orphan deletion here, centrally, and recursively?
|
33
|
+
doc_items.each { |doc_item| import_item(doc_item, context) }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Imports a single document item into Seiso. Returns the imported item's URI
|
37
|
+
#
|
38
|
+
# - item : Item in document format
|
39
|
+
# - context : Import context
|
40
|
+
def import_item(doc_item, context)
|
41
|
+
data = mapper.map(doc_item, context)
|
42
|
+
search_params = to_search_params(doc_item, context)
|
43
|
+
begin
|
44
|
+
resource = find_resource search_params
|
45
|
+
|
46
|
+
# In the Seiso API, PUT will leave any unspecified associations alone. So for example we can handle node health
|
47
|
+
# status and rotation status like this. When we have node build version, though, we will have to do something
|
48
|
+
# else, like turn it into an association or else PATCH here. [WLW]
|
49
|
+
rest_util.put(resource, data, search_params)
|
50
|
+
|
51
|
+
rescue HyperResource::ClientError => e
|
52
|
+
status = e.response.status
|
53
|
+
body = e.response.body
|
54
|
+
fail "Client error: status=#{status}, body=#{body}" unless status == 404
|
55
|
+
|
56
|
+
# Seiso API returns the created resource in the response body, so grab that.
|
57
|
+
# TODO Clean up this implementation. E.g. don't used nested exception handling, and don't create the logger
|
58
|
+
# here. [WLW]
|
59
|
+
begin
|
60
|
+
resource = rest_util.post(repo_resource, data, search_params)
|
61
|
+
rescue HyperResource::ClientError => e2
|
62
|
+
# HTTP 409 is typical. It happens when client references nonexistent entities.
|
63
|
+
status2 = e2.response.status
|
64
|
+
body2 = e2.response.body
|
65
|
+
log = Util::Logger.new "BaseImporter"
|
66
|
+
log.warn "Client error: status=#{status2}, body=#{body2}. Failed to import item."
|
67
|
+
return
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# ================================================================================================================
|
72
|
+
# FIXME For puts, this is putting the *old* resource on the context, which isn't what we want! [WLW]
|
73
|
+
# ================================================================================================================
|
74
|
+
|
75
|
+
if respond_to?(:import_children_of)
|
76
|
+
new_context = respond_to?(:context_for) ? context_for(resource, context) : {}
|
77
|
+
# FIXME For NodeIpAddress, this is returning a resource whose self link is /search/findByNodeNameAndIpAddress,
|
78
|
+
# and we can't PUT to that.
|
79
|
+
import_children_of(doc_item, new_context)
|
80
|
+
end
|
81
|
+
|
82
|
+
resource.href
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
attr_accessor :api
|
88
|
+
attr_accessor :rest_util
|
89
|
+
attr_accessor :mapper
|
90
|
+
attr_accessor :repo_resource
|
91
|
+
end
|
31
92
|
end
|