Skip to content

feat: add PuppetDB Query V4 APIs#11

Open
zaben903 wants to merge 3 commits intomainfrom
feature/puppet_db_query
Open

feat: add PuppetDB Query V4 APIs#11
zaben903 wants to merge 3 commits intomainfrom
feature/puppet_db_query

Conversation

@zaben903
Copy link
Collaborator

@zaben903 zaben903 commented Jan 12, 2026

Note: Yard-lint is currently failing due to handling of YARD macros. This will be resolved once mensfeld/yard-lint#65 is merged

@zaben903 zaben903 requested a review from Copilot January 12, 2026 02:38
@zaben903 zaben903 self-assigned this Jan 12, 2026
@zaben903 zaben903 added the enhancement New feature or request label Jan 12, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds comprehensive support for PuppetDB Query V4 APIs to the PE Client Ruby library. The implementation provides a complete interface for querying PuppetDB data including nodes, facts, catalogs, reports, resources, events, and more.

Changes:

  • Added main PuppetDB resource class with Query V4 API support
  • Implemented 15+ query endpoints covering nodes, facts, catalogs, reports, events, packages, and inventory
  • Added specialized sub-resources for nodes, factsets, catalogs, and reports with their own endpoint methods
  • Included comprehensive RSpec tests for all endpoints with required and optional parameter scenarios
  • Provided RBS type signatures for type checking

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
lib/pe_client/client.rb Adds puppet_db accessor method to client
lib/pe_client/resources/puppet_db.rb Main PuppetDB resource class with port configuration and query_v4 accessor
lib/pe_client/resources/puppet_db/query.v4.rb Core Query V4 implementation with 15+ endpoint methods
lib/pe_client/resources/puppet_db/query.v4/nodes.rb Node-specific endpoints for facts and resources
lib/pe_client/resources/puppet_db/query.v4/factsets.rb Factset query endpoints
lib/pe_client/resources/puppet_db/query.v4/catalogs.rb Catalog query endpoints with edges and resources
lib/pe_client/resources/puppet_db/query.v4/reports.rb Report query endpoints with events, metrics, and logs
sig/pe_client/resource/puppet_db.rbs Type signature for main PuppetDB resource
sig/pe_client/resource/puppet_db/query.v4.rbs Type signatures for Query V4 endpoints
sig/pe_client/resource/puppet_db/query.v4/nodes.rbs Type signatures for nodes sub-resource
sig/pe_client/resource/puppet_db/query.v4/factsets.rbs Type signatures for factsets sub-resource
sig/pe_client/resource/puppet_db/query.v4/catalogs.rbs Type signatures for catalogs sub-resource
sig/pe_client/resource/puppet_db/query.v4/reports.rbs Type signatures for reports sub-resource
spec/pe_client/resources/puppet_db_spec.rb Tests for main PuppetDB resource initialization and memoization
spec/pe_client/resources/puppet_db/query_v4_spec.rb Comprehensive tests for all Query V4 endpoints
spec/pe_client/resources/puppet_db/query_v4/nodes_spec.rb Tests for node-specific endpoints
spec/pe_client/resources/puppet_db/query_v4/factsets_spec.rb Tests for factset endpoints
spec/pe_client/resources/puppet_db/query_v4/catalogs_spec.rb Tests for catalog endpoints
spec/pe_client/resources/puppet_db/query_v4/reports_spec.rb Tests for report endpoints

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 8 comments.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 16 comments.

Comment on lines +5 to +6
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4/factsets"
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The require paths use dots in the filename "query.v4" which does not follow Ruby conventions. Ruby filenames should use underscores, not dots (except for the file extension). These should be "query_v4" to match standard Ruby naming conventions.

Suggested change
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4/factsets"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query_v4"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query_v4/factsets"

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +6
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4/catalogs"
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The require paths use dots in the filename "query.v4" which does not follow Ruby conventions. Ruby filenames should use underscores, not dots (except for the file extension). These should be "query_v4" to match standard Ruby naming conventions.

Suggested change
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4/catalogs"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query_v4"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query_v4/catalogs"

Copilot uses AI. Check for mistakes.

# @return [QueryV4::Factsets]
def factsets
require_relative "query.v4/factsets"
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The require path uses dots in the filename "query.v4/factsets" which does not follow Ruby conventions. Ruby filenames and directory names should use underscores, not dots (except for the file extension). This should be "query_v4/factsets" to match standard Ruby naming conventions.

Suggested change
require_relative "query.v4/factsets"
require_relative "query_v4/factsets"

Copilot uses AI. Check for mistakes.
Comment on lines +338 to +356
require_relative "query.v4/nodes"
@nodes ||= QueryV4::Nodes.new(@client)
end

# @return [QueryV4::Factsets]
def factsets
require_relative "query.v4/factsets"
@factsets ||= QueryV4::Factsets.new(@client)
end

# @return [QueryV4::Catalogs]
def catalogs
require_relative "query.v4/catalogs"
@catalogs ||= QueryV4::Catalogs.new(@client)
end

# @return [QueryV4::Reports]
def reports
require_relative "query.v4/reports"
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The require path uses dots in the filename "query.v4/catalogs" which does not follow Ruby conventions. Ruby filenames and directory names should use underscores, not dots (except for the file extension). This should be "query_v4/catalogs" to match standard Ruby naming conventions.

Suggested change
require_relative "query.v4/nodes"
@nodes ||= QueryV4::Nodes.new(@client)
end
# @return [QueryV4::Factsets]
def factsets
require_relative "query.v4/factsets"
@factsets ||= QueryV4::Factsets.new(@client)
end
# @return [QueryV4::Catalogs]
def catalogs
require_relative "query.v4/catalogs"
@catalogs ||= QueryV4::Catalogs.new(@client)
end
# @return [QueryV4::Reports]
def reports
require_relative "query.v4/reports"
require_relative "query_v4/nodes"
@nodes ||= QueryV4::Nodes.new(@client)
end
# @return [QueryV4::Factsets]
def factsets
require_relative "query_v4/factsets"
@factsets ||= QueryV4::Factsets.new(@client)
end
# @return [QueryV4::Catalogs]
def catalogs
require_relative "query_v4/catalogs"
@catalogs ||= QueryV4::Catalogs.new(@client)
end
# @return [QueryV4::Reports]
def reports
require_relative "query_v4/reports"

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +15
module PEClient
module Resource
class PuppetDB
class QueryV4
class Nodes < Base
BASE_PATH: String

def get: (?node: String?, ?query: Array[untyped]?, **untyped) -> (Array[Hash[String, untyped]] | Hash[String, untyped])
def facts: (node: String, ?name: String?, ?value: String?, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def resources: (node: String, ?type: String?, ?title: String?, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
end
end
end
end
end No newline at end of file
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The RBS file path uses dots in the directory name "query.v4" which does not follow Ruby conventions. This should be "query_v4" to match standard Ruby naming conventions and be consistent with Ruby file naming practices.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +6
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4/nodes"
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The require paths use dots in the filename "query.v4" which does not follow Ruby conventions. Ruby filenames should use underscores, not dots (except for the file extension). These should be "query_v4" to match standard Ruby naming conventions.

Suggested change
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query.v4/nodes"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query_v4"
require_relative "../../../../../lib/pe_client/resources/puppet_db/query_v4/nodes"

Copilot uses AI. Check for mistakes.
Comment on lines +338 to +356
require_relative "query.v4/nodes"
@nodes ||= QueryV4::Nodes.new(@client)
end

# @return [QueryV4::Factsets]
def factsets
require_relative "query.v4/factsets"
@factsets ||= QueryV4::Factsets.new(@client)
end

# @return [QueryV4::Catalogs]
def catalogs
require_relative "query.v4/catalogs"
@catalogs ||= QueryV4::Catalogs.new(@client)
end

# @return [QueryV4::Reports]
def reports
require_relative "query.v4/reports"
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The require path uses dots in the filename "query.v4/nodes" which does not follow Ruby conventions. Ruby filenames and directory names should use underscores, not dots (except for the file extension). This should be "query_v4/nodes" to match standard Ruby naming conventions.

Suggested change
require_relative "query.v4/nodes"
@nodes ||= QueryV4::Nodes.new(@client)
end
# @return [QueryV4::Factsets]
def factsets
require_relative "query.v4/factsets"
@factsets ||= QueryV4::Factsets.new(@client)
end
# @return [QueryV4::Catalogs]
def catalogs
require_relative "query.v4/catalogs"
@catalogs ||= QueryV4::Catalogs.new(@client)
end
# @return [QueryV4::Reports]
def reports
require_relative "query.v4/reports"
require_relative "query_v4/nodes"
@nodes ||= QueryV4::Nodes.new(@client)
end
# @return [QueryV4::Factsets]
def factsets
require_relative "query_v4/factsets"
@factsets ||= QueryV4::Factsets.new(@client)
end
# @return [QueryV4::Catalogs]
def catalogs
require_relative "query_v4/catalogs"
@catalogs ||= QueryV4::Catalogs.new(@client)
end
# @return [QueryV4::Reports]
def reports
require_relative "query_v4/reports"

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +16
module PEClient
module Resource
class PuppetDB
class QueryV4
class Reports < Base
BASE_PATH: String

def get: (?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def events: (hash: String, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def metrics: (hash: String) -> Array[Hash[String, untyped]]
def logs: (hash: String) -> Array[Hash[String, untyped]]
end
end
end
end
end No newline at end of file
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The RBS file path uses dots in the directory name "query.v4" which does not follow Ruby conventions. This should be "query_v4" to match standard Ruby naming conventions and be consistent with Ruby file naming practices.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +16
module PEClient
module Resource
class PuppetDB
class QueryV4
class Catalogs < Base
BASE_PATH: String

def get: (?node: nil, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
| (node: String, ?query: Array[untyped]?, **untyped) -> Hash[String, untyped]
def edges: (node: String, **untyped) -> Array[Hash[String, untyped]]
def resources: (node: String, **untyped) -> Array[Hash[String, untyped]]
end
end
end
end
end No newline at end of file
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The RBS file path uses dots in the directory name "query.v4" which does not follow Ruby conventions. This should be "query_v4" to match standard Ruby naming conventions and be consistent with Ruby file naming practices.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +39
module PEClient
module Resource
class PuppetDB
class QueryV4 < Base
BASE_PATH: String

def root: (query: Array[untyped], ?timeout: Integer?, ?ast_only: bool?, ?origin: String?, ?explain: String?, **untyped) -> Array[Hash[String, untyped]]
def environments: (?environment: String?, ?type: String?, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def producers: (?producer: nil, ?type: nil, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
| (producer: String, ?type: nil, ?query: Array[untyped]?, **untyped) -> Hash[String, untyped]
| (producer: String, type: String, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def facts: (?fact_name: String?, ?value: String?, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def fact_names: (?query: Array[untyped]?, **untyped) -> Array[String]
def fact_paths: (?query: Array[untyped]?, **untyped) -> Array[String]
def fact_contents: (?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def inventory: (?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def resources: (?type: String?, ?title: String?, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def edges: (?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def events: (?distinct_resources: nil, ?distinct_start_time: nil, ?distinct_end_time: nil, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
| (distinct_resources: bool, ?distinct_start_time: String, ?distinct_end_time: String, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def event_counts: (summarize_by: String, ?count_by: String?, ?counts_filter: Array[untyped]?, ?distinct_resources: bool?, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def aggregate_event_counts: (summarize_by: String, ?count_by: String?, ?counts_filter: Array[untyped]?, ?distinct_resources: bool?, ?query: Array[untyped]?) -> Array[Hash[String, untyped]]
def packages: (?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]
def package_inventory: (?certname: String?, ?query: Array[untyped]?, **untyped) -> Array[Hash[String, untyped]]

@nodes: QueryV4::Nodes
def nodes: () -> QueryV4::Nodes
@factsets: QueryV4::Factsets
def factsets: () -> QueryV4::Factsets
@catalogs: QueryV4::Catalogs
def catalogs: () -> QueryV4::Catalogs
@reports: QueryV4::Reports
def reports: () -> QueryV4::Reports

def self.query_paging: (**untyped) -> Hash[Symbol, untyped]
end
end
end
end No newline at end of file
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The RBS file path uses dots in the filename "query.v4.rbs" which does not follow Ruby conventions. This should be "query_v4.rbs" to match standard Ruby naming conventions and be consistent with Ruby file naming practices.

Copilot uses AI. Check for mistakes.
fixed `resource` URI generation
fixed working of `Nodes` class documentation
fixed missing RBS definition
fixed kwargs type definition
added missing URI construction tests
@zaben903 zaben903 force-pushed the feature/puppet_db_query branch from 212d7bb to 2b23079 Compare January 12, 2026 06:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant