inventory_refresh 0.3.6 → 1.0.0

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +25 -30
  3. data/.github/workflows/ci.yaml +47 -0
  4. data/.rubocop.yml +3 -3
  5. data/.rubocop_cc.yml +3 -4
  6. data/.rubocop_local.yml +5 -2
  7. data/.whitesource +3 -0
  8. data/CHANGELOG.md +19 -0
  9. data/Gemfile +10 -4
  10. data/README.md +1 -2
  11. data/Rakefile +2 -2
  12. data/inventory_refresh.gemspec +8 -9
  13. data/lib/inventory_refresh/application_record_iterator.rb +25 -12
  14. data/lib/inventory_refresh/graph/topological_sort.rb +24 -26
  15. data/lib/inventory_refresh/graph.rb +2 -2
  16. data/lib/inventory_refresh/inventory_collection/builder.rb +37 -15
  17. data/lib/inventory_refresh/inventory_collection/data_storage.rb +9 -0
  18. data/lib/inventory_refresh/inventory_collection/helpers/initialize_helper.rb +147 -38
  19. data/lib/inventory_refresh/inventory_collection/helpers/questions_helper.rb +48 -4
  20. data/lib/inventory_refresh/inventory_collection/index/proxy.rb +35 -3
  21. data/lib/inventory_refresh/inventory_collection/index/type/base.rb +8 -0
  22. data/lib/inventory_refresh/inventory_collection/index/type/local_db.rb +2 -0
  23. data/lib/inventory_refresh/inventory_collection/index/type/skeletal.rb +1 -0
  24. data/lib/inventory_refresh/inventory_collection/reference.rb +1 -0
  25. data/lib/inventory_refresh/inventory_collection/references_storage.rb +17 -0
  26. data/lib/inventory_refresh/inventory_collection/scanner.rb +91 -3
  27. data/lib/inventory_refresh/inventory_collection/serialization.rb +16 -10
  28. data/lib/inventory_refresh/inventory_collection.rb +122 -64
  29. data/lib/inventory_refresh/inventory_object.rb +74 -40
  30. data/lib/inventory_refresh/inventory_object_lazy.rb +17 -10
  31. data/lib/inventory_refresh/null_logger.rb +2 -2
  32. data/lib/inventory_refresh/persister.rb +43 -93
  33. data/lib/inventory_refresh/save_collection/base.rb +4 -2
  34. data/lib/inventory_refresh/save_collection/saver/base.rb +114 -15
  35. data/lib/inventory_refresh/save_collection/saver/batch.rb +17 -0
  36. data/lib/inventory_refresh/save_collection/saver/concurrent_safe_batch.rb +129 -51
  37. data/lib/inventory_refresh/save_collection/saver/default.rb +57 -0
  38. data/lib/inventory_refresh/save_collection/saver/partial_upsert_helper.rb +2 -19
  39. data/lib/inventory_refresh/save_collection/saver/retention_helper.rb +68 -3
  40. data/lib/inventory_refresh/save_collection/saver/sql_helper.rb +125 -0
  41. data/lib/inventory_refresh/save_collection/saver/sql_helper_update.rb +10 -6
  42. data/lib/inventory_refresh/save_collection/saver/sql_helper_upsert.rb +28 -16
  43. data/lib/inventory_refresh/save_collection/sweeper.rb +17 -93
  44. data/lib/inventory_refresh/save_collection/topological_sort.rb +5 -5
  45. data/lib/inventory_refresh/save_inventory.rb +5 -12
  46. data/lib/inventory_refresh/target.rb +73 -0
  47. data/lib/inventory_refresh/target_collection.rb +92 -0
  48. data/lib/inventory_refresh/version.rb +1 -1
  49. data/lib/inventory_refresh.rb +2 -0
  50. metadata +34 -37
  51. data/.travis.yml +0 -23
  52. data/lib/inventory_refresh/exception.rb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c45babbc585f12693544de305f05e4011e1e3ef7ccb4d3fb1dd306d17d8814b2
4
- data.tar.gz: 8512e2e81eb065b5ddd486ab5a53e1ca0e2c09f7fa426fa82ffbeab12dc322ec
3
+ metadata.gz: 8d788fa837920653d4f68b418a41687dcfb5555da780854c371654b93cf0fbaa
4
+ data.tar.gz: 516547253906ef09089351d6e007ebaac0160aaadee73a38782aa598f284e396
5
5
  SHA512:
6
- metadata.gz: f41ba870e4a66782549e2a6baae960281ec2604c70633d37ef993b013ac3201b887a4346c68d277167b4b5d688986d95a937e9934d9b1dd3057939644fc3eed4
7
- data.tar.gz: f8a1644db501c32caebe8f7fa5eea9602b3a140180e822b1abe941676b654595743fe9f87ec73574a4a842a7b2373ada8aba325c17667eeb159b55f27ebf799d
6
+ metadata.gz: c6b1fcf9600b6f9ff22da8cc5226f7c6395a7c35f9b9b62f9c0a2edb51158e1d3eaa59b1c1400b1e1ccf2f2bf1ff7bfa5901db04326afc490d569715daf73ad9
7
+ data.tar.gz: 50b1acc7a4b10a5a8a678b16fd06aa9c809068054d9b469391e877e668e18340ca998ab8485346d5f51cd0f682582fcd9ef516df2f88e273c1a401f45fe31241
data/.codeclimate.yml CHANGED
@@ -1,18 +1,21 @@
1
- ---
2
- exclude_paths:
3
- - ".git/"
4
- - "**.xml"
5
- - "**.yaml"
6
- - "**.yml"
7
- - "locale/"
8
- - "spec/"
9
- - "tools/"
10
- engines:
1
+ prepare:
2
+ fetch:
3
+ - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_base.yml
4
+ path: ".rubocop_base.yml"
5
+ - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_cc_base.yml
6
+ path: ".rubocop_cc_base.yml"
7
+ - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/base.yml
8
+ path: styles/base.yml
9
+ - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/cc_base.yml
10
+ path: styles/cc_base.yml
11
+ plugins:
12
+ rubocop:
13
+ enabled: true
14
+ config: ".rubocop_cc.yml"
15
+ channel: rubocop-0-82
11
16
  brakeman:
12
- # very slow :sad_panda:
13
17
  enabled: false
14
18
  bundler-audit:
15
- # requires Gemfile.lock
16
19
  enabled: false
17
20
  csslint:
18
21
  enabled: false
@@ -24,25 +27,17 @@ engines:
24
27
  - javascript
25
28
  eslint:
26
29
  enabled: false
27
- channel: "eslint-3"
30
+ channel: eslint-3
28
31
  fixme:
29
- # let's enable later
30
32
  enabled: false
31
33
  markdownlint:
32
- # let's enable later
33
34
  enabled: false
34
- rubocop:
35
- enabled: true
36
- config: '.rubocop_cc.yml'
37
- channel: rubocop-0-69
38
- prepare:
39
- fetch:
40
- - url: "https://raw.githubusercontent.com/ManageIQ/guides/master/.rubocop_base.yml"
41
- path: ".rubocop_base.yml"
42
- - url: "https://raw.githubusercontent.com/ManageIQ/guides/master/.rubocop_cc_base.yml"
43
- path: ".rubocop_cc_base.yml"
44
- ratings:
45
- paths:
46
- - Gemfile.lock
47
- - "**.rake"
48
- - "**.rb"
35
+ exclude_patterns:
36
+ - ".git/"
37
+ - "**.xml"
38
+ - "**.yaml"
39
+ - "**.yml"
40
+ - locale/
41
+ - spec/
42
+ - tools/
43
+ version: '2'
@@ -0,0 +1,47 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ ci:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ ruby-version:
11
+ - '2.5'
12
+ - '2.6'
13
+ - '2.7'
14
+ rails-version:
15
+ - '5.2'
16
+ - '6.0'
17
+ - '6.1'
18
+ services:
19
+ postgres:
20
+ image: manageiq/postgresql:10
21
+ env:
22
+ POSTGRESQL_USER: root
23
+ POSTGRESQL_PASSWORD: smartvm
24
+ POSTGRESQL_DATABASE: inventory_refresh_dummy_test
25
+ options: --health-cmd pg_isready --health-interval 2s --health-timeout 5s --health-retries 5
26
+ ports:
27
+ - 5432:5432
28
+ env:
29
+ TEST_RAILS_VERSION: ${{ matrix.rails-version }}
30
+ PGHOST: localhost
31
+ PGPASSWORD: smartvm
32
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
33
+ steps:
34
+ - uses: actions/checkout@v2
35
+ - name: Set up Ruby
36
+ uses: ruby/setup-ruby@v1
37
+ with:
38
+ ruby-version: ${{ matrix.ruby-version }}
39
+ bundler-cache: true
40
+ - name: Prepare tests
41
+ run: bundle exec rake spec:setup
42
+ - name: Run tests
43
+ run: bundle exec rake
44
+ - name: Report code coverage
45
+ if: ${{ github.ref == 'refs/heads/master' && matrix.ruby-version == '2.7' && matrix.rails-version == '6.1' }}
46
+ continue-on-error: true
47
+ uses: paambaati/codeclimate-action@v3.0.0
data/.rubocop.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  inherit_from:
2
- - https://raw.githubusercontent.com/ManageIQ/guides/master/.rubocop_base.yml
3
- # put all local rubocop config into .rubocop_local.yml as it will be loaded by .rubocop_cc.yml as well
4
- - .rubocop_local.yml
2
+ - ".rubocop_local.yml"
3
+ inherit_gem:
4
+ manageiq-style: ".rubocop_base.yml"
data/.rubocop_cc.yml CHANGED
@@ -1,5 +1,4 @@
1
1
  inherit_from:
2
- # this is downloaded by .codeclimate.yml
3
- - .rubocop_base.yml
4
- - .rubocop_cc_base.yml
5
- - .rubocop_local.yml
2
+ - ".rubocop_base.yml"
3
+ - ".rubocop_cc_base.yml"
4
+ - ".rubocop_local.yml"
data/.rubocop_local.yml CHANGED
@@ -1,2 +1,5 @@
1
- # GlobalVars:
2
- # AllowedVariables:
1
+ AllCops:
2
+ Exclude:
3
+ - spec/schema.rb
4
+ Rails:
5
+ Enabled: false
data/.whitesource ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "settingsInheritedFrom": "ManageIQ/whitesource-config@master"
3
+ }
data/CHANGELOG.md CHANGED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ This project adheres to [Semantic Versioning](http://semver.org/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [1.0.0] - 2022-02-09
9
+ ### Changed
10
+ - Run rubocop -A (#102)
11
+ - Switch from travis to github actions (#104, #105)
12
+
13
+ ### Added
14
+ - **BREAKING** Add back support for non-concurrent-safe batch strategies (#101)
15
+ - Add support for Rails 6.1 (#103)
16
+ - Add bundler-inject (#106)
17
+
18
+ ### Fixed
19
+ - Fix InventoryCollection missing cache returns (#107)
data/Gemfile CHANGED
@@ -1,10 +1,16 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ plugin "bundler-inject", "~> 2.0"
4
+ require File.join(Bundler::Plugin.index.load_paths("bundler-inject")[0], "bundler-inject") rescue nil
4
5
 
5
6
  # Specify your gem's dependencies in inventory_refresh.gemspec
6
7
  gemspec
7
8
 
8
- # Load other additional Gemfiles
9
- # Developers can create a file ending in .rb under bundler.d/ to specify additional development dependencies
10
- Dir.glob(File.join(__dir__, 'bundler.d/*.rb')).each { |f| eval_gemfile(File.expand_path(f, __dir__)) }
9
+ case ENV['TEST_RAILS_VERSION']
10
+ when "5.2"
11
+ gem "activerecord", "~>5.2.6"
12
+ when "6.0"
13
+ gem "activerecord", "~>6.0.4"
14
+ when "6.1"
15
+ gem "activerecord", "~>6.1.4"
16
+ end
data/README.md CHANGED
@@ -1,10 +1,9 @@
1
1
  # InventoryRefresh
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/inventory_refresh.svg)](http://badge.fury.io/rb/inventory_refresh)
4
- [![Build Status](https://travis-ci.org/ManageIQ/inventory_refresh.svg)](https://travis-ci.org/ManageIQ/inventory_refresh)
4
+ [![CI](https://github.com/ManageIQ/inventory_refresh/actions/workflows/ci.yaml/badge.svg)](https://github.com/ManageIQ/inventory_refresh/actions/workflows/ci.yaml)
5
5
  [![Code Climate](https://codeclimate.com/github/ManageIQ/inventory_refresh.svg)](https://codeclimate.com/github/ManageIQ/inventory_refresh)
6
6
  [![Test Coverage](https://codeclimate.com/github/ManageIQ/inventory_refresh/badges/coverage.svg)](https://codeclimate.com/github/ManageIQ/inventory_refresh/coverage)
7
- [![Security](https://hakiri.io/github/ManageIQ/inventory_refresh/master.svg)](https://hakiri.io/github/ManageIQ/inventory_refresh/master)
8
7
 
9
8
  [![Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ManageIQ/manageiq/providers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
10
9
 
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ namespace :spec do
12
12
 
13
13
  task :db_load_schema do
14
14
  require "active_record"
15
- with_connection(test_database_name) { load File.join(__dir__, %w{spec schema.rb}) }
15
+ with_connection(test_database_name) { load File.join(__dir__, %w[spec schema.rb]) }
16
16
  end
17
17
 
18
18
  desc "Setup test database"
@@ -20,7 +20,7 @@ namespace :spec do
20
20
 
21
21
  def connection_spec
22
22
  require 'yaml'
23
- @connection_spec ||= YAML.load_file(File.join(__dir__, %w(config database.yml)))
23
+ @connection_spec ||= YAML.load_file(File.join(__dir__, %w[config database.yml]))
24
24
  end
25
25
 
26
26
  def test_database_name
@@ -1,5 +1,4 @@
1
-
2
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require "inventory_refresh/version"
5
4
 
@@ -8,30 +7,30 @@ Gem::Specification.new do |spec|
8
7
  spec.version = InventoryRefresh::VERSION
9
8
  spec.authors = ["ManageIQ Developers"]
10
9
 
11
- spec.summary = %q{Topological Inventory Persister}
12
- spec.description = %q{Topological Inventory Persister}
10
+ spec.summary = 'Topological Inventory Persister'
11
+ spec.description = 'Topological Inventory Persister'
13
12
  spec.homepage = "https://github.com/ManageIQ/inventory_refresh"
14
13
  spec.licenses = ["Apache-2.0"]
15
14
 
16
15
  # Specify which files should be added to the gem when it is released.
17
16
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
18
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
19
  end
21
20
  spec.bindir = "exe"
22
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
22
  spec.require_paths = ["lib"]
23
+ spec.metadata['rubygems_mfa_required'] = 'true'
24
24
 
25
- spec.add_dependency "activerecord", "~> 5.0"
25
+ spec.add_dependency "activerecord", ">=5.0", "< 7.0"
26
26
  spec.add_dependency "more_core_extensions", ">=3.5", "< 5"
27
27
  spec.add_dependency "pg", "> 0"
28
28
 
29
29
  spec.add_development_dependency "ancestry"
30
30
  spec.add_development_dependency "bundler", "~> 2.0"
31
31
  spec.add_development_dependency "factory_bot", "~> 4.11.1"
32
+ spec.add_development_dependency "manageiq-style"
32
33
  spec.add_development_dependency "rake", "~> 10.0"
33
34
  spec.add_development_dependency "rspec", "~> 3.0"
34
- spec.add_development_dependency "rubocop"
35
- spec.add_development_dependency "rubocop-performance"
36
- spec.add_development_dependency "simplecov"
35
+ spec.add_development_dependency "simplecov", ">= 0.21.2"
37
36
  end
@@ -1,12 +1,20 @@
1
1
  module InventoryRefresh
2
2
  class ApplicationRecordIterator
3
- attr_reader :inventory_collection
3
+ attr_reader :inventory_collection, :manager_uuids_set, :iterator, :query
4
4
 
5
- # An iterator that can fetch batches of the AR objects based on a set of attribute_indexes
5
+ # An iterator that can fetch batches of the AR objects based on a set of manager refs, or just mimics AR relation
6
+ # when given an iterator. Or given query, acts as iterator by selecting batches.
6
7
  #
7
8
  # @param inventory_collection [InventoryRefresh::InventoryCollection] Inventory collection owning the iterator
8
- def initialize(inventory_collection: nil)
9
+ # @param manager_uuids_set [Array<InventoryRefresh::InventoryCollection::Reference>] Array of references we want to
10
+ # fetch from the DB
11
+ # @param iterator [Proc] Block based iterator
12
+ # @query query [ActiveRecord::Relation] Existing query we want to use for querying the db
13
+ def initialize(inventory_collection: nil, manager_uuids_set: nil, iterator: nil, query: nil)
9
14
  @inventory_collection = inventory_collection
15
+ @manager_uuids_set = manager_uuids_set
16
+ @iterator = iterator
17
+ @query = query
10
18
  end
11
19
 
12
20
  # Iterator that mimics find_in_batches of ActiveRecord::Relation. This iterator serves for making more optimized query
@@ -17,22 +25,27 @@ module InventoryRefresh
17
25
  # and relation.where(:id => 500ids)
18
26
  #
19
27
  # @param batch_size [Integer] A batch size we want to fetch from DB
20
- # @param attributes_index [Hash{String => Hash}] Indexed hash with data we will be saving
21
28
  # @yield Code processing the batches
22
- def find_in_batches(batch_size: 1000, attributes_index: {})
23
- attributes_index.each_slice(batch_size) do |batch|
24
- yield(inventory_collection.db_collection_for_comparison_for(batch))
29
+ def find_in_batches(batch_size: 1000, &block)
30
+ if iterator
31
+ iterator.call(&block)
32
+ elsif query
33
+ manager_uuids_set.each_slice(batch_size) do |batch|
34
+ yield(query.where(inventory_collection.targeted_selection_for(batch)))
35
+ end
36
+ else
37
+ manager_uuids_set.each_slice(batch_size) do |batch|
38
+ yield(inventory_collection.db_collection_for_comparison_for(batch))
39
+ end
25
40
  end
26
41
  end
27
42
 
28
43
  # Iterator that mimics find_each of ActiveRecord::Relation using find_in_batches (see #find_in_batches)
29
44
  #
30
45
  # @yield Code processing the batches
31
- def find_each(attributes_index: {})
32
- find_in_batches(:attributes_index => attributes_index) do |batch|
33
- batch.each do |item|
34
- yield(item)
35
- end
46
+ def find_each(&block)
47
+ find_in_batches do |batch|
48
+ batch.each(&block)
36
49
  end
37
50
  end
38
51
  end
@@ -8,30 +8,30 @@ module InventoryRefresh
8
8
  @graph = graph
9
9
  end
10
10
 
11
- ################################################################################################################
12
- # Topological sort of the graph of the DTO collections to find the right order of saving DTO collections and
13
- # identify what DTO collections can be saved in parallel.
14
- # Does not mutate graph.
15
- #
16
- # @return [Array<Array>] Array of arrays(layers) of InventoryCollection objects
17
- ################################################################################################################
18
- # The expected input here is the directed acyclic Graph G (inventory_collections), consisting of Vertices(Nodes) V and
19
- # Edges E:
20
- # G = (V, E)
21
- #
22
- # The directed edge is defined as (u, v), where u is the dependency of v, i.e. arrow comes from u to v:
23
- # (u, v) ∈ E and u,v ∈ V
24
- #
25
- # S0 is a layer that has no dependencies:
26
- # S0 = { v ∈ V ∣ ∀u ∈ V.(u,v) ∉ E}
27
- #
28
- # Si+1 is a layer whose dependencies are in the sum of the previous layers from i to 0, cannot write
29
- # mathematical sum using U in text editor, so there is an alternative format using _(sum)
30
- # Si+1 = { v ∈ V ∣ ∀u ∈ V.(u,v) ∈ E → u ∈ _(sum(S0..Si))_ }
31
- #
32
- # Then each Si can have their Vertices(DTO collections) processed in parallel. This algorithm cannot
33
- # identify independent sub-graphs inside of the layers Si, so we can make the processing even more effective.
34
- ################################################################################################################
11
+ ################################################################################################################
12
+ # Topological sort of the graph of the DTO collections to find the right order of saving DTO collections and
13
+ # identify what DTO collections can be saved in parallel.
14
+ # Does not mutate graph.
15
+ #
16
+ # @return [Array<Array>] Array of arrays(layers) of InventoryCollection objects
17
+ ################################################################################################################
18
+ # The expected input here is the directed acyclic Graph G (inventory_collections), consisting of Vertices(Nodes) V and
19
+ # Edges E:
20
+ # G = (V, E)
21
+ #
22
+ # The directed edge is defined as (u, v), where u is the dependency of v, i.e. arrow comes from u to v:
23
+ # (u, v) ∈ E and u,v ∈ V
24
+ #
25
+ # S0 is a layer that has no dependencies:
26
+ # S0 = { v ∈ V ∣ ∀u ∈ V.(u,v) ∉ E}
27
+ #
28
+ # Si+1 is a layer whose dependencies are in the sum of the previous layers from i to 0, cannot write
29
+ # mathematical sum using U in text editor, so there is an alternative format using _(sum)
30
+ # Si+1 = { v ∈ V ∣ ∀u ∈ V.(u,v) ∈ E → u ∈ _(sum(S0..Si))_ }
31
+ #
32
+ # Then each Si can have their Vertices(DTO collections) processed in parallel. This algorithm cannot
33
+ # identify independent sub-graphs inside of the layers Si, so we can make the processing even more effective.
34
+ ################################################################################################################
35
35
  def topological_sort
36
36
  nodes = graph.nodes.dup
37
37
  edges = graph.edges
@@ -45,14 +45,12 @@ module InventoryRefresh
45
45
  max_depth -= 1
46
46
  if max_depth <= 0
47
47
  message = "Max depth reached while doing topological sort, your graph probably contains a cycle"
48
- #logger.error("#{message}:\n#{graph.to_graphviz}")
49
48
  raise "#{message} (see log)"
50
49
  end
51
50
 
52
51
  set, nodes = nodes.partition { |v| edges.select { |e| e.second == v }.all? { |e| sets.flatten.include?(e.first) } }
53
52
  if set.blank?
54
53
  message = "Blank dependency set while doing topological sort, your graph probably contains a cycle"
55
- #logger.error("#{message}:\n#{graph.to_graphviz}")
56
54
  raise "#{message} (see log)"
57
55
  end
58
56
 
@@ -37,7 +37,7 @@ module InventoryRefresh
37
37
  s << " #{node_names[from]} -> #{node_names[to]};"
38
38
  end
39
39
  s << "}"
40
- s.join("\n") + "\n"
40
+ "#{s.join("\n")}\n"
41
41
  end
42
42
 
43
43
  protected
@@ -147,7 +147,7 @@ module InventoryRefresh
147
147
  nodes.group_by { |n| n.respond_to?(:name) ? n.name.to_s : n.to_s }.each do |base_name, ns|
148
148
  ns.each_with_index do |n, i|
149
149
  name = ns.size == 1 ? base_name : "#{base_name}_#{i}"
150
- name = '"' + name.gsub(/["\\]/) { |c| "\\" + c } + '"' unless name =~ /^[A-Za-z0-9_]+$/
150
+ name = "\"#{name.gsub(/["\\]/) { |c| "\\#{c}" }}\"" unless /^[A-Za-z0-9_]+$/.match?(name)
151
151
  node_names[n] = name
152
152
  end
153
153
  end
@@ -4,17 +4,39 @@ module InventoryRefresh
4
4
  class MissingModelClassError < StandardError; end
5
5
 
6
6
  def self.allowed_properties
7
- %i(arel association
8
- attributes_blacklist attributes_whitelist batch_extra_attributes
9
- complete create_only custom_save_block
10
- custom_reconnect_block default_values
11
- dependency_attributes check_changed inventory_object_attributes
12
- manager_ref manager_ref_allowed_nil
13
- model_class name parent
14
- retention_strategy strategy
15
- secondary_refs
16
- update_only use_ar_object
17
- assert_graph_integrity).to_set
7
+ %i[
8
+ all_manager_uuids
9
+ arel
10
+ association
11
+ attributes_blacklist
12
+ attributes_whitelist
13
+ batch_extra_attributes
14
+ complete
15
+ create_only
16
+ custom_save_block
17
+ custom_reconnect_block
18
+ default_values
19
+ delete_method
20
+ dependency_attributes
21
+ check_changed
22
+ inventory_object_attributes
23
+ manager_ref
24
+ manager_ref_allowed_nil
25
+ manager_uuids
26
+ model_class
27
+ name
28
+ parent
29
+ parent_inventory_collections
30
+ retention_strategy
31
+ strategy
32
+ saver_strategy
33
+ secondary_refs
34
+ targeted
35
+ targeted_arel
36
+ update_only
37
+ use_ar_object
38
+ assert_graph_integrity
39
+ ].to_set
18
40
  end
19
41
 
20
42
  def allowed_properties
@@ -76,8 +98,8 @@ module InventoryRefresh
76
98
 
77
99
  send(@name.to_sym) if @name.respond_to?(:to_sym) && respond_to?(@name.to_sym)
78
100
 
79
- if @properties[:model_class].nil?
80
- add_properties(:model_class => auto_model_class) unless @options[:without_model_class]
101
+ if @properties[:model_class].nil? && !(@options[:without_model_class])
102
+ add_properties(:model_class => auto_model_class)
81
103
  end
82
104
  end
83
105
 
@@ -177,7 +199,7 @@ module InventoryRefresh
177
199
 
178
200
  def assert_allowed_property(name)
179
201
  unless allowed_properties.include?(name)
180
- raise "InventoryCollection property :#{name} is not allowed. Allowed properties are:\n#{self.allowed_properties.to_a.map(&:to_s).join(', ')}"
202
+ raise "InventoryCollection property :#{name} is not allowed. Allowed properties are:\n#{allowed_properties.to_a.map(&:to_s).join(', ')}"
181
203
  end
182
204
  end
183
205
 
@@ -216,7 +238,7 @@ module InventoryRefresh
216
238
  def auto_inventory_attributes
217
239
  return if @properties[:model_class].nil?
218
240
 
219
- (@properties[:model_class].new.methods - ar_base_class.methods).grep(/^[\w]+?\=$/).collect do |setter|
241
+ (@properties[:model_class].new.methods - ar_base_class.methods).grep(/^\w+?=$/).collect do |setter|
220
242
  setter.to_s[0..setter.length - 2].to_sym
221
243
  end
222
244
  end
@@ -70,6 +70,15 @@ module InventoryRefresh
70
70
  build(hash)
71
71
  end
72
72
 
73
+ # Finds InventoryObject.
74
+ #
75
+ # @param hash [Hash] Hash that needs to contain attributes defined in :manager_ref of the InventoryCollection
76
+ # @return [InventoryRefresh::InventoryObject] Found or built InventoryObject object
77
+ def find_in_data(hash)
78
+ _hash, _uuid, inventory_object = primary_index_scan(hash)
79
+ inventory_object
80
+ end
81
+
73
82
  # Finds of builds a new InventoryObject. By building it, we also put in into the InventoryCollection's storage.
74
83
  #
75
84
  # @param hash [Hash] Hash that needs to contain attributes defined in :manager_ref of the