inventory_refresh 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +0 -1
  3. data/.travis.yml +6 -8
  4. data/inventory_refresh.gemspec +2 -4
  5. data/lib/inventory_refresh.rb +0 -2
  6. data/lib/inventory_refresh/application_record_iterator.rb +9 -26
  7. data/lib/inventory_refresh/exception.rb +8 -0
  8. data/lib/inventory_refresh/inventory_collection.rb +36 -110
  9. data/lib/inventory_refresh/inventory_collection/builder.rb +6 -6
  10. data/lib/inventory_refresh/inventory_collection/data_storage.rb +0 -9
  11. data/lib/inventory_refresh/inventory_collection/helpers/initialize_helper.rb +34 -143
  12. data/lib/inventory_refresh/inventory_collection/helpers/questions_helper.rb +1 -44
  13. data/lib/inventory_refresh/inventory_collection/index/proxy.rb +6 -34
  14. data/lib/inventory_refresh/inventory_collection/index/type/base.rb +0 -8
  15. data/lib/inventory_refresh/inventory_collection/references_storage.rb +0 -17
  16. data/lib/inventory_refresh/inventory_collection/scanner.rb +1 -87
  17. data/lib/inventory_refresh/inventory_collection/serialization.rb +10 -16
  18. data/lib/inventory_refresh/inventory_object.rb +34 -68
  19. data/lib/inventory_refresh/inventory_object_lazy.rb +10 -17
  20. data/lib/inventory_refresh/persister.rb +63 -29
  21. data/lib/inventory_refresh/save_collection/base.rb +2 -4
  22. data/lib/inventory_refresh/save_collection/saver/base.rb +8 -108
  23. data/lib/inventory_refresh/save_collection/saver/concurrent_safe_batch.rb +48 -126
  24. data/lib/inventory_refresh/save_collection/saver/partial_upsert_helper.rb +19 -1
  25. data/lib/inventory_refresh/save_collection/saver/retention_helper.rb +3 -68
  26. data/lib/inventory_refresh/save_collection/saver/sql_helper.rb +0 -125
  27. data/lib/inventory_refresh/save_collection/saver/sql_helper_update.rb +5 -9
  28. data/lib/inventory_refresh/save_collection/saver/sql_helper_upsert.rb +9 -17
  29. data/lib/inventory_refresh/save_collection/sweeper.rb +91 -18
  30. data/lib/inventory_refresh/save_collection/topological_sort.rb +5 -5
  31. data/lib/inventory_refresh/save_inventory.rb +12 -5
  32. data/lib/inventory_refresh/version.rb +1 -1
  33. metadata +9 -45
  34. data/lib/inventory_refresh/save_collection/saver/batch.rb +0 -17
  35. data/lib/inventory_refresh/save_collection/saver/default.rb +0 -57
  36. data/lib/inventory_refresh/target.rb +0 -73
  37. data/lib/inventory_refresh/target_collection.rb +0 -92
@@ -17,21 +17,21 @@ module InventoryRefresh::SaveCollection
17
17
 
18
18
  layers = InventoryRefresh::Graph::TopologicalSort.new(graph).topological_sort
19
19
 
20
- logger.debug("Saving manager #{ems.name}...")
20
+ logger.debug("Saving manager #{ems.id}...")
21
21
 
22
- sorted_graph_log = "Topological sorting of manager #{ems.name} resulted in these layers processable in parallel:\n"
22
+ sorted_graph_log = "Topological sorting of manager #{ems.id} resulted in these layers processable in parallel:\n"
23
23
  sorted_graph_log += graph.to_graphviz(:layers => layers)
24
24
  logger.debug(sorted_graph_log)
25
25
 
26
26
  layers.each_with_index do |layer, index|
27
- logger.debug("Saving manager #{ems.name} | Layer #{index}")
27
+ logger.debug("Saving manager #{ems.id} | Layer #{index}")
28
28
  layer.each do |inventory_collection|
29
29
  save_inventory_object_inventory(ems, inventory_collection) unless inventory_collection.saved?
30
30
  end
31
- logger.debug("Saved manager #{ems.name} | Layer #{index}")
31
+ logger.debug("Saved manager #{ems.id} | Layer #{index}")
32
32
  end
33
33
 
34
- logger.debug("Saving manager #{ems.name}...Complete")
34
+ logger.debug("Saving manager #{ems.id}...Complete")
35
35
  end
36
36
  end
37
37
  end
@@ -29,11 +29,18 @@ module InventoryRefresh
29
29
  # @param ems [ExtManagementSystem] manager owning the inventory_collections
30
30
  # @param inventory_collections [Array<InventoryRefresh::InventoryCollection>] array of InventoryCollection objects
31
31
  # for sweeping
32
+ # @param sweep_scope [Array<String, Symbol, Hash>] Array of inventory collection names marking sweep. Or for
33
+ # targeted sweeping it's array of hashes, where key is inventory collection name pointing to an array of
34
+ # identifiers of inventory objects we want to target for sweeping.
32
35
  # @param refresh_state [ActiveRecord] Record of :refresh_states
33
- def sweep_inactive_records(ems, inventory_collections, refresh_state)
34
- logger.info("#{log_header(ems)} Sweeping EMS Inventory...")
35
- InventoryRefresh::SaveCollection::Sweeper.sweep(ems, inventory_collections, refresh_state)
36
- logger.info("#{log_header(ems)} Sweeping EMS Inventory...Complete")
36
+ def sweep_inactive_records(ems, inventory_collections, sweep_scope, refresh_state)
37
+ inventory_collections.each do |inventory_collection|
38
+ inventory_collection.strategy = :local_db_find_references
39
+ end
40
+
41
+ logger.info("#{log_header(ems)} Sweeping EMS Inventory with scope #{sweep_scope} and date #{refresh_state.created_at} ...")
42
+ InventoryRefresh::SaveCollection::Sweeper.sweep(ems, inventory_collections, sweep_scope, refresh_state)
43
+ logger.info("#{log_header(ems)} Sweeping EMS Inventory with scope #{sweep_scope} and date #{refresh_state.created_at}...Complete")
37
44
 
38
45
  ems
39
46
  end
@@ -43,7 +50,7 @@ module InventoryRefresh
43
50
  # @param ems [ExtManagementSystem] manager owning the inventory_collections
44
51
  # @return [String] helper string for logging
45
52
  def log_header(ems)
46
- "EMS: [#{ems.name}], id: [#{ems.id}]"
53
+ "EMS: [#{ems.id}]"
47
54
  end
48
55
  end
49
56
  end
@@ -1,3 +1,3 @@
1
1
  module InventoryRefresh
2
- VERSION = "0.2.2".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inventory_refresh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ManageIQ Developers
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-14 00:00:00.000000000 Z
11
+ date: 2019-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -28,22 +28,16 @@ dependencies:
28
28
  name: more_core_extensions
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '3.5'
34
- - - "<"
35
- - !ruby/object:Gem::Version
36
- version: '5'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
- - - ">="
38
+ - - "~>"
42
39
  - !ruby/object:Gem::Version
43
40
  version: '3.5'
44
- - - "<"
45
- - !ruby/object:Gem::Version
46
- version: '5'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: pg
49
43
  requirement: !ruby/object:Gem::Requirement
@@ -78,14 +72,14 @@ dependencies:
78
72
  requirements:
79
73
  - - "~>"
80
74
  - !ruby/object:Gem::Version
81
- version: '2.0'
75
+ version: 2.0.1
82
76
  type: :development
83
77
  prerelease: false
84
78
  version_requirements: !ruby/object:Gem::Requirement
85
79
  requirements:
86
80
  - - "~>"
87
81
  - !ruby/object:Gem::Version
88
- version: '2.0'
82
+ version: 2.0.1
89
83
  - !ruby/object:Gem::Dependency
90
84
  name: factory_bot
91
85
  requirement: !ruby/object:Gem::Requirement
@@ -128,34 +122,6 @@ dependencies:
128
122
  - - "~>"
129
123
  - !ruby/object:Gem::Version
130
124
  version: '3.0'
131
- - !ruby/object:Gem::Dependency
132
- name: rubocop
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - ">="
136
- - !ruby/object:Gem::Version
137
- version: '0'
138
- type: :development
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - ">="
143
- - !ruby/object:Gem::Version
144
- version: '0'
145
- - !ruby/object:Gem::Dependency
146
- name: rubocop-performance
147
- requirement: !ruby/object:Gem::Requirement
148
- requirements:
149
- - - ">="
150
- - !ruby/object:Gem::Version
151
- version: '0'
152
- type: :development
153
- prerelease: false
154
- version_requirements: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - ">="
157
- - !ruby/object:Gem::Version
158
- version: '0'
159
125
  - !ruby/object:Gem::Dependency
160
126
  name: simplecov
161
127
  requirement: !ruby/object:Gem::Requirement
@@ -198,6 +164,7 @@ files:
198
164
  - lib/inventory_refresh.rb
199
165
  - lib/inventory_refresh/application_record_iterator.rb
200
166
  - lib/inventory_refresh/application_record_reference.rb
167
+ - lib/inventory_refresh/exception.rb
201
168
  - lib/inventory_refresh/graph.rb
202
169
  - lib/inventory_refresh/graph/topological_sort.rb
203
170
  - lib/inventory_refresh/inventory_collection.rb
@@ -225,9 +192,7 @@ files:
225
192
  - lib/inventory_refresh/persister.rb
226
193
  - lib/inventory_refresh/save_collection/base.rb
227
194
  - lib/inventory_refresh/save_collection/saver/base.rb
228
- - lib/inventory_refresh/save_collection/saver/batch.rb
229
195
  - lib/inventory_refresh/save_collection/saver/concurrent_safe_batch.rb
230
- - lib/inventory_refresh/save_collection/saver/default.rb
231
196
  - lib/inventory_refresh/save_collection/saver/partial_upsert_helper.rb
232
197
  - lib/inventory_refresh/save_collection/saver/retention_helper.rb
233
198
  - lib/inventory_refresh/save_collection/saver/sql_helper.rb
@@ -236,8 +201,6 @@ files:
236
201
  - lib/inventory_refresh/save_collection/sweeper.rb
237
202
  - lib/inventory_refresh/save_collection/topological_sort.rb
238
203
  - lib/inventory_refresh/save_inventory.rb
239
- - lib/inventory_refresh/target.rb
240
- - lib/inventory_refresh/target_collection.rb
241
204
  - lib/inventory_refresh/version.rb
242
205
  homepage: https://github.com/ManageIQ/inventory_refresh
243
206
  licenses:
@@ -258,7 +221,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
258
221
  - !ruby/object:Gem::Version
259
222
  version: '0'
260
223
  requirements: []
261
- rubygems_version: 3.1.3
224
+ rubyforge_project:
225
+ rubygems_version: 2.7.6.2
262
226
  signing_key:
263
227
  specification_version: 4
264
228
  summary: Topological Inventory Persister
@@ -1,17 +0,0 @@
1
- require "inventory_refresh/save_collection/saver/concurrent_safe_batch"
2
-
3
- module InventoryRefresh::SaveCollection
4
- module Saver
5
- class Batch < InventoryRefresh::SaveCollection::Saver::ConcurrentSafeBatch
6
- private
7
-
8
- # Just returning manager ref transformed to column names, for strategies that do not expect to have unique DB
9
- # indexes.
10
- #
11
- # @return [Array<Symbol>] manager ref transformed to column names
12
- def unique_index_columns
13
- inventory_collection.manager_ref_to_cols.map(&:to_sym)
14
- end
15
- end
16
- end
17
- end
@@ -1,57 +0,0 @@
1
- require "inventory_refresh/save_collection/saver/base"
2
-
3
- module InventoryRefresh::SaveCollection
4
- module Saver
5
- class Default < InventoryRefresh::SaveCollection::Saver::Base
6
- private
7
-
8
- # Updates the passed record with hash data and stores primary key value into inventory_object.
9
- #
10
- # @param record [ApplicationRecord] record we want to update in DB
11
- # @param hash [Hash] data we want to update the record with
12
- # @param inventory_object [InventoryRefresh::InventoryObject] InventoryObject instance where we will store primary
13
- # key value
14
- def update_record!(record, hash, inventory_object)
15
- record.assign_attributes(hash.except(:id))
16
- if !inventory_collection.check_changed? || record.changed?
17
- record.save
18
- inventory_collection.store_updated_records(record)
19
- end
20
-
21
- inventory_object.id = record.id
22
- end
23
-
24
- # Creates a new record in the DB using the passed hash data
25
- #
26
- # @param hash [Hash] hash with data we want to persist to DB
27
- # @param inventory_object [InventoryRefresh::InventoryObject] InventoryObject instance where we will store primary
28
- # key value
29
- def create_record!(hash, inventory_object)
30
- record = inventory_collection.model_class.create!(hash.except(:id))
31
- inventory_collection.store_created_records(record)
32
-
33
- inventory_object.id = record.id
34
- end
35
-
36
- # Asserts we do not have duplicate records in the DB. If the record is duplicate we will destroy it.
37
- #
38
- # @param record [ApplicationRecord] record we want to update in DB
39
- # @param index [String] manager_uuid of the record
40
- # @return [Boolean] false if the record is duplicate
41
- def assert_unique_record(record, index)
42
- # TODO(lsmola) can go away once we indexed our DB with unique indexes
43
- if unique_db_indexes.include?(index) # Include on Set is O(1)
44
- # We have a duplicate in the DB, destroy it. A find_each method does automatically .order(:id => :asc)
45
- # so we always keep the oldest record in the case of duplicates.
46
- logger.warn("A duplicate record was detected and destroyed, inventory_collection: "\
47
- "'#{inventory_collection}', record: '#{record}', duplicate_index: '#{index}'")
48
- record.destroy
49
- return false
50
- else
51
- unique_db_indexes << index
52
- end
53
- true
54
- end
55
- end
56
- end
57
- end
@@ -1,73 +0,0 @@
1
- module InventoryRefresh
2
- class Target
3
- attr_reader :association, :manager_ref, :event_id, :options
4
-
5
- # @param association [Symbol] An existing association on Manager, that lists objects represented by a Target, naming
6
- # should be the same of association of a counterpart InventoryCollection object
7
- # @param manager_ref [Hash] A Hash that can be used to find_by on a given association and returning a unique object.
8
- # The keys should be the same as the keys of the counterpart InventoryObject
9
- # @param manager [ManageIQ::Providers::BaseManager] The Manager owning the Target
10
- # @param manager_id [Integer] A primary key of the Manager owning the Target
11
- # @param event_id [Integer] A primary key of the EmsEvent associated with the Target
12
- # @param options [Hash] A free form options hash
13
- def initialize(association:, manager_ref:, manager: nil, manager_id: nil, event_id: nil, options: {})
14
- raise "Provide either :manager or :manager_id argument" if manager.nil? && manager_id.nil?
15
-
16
- @manager = manager
17
- @manager_id = manager_id
18
- @association = association
19
- @manager_ref = manager_ref
20
- @event_id = event_id
21
- @options = options
22
- end
23
-
24
- # A Rails recommended interface for deserializing an object
25
- # @return [InventoryRefresh::Target] InventoryRefresh::Target instance
26
- def self.load(*args)
27
- new(*args)
28
- end
29
-
30
- # A Rails recommended interface for serializing an object
31
- #
32
- # @param obj [InventoryRefresh::Target] InventoryRefresh::Target instance we want to serialize
33
- # @return [Hash] serialized object
34
- def self.dump(obj)
35
- obj.dump
36
- end
37
-
38
- # Returns a serialized InventoryRefresh::Target object. This can be used to initialize a new object, then the object
39
- # target acts the same as the object InventoryRefresh::Target.new(target.serialize)
40
- #
41
- # @return [Hash] serialized object
42
- def dump
43
- {
44
- :manager_id => manager_id,
45
- :association => association,
46
- :manager_ref => manager_ref,
47
- :event_id => event_id,
48
- :options => options
49
- }
50
- end
51
-
52
- alias id dump
53
- alias name manager_ref
54
-
55
- # @return [ManageIQ::Providers::BaseManager] The Manager owning the Target
56
- def manager
57
- @manager || ManageIQ::Providers::BaseManager.find(@manager_id)
58
- end
59
-
60
- # @return [Integer] A primary key of the Manager owning the Target
61
- def manager_id
62
- @manager_id || manager.try(:id)
63
- end
64
-
65
- # Loads InventoryRefresh::Target ApplicationRecord representation from our DB, this requires that InventoryRefresh::Target
66
- # has been refreshed, otherwise the AR object can be missing.
67
- #
68
- # @return [ApplicationRecord] A InventoryRefresh::Target loaded from the database as AR object
69
- def load_from_db
70
- manager.public_send(association).find_by(manager_ref)
71
- end
72
- end
73
- end
@@ -1,92 +0,0 @@
1
- require "active_support/core_ext/module/delegation"
2
-
3
- module InventoryRefresh
4
- class TargetCollection
5
- attr_reader :targets
6
-
7
- delegate :<<, :to => :targets
8
-
9
- # @param manager [ManageIQ::Providers::BaseManager] manager owning the TargetCollection
10
- # @param manager_id [Integer] primary key of manager owning the TargetCollection
11
- # @param event [EmsEvent] EmsEvent associated with the TargetCollection
12
- # @param targets [Array<InventoryRefresh::Target, ApplicationRecord>] Array of InventoryRefresh::Target objects or
13
- # ApplicationRecord objects
14
- def initialize(manager: nil, manager_id: nil, event: nil, targets: [])
15
- @manager = manager
16
- @manager_id = manager_id
17
- @event = event
18
- @targets = targets
19
- end
20
-
21
- # @param association [Symbol] An existing association on Manager, that lists objects represented by a Target, naming
22
- # should be the same of association of a counterpart InventoryCollection object
23
- # @param manager_ref [Hash] A Hash that can be used to find_by on a given association and returning a unique object.
24
- # The keys should be the same as the keys of the counterpart InventoryObject
25
- # @param manager [ManageIQ::Providers::BaseManager] The Manager owning the Target
26
- # @param manager_id [Integer] A primary key of the Manager owning the Target
27
- # @param event_id [Integer] A primary key of the EmsEvent associated with the Target
28
- # @param options [Hash] A free form options hash
29
- def add_target(association:, manager_ref:, manager: nil, manager_id: nil, event_id: nil, options: {})
30
- self << InventoryRefresh::Target.new(:association => association,
31
- :manager_ref => manager_ref,
32
- :manager => manager || @manager,
33
- :manager_id => manager_id || @manager_id || @manager.try(:id),
34
- :event_id => event_id || @event.try(:id),
35
- :options => options)
36
- end
37
-
38
- # @return [String] A String containing a summary
39
- def name
40
- "Collection of #{targets.size} targets"
41
- end
42
-
43
- # @return [String] A String containing an id of each target in the TargetCollection
44
- def id
45
- "Collection of targets with id: #{targets.collect(&:name)}"
46
- end
47
-
48
- # Returns targets in a format:
49
- # {
50
- # :vms => {:ems_ref => Set.new(["vm_ref_1", "vm_ref2"])},
51
- # :network_ports => {:ems_ref => Set.new(["network_port_1", "network_port2"])
52
- # }
53
- #
54
- # Then we can quickly access all objects affected by:
55
- # NetworkPort.where(target_collection.manager_refs_by_association[:network_ports].to_a) =>
56
- # return AR objects with ems_refs ["network_port_1", "network_port2"]
57
- # And we can get a list of ids for the API query by:
58
- # target_collection.manager_refs_by_association[:network_ports][:ems_ref].to_a =>
59
- # ["network_port_1", "network_port2"]
60
- #
61
- # Only targets of a type InventoryRefresh::Target are processed, any other targets present should be converted to
62
- # InventoryRefresh::Target, e.g. in the Inventory::Collector code.
63
- def manager_refs_by_association
64
- @manager_refs_by_association ||= targets.select { |x| x.kind_of?(InventoryRefresh::Target) }.each_with_object({}) do |x, obj|
65
- if obj[x.association].blank?
66
- obj[x.association] = x.manager_ref.each_with_object({}) { |(key, value), hash| hash[key] = Set.new([value]) }
67
- else
68
- obj[x.association].each do |key, value|
69
- value << x.manager_ref[key]
70
- end
71
- end
72
- end
73
- end
74
-
75
- # Resets the cached @manager_refs_by_association to enforce reload when calling :manager_refs_by_association method
76
- def manager_refs_by_association_reset
77
- @manager_refs_by_association = nil
78
- end
79
-
80
- # Returns list of ems_refs
81
- # @return [Array<String>]
82
- def references(collection)
83
- manager_refs_by_association.try(:[], collection).try(:[], :ems_ref)&.to_a || []
84
- end
85
-
86
- # Returns list of names
87
- # @return [Array<String>]
88
- def name_references(collection)
89
- manager_refs_by_association.try(:[], collection).try(:[], :name)&.to_a || []
90
- end
91
- end
92
- end