Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using regexp for model_map and group_map keys #3362

Merged
merged 3 commits into from
Jan 15, 2025
Merged

Conversation

ytti
Copy link
Owner

@ytti ytti commented Jan 9, 2025

Use case is that the source returns string which has unrelated and variant data but the actual model is included somewhere in this data

For example source could have space separated list of tags and one of these tags could be model name. Eg 'procurve switch'.

Closes #3360

Summary by CodeRabbit

  • New Features

    • Configuration now supports regular expressions for model_map and group_map keys.
    • Added support for procurve device model mapping.
  • Documentation

    • Updated Configuration.md with new mapping and group configuration examples.
    • Added CHANGELOG.md entry for the new configuration feature.
  • Improvements

    • Simplified configuration mapping logic in source handling.
    • Added new map_value method to support flexible key matching.
  • Tests

    • Added comprehensive test suite for model mapping functionality.

Use case is that the source returns string which has unrelated and variant data
but the actual model is included somewhere in this data

For example source could have space separated list of tags and one of these
tags could be model name. Eg 'procurve switch'.

Closes #3360
We want to retain regexp keys for #3360
@ytti
Copy link
Owner Author

ytti commented Jan 9, 2025

I honestly cannot remember why I am normalising all keys to strings, but tests at least pass even if we don't normalise them.

@ytti ytti marked this pull request as ready for review January 9, 2025 21:03
@ytti
Copy link
Owner Author

ytti commented Jan 11, 2025

Another option, which doesn't require changing the key_to_s would be to introduce new config stanza like.

source:
  map:
    model:
       "oxidized_model": "source_model"

By swapping the order, we would guarantee the key is string, and value could be potentially any other class.

How we could transition to this new config stanza is that we could check existence of old, if old is found, we could emit warning that it's being deprecated and removed later in X, potentially link to documentation. Then we swap key/value and process the old and new stanza the same way.
We could even replace the user config with new version, however this would remove their formatting and comments as we don't preserve those when we write.

I don't feel strongly.

@ytti ytti requested a review from robertcheramy January 11, 2025 08:02
@ytti
Copy link
Owner Author

ytti commented Jan 13, 2025

Closing and reopening, as I want to see what CodeRabbit does.

Apparently nothing, guess it excludes reopened ones and wants to see fresh.

@ytti ytti closed this Jan 13, 2025
@ytti ytti reopened this Jan 13, 2025
@ytti
Copy link
Owner Author

ytti commented Jan 13, 2025

@coderabbitai full review

Copy link

coderabbitai bot commented Jan 13, 2025

✅ Actions performed

Full review triggered.

Copy link

coderabbitai bot commented Jan 13, 2025

Walkthrough

The pull request introduces enhancements to Oxidized's configuration system, focusing on improving device model and group mapping flexibility. The changes allow the model_map and group_map configurations to accept regular expressions, enabling more sophisticated device identification. This modification addresses limitations in parsing multiple tags from sources like PRTG, providing network engineers with more robust device classification options.

Changes

File Change Summary
CHANGELOG.md Added entry about regexp support for model_map and group_map
docs/Configuration.md Added procurve model mapping and expanded group-specific examples
lib/oxidized/config.rb Simplified Asetus class instantiation by removing key_to_s: true
lib/oxidized/source/source.rb Added map_value method to support regex-based mapping
spec/source/source_spec.rb Added test suite for #map_model method with regex mapping scenarios

Assessment against linked issues

Objective Addressed Explanation
Support regex for parsing multiple tags [#3360]
Enable flexible device model identification
Handle complex tag scenarios from PRTG

Poem

🐰 In the realm of network's embrace,
Regex dances with mapping's grace
Procurve, Cisco, tags galore
Oxidized opens a flexible door!
Configuration magic takes its flight 🚀


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c27d0e4 and 9d5ad92.

📒 Files selected for processing (2)
  • docs/Configuration.md (3 hunks)
  • lib/oxidized/source/source.rb (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/Configuration.md
  • lib/oxidized/source/source.rb

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
lib/oxidized/source/source.rb (1)

11-17: Consider performance optimization for map_value.

The current implementation iterates through all keys for every lookup. For large maps with regex keys, this could be inefficient. Consider:

  1. Separating regex and non-regex keys
  2. Checking exact matches first
  3. Caching compiled regexes
 def map_value(map_hash, original_value)
+  # First try exact matches (faster)
+  return map_hash[original_value] if map_hash.key?(original_value)
+
+  # Then try regex matches
   map_hash.each do |key, new_value|
     mthd = key.instance_of?(Regexp) ? :match : :eql?
     return new_value if original_value.send(mthd, key)
   end
   original_value
 end
spec/source/source_spec.rb (1)

4-31: Enhance test coverage.

While the current tests cover basic functionality, consider adding:

  1. Edge cases (nil, empty string)
  2. Performance tests for large maps
  3. Tests for the map_group method
  4. Tests for overlapping regex patterns
 describe Oxidized::Source do
   describe '#map_model' do
     before(:each) do
       Asetus.any_instance.expects(:load)
       Asetus.any_instance.expects(:create).returns(false)

       # Set :home_dir to make sure the OXIDIZED_HOME environment variable is not used
       Oxidized::Config.load({ home_dir: '/cfg_path/' })
       yaml = %(
         juniper: junos
         !ruby/regexp /procurve/: procurve
+        !ruby/regexp /^$/: empty_model
+        !ruby/regexp /cisco|ios/: ios
       )
       Oxidized.config.model_map = YAML.unsafe_load(yaml)
       @source = Oxidized::Source::Source.new
     end

+    it 'handles nil input' do
+      _(@source.map_model(nil)).must_equal nil
+    end
+
+    it 'handles empty string input' do
+      _(@source.map_model('')).must_equal 'empty_model'
+    end
+
+    it 'handles overlapping regex patterns' do
+      _(@source.map_model('cisco-ios')).must_equal 'ios'
+    end
   end
+
+  describe '#map_group' do
+    # Add similar tests for group mapping
+  end
 end
docs/Configuration.md (1)

229-229: Enhance regex documentation.

While the example shows how to use regex, consider adding:

  1. Explanation of regex pattern syntax
  2. Best practices for pattern matching
  3. Performance implications of using regex
  4. Examples of common patterns
 model_map:
   cisco: ios
   juniper: junos
   !ruby/regexp /procurve/: procurve
+  # Regex patterns are matched against the entire string
+  # Examples:
+  # Match exact word: !ruby/regexp /^procurve$/
+  # Match at start: !ruby/regexp /^cisco/
+  # Match anywhere: !ruby/regexp /juniper/
+  # Case insensitive: !ruby/regexp /(?i)cisco/
+  # Note: Complex patterns may impact performance
CHANGELOG.md (1)

11-11: LGTM! Consider enhancing the regexp entry description.

The changelog entries are well-formatted and follow the Keep a Changelog convention. However, the regexp entry could be more descriptive about the impact and benefits of this change.

Consider expanding the regexp entry to:

-config: allow model_map and group_map keys to be regexp. Fixes #3360 (@ytti)
+config: allow model_map and group_map keys to be regexp for flexible device matching. Fixes #3360 (@ytti)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6afc21d and c27d0e4.

📒 Files selected for processing (5)
  • CHANGELOG.md (1 hunks)
  • docs/Configuration.md (1 hunks)
  • lib/oxidized/config.rb (1 hunks)
  • lib/oxidized/source/source.rb (1 hunks)
  • spec/source/source_spec.rb (1 hunks)
🔇 Additional comments (1)
lib/oxidized/config.rb (1)

22-22: Verify the impact of removing key_to_s.

The removal of key_to_s: true allows regex keys in maps but might affect other configuration values. Let's verify there are no unintended consequences.

✅ Verification successful

Removal of key_to_s is safe

The codebase consistently converts keys to strings before configuration lookups, making it resilient to non-string keys in configuration maps. The explicit key conversion in the codebase ensures compatibility with both string and non-string keys.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for direct key access or string operations on configuration values
rg -A 2 "config\.[a-zA-Z_]+\[.+\]|\.to_s|\.is_a\?\s*\(?String\)?"

Length of output: 16672

coderabbitai bot added a commit that referenced this pull request Jan 13, 2025
Docstrings generation was requested by @ytti.

* #3362 (comment)

The following files were modified:

* `lib/oxidized/source/source.rb`
Copy link

coderabbitai bot commented Jan 13, 2025

Note

We have generated docstrings for this pull request, at #3366

@robertcheramy
Copy link
Collaborator

I'd like to extend the documentation:

  • Add some more texte in docs/Configuration.md (and not just an example)
  • Briefly comment the code. It is difficult for an AI to find the point between too short and over verbose. We will see if I am better at it ;-)
    I'll need a few day for this - I'm currently working on other topics.

@ytti
Copy link
Owner Author

ytti commented Jan 14, 2025

I'm ok with that. Personally I don't write or read ever comments which is English version of the code, to me it is non-sensical to maintain two versions of code, one in formal language another in natural language. I don't read them, because I don't trust that they are in sync, or that the English version ever was accurate about formal version.

I also try to write methods which are short, do one thing without side effects and fit in mental space, in which case it is often faster to just read the code. I think comments make more sense when the 'why' is important, not the 'what', like when you know what the code does, but you might not understand why it is needed. Or if code is particularly tricky and I couldn't figure out how to write it elegantly and simply. But each to their own, and I'm not going to reject any style of commenting.

@robertcheramy
Copy link
Collaborator

I like using comments because they help me understand the code faster later on, and I hope it helps others too.
In this case, it helps me to see in the code how the configuration is structured and what the method returns.

The PR is good for me an can be merged.

@ytti ytti merged commit c7f0bdc into master Jan 15, 2025
13 checks passed
@ytti ytti deleted the feat/regexp_model_map branch January 15, 2025 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Oxidized unable to parse/search multiple tags in http api call from PRTG
2 participants