Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/pe_client/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ def puppet_ca_v1
@puppet_ca_v1 ||= Resource::PuppetCAV1.new(self)
end

# @return [Resource::PuppetDB]
def puppet_db
require_relative "resources/puppet_db"
@puppet_db ||= Resource::PuppetDB.new(self)
end

private

# Handle HTTP response
Expand Down
38 changes: 38 additions & 0 deletions lib/pe_client/resources/puppet_db.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true

# Copyright 2025 Perforce Software Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require_relative "base_with_port"

module PEClient
module Resource
# Interact with PuppetDB
#
# @see https://help.puppet.com/pdb/current/topics/api.htm
class PuppetDB < BaseWithPort
# The base path for PuppetDB endpoints.
BASE_PATH = "/pdb"

# Default PuppetDB API Port
PORT = 8080

# @return [PuppetDB::QueryV4]
def query_v4
require_relative "puppet_db/query.v4"
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 "puppet_db/query.v4" which does not follow Ruby conventions. Ruby filenames and directory names should use underscores, not dots (except for the file extension). This should be "puppet_db/query_v4" to match standard Ruby naming conventions.

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

Copilot uses AI. Check for mistakes.
@query_v4 ||= PuppetDB::QueryV4.new(@client)
end
end
end
end
373 changes: 373 additions & 0 deletions lib/pe_client/resources/puppet_db/query.v4.rb

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions lib/pe_client/resources/puppet_db/query.v4/catalogs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# frozen_string_literal: true

# Copyright 2025 Perforce Software Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require_relative "../../base"

module PEClient
module Resource
class PuppetDB
class QueryV4
# You can query catalogs by making an HTTP request to the catalogs endpoint.
#
# @see https://help.puppet.com/pdb/current/topics/catalogs.htm
class Catalogs < Base
# The base path for PuppetDB Query v4 Catalogs endpoints.
BASE_PATH = "#{QueryV4::BASE_PATH}/catalogs".freeze

# This will return a JSON array containing the most recent catalog for each node or for a given node in your infrastructure.
#
# @param node [String]
# @macro query
# @macro query_paging
#
# @return [Array<Hash>, Hash]
#
# @see https://help.puppet.com/pdb/current/topics/catalogs.htm#pdbqueryv4catalogs
# @see https://help.puppet.com/pdb/current/topics/catalogs.htm#pdbqueryv4catalogsnode
def get(node: nil, query: nil, **kwargs)
@client.get node ? "#{BASE_PATH}/#{node}" : BASE_PATH,
params: {query: query&.to_json}.merge!(QueryV4.query_paging(**kwargs)).compact
end

# This will return all edges for a particular catalog, designated by a node certname.
# This is a shortcut to the {QueryV4#edges} endpoint. It behaves the same as a call to {QueryV4#edges} with `query: ["=", "certname", "<NODE>"]`.
# Except results are returned even if the node is deactivated or expired.
#
# @param node [String]
# @macro query_paging
#
# @return [Array<Hash>]
#
# @see https://help.puppet.com/pdb/current/topics/catalogs.htm#pdbqueryv4catalogsnodeedges
def edges(node:, **kwargs)
@client.get "#{BASE_PATH}/#{node}/edges", params: QueryV4.query_paging(**kwargs).compact
end

# This will return all resources for a particular catalog, designated by a node certname.
# This is a shortcut to the {QueryV4#resources} endpoint. It behaves the same as a call to {QueryV4#resources} with `query: ["=", "certname", "<NODE>"]`.
# Except results are returned even if the node is deactivated or expired.
#
# @param node [String]
# @macro query_paging
#
# @return [Array<Hash>]
#
# @see https://help.puppet.com/pdb/current/topics/catalogs.htm#pdbqueryv4catalogsnoderesources
def resources(node:, **kwargs)
@client.get "#{BASE_PATH}/#{node}/resources", params: QueryV4.query_paging(**kwargs).compact
end
end
end
end
end
end
65 changes: 65 additions & 0 deletions lib/pe_client/resources/puppet_db/query.v4/factsets.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

# Copyright 2025 Perforce Software Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require_relative "../../base"

module PEClient
module Resource
class PuppetDB
class QueryV4
# The factsets endpoint provides access to a representation of node factsets where each result includes the structured facts for a node broken down into a vector of top-level key/value pairs.
# Note that the inventory endpoint will often provide more flexible and efficient access to the same information.
#
# @see https://help.puppet.com/pdb/current/topics/factsets.htm
class Factsets < Base
# The base path for PuppetDB Query v4 Factsets endpoints.
BASE_PATH = "#{QueryV4::BASE_PATH}/factsets".freeze

# This will return all factsets matching the given query.
#
# @param node [String] This will return the most recent factset for the given node.
# @macro query
# @macro query_paging
#
# @return [Array<Hash>, Hash]
#
# @see {QueryV4#query_paging} for paging options
# @see https://help.puppet.com/pdb/current/topics/factsets.htm#pdbqueryv4factsets
# @see https://help.puppet.com/pdb/current/topics/factsets.htm#pdbqueryv4factsetsnode
def get(node: nil, query: nil, **kwargs)
@client.get node ? "#{BASE_PATH}/#{node}" : BASE_PATH,
params: {query: query&.to_json}.merge!(QueryV4.query_paging(**kwargs)).compact
end

# This will return all facts for a particular factset, designated by a node certname.
# This is a shortcut to the {QueryV4#facts} endpoint.
# It behaves the same as a call to {QueryV4#facts} with a query string of ["=", "certname", "<NODE>"], except results are returned even if the node is deactivated or expired.
#
# @param node [String]
# @macro query_paging
#
# @return [Array<Hash>]
#
# @see {QueryV4#facts} for more details
# @see https://help.puppet.com/pdb/current/topics/factsets.htm#pdbqueryv4factsetsnodefacts
def facts(node:, **kwargs)
@client.get "#{BASE_PATH}/#{node}/facts", params: QueryV4.query_paging(**kwargs).compact
end
end
end
end
end
end
96 changes: 96 additions & 0 deletions lib/pe_client/resources/puppet_db/query.v4/nodes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# frozen_string_literal: true

# Copyright 2025 Perforce Software Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require_relative "../../base"

module PEClient
module Resource
class PuppetDB
class QueryV4
# Nodes can be queried by making requests through these endpoints.
#
# @see https://help.puppet.com/pdb/current/topics/nodes.htm
class Nodes < Base
# The base path for PuppetDB Query v4 Nodes endpoints.
BASE_PATH = "#{QueryV4::BASE_PATH}/nodes".freeze

# This will return all nodes matching the given query.
# Deactivated and expired nodes aren't included in the response.
#
# @param node [String] This will return status information for the given node, active or not.
# It behaves exactly like a call with `node: nil` but with a query string of ["=", "certname", "<NODE>"].
# @macro query
# @macro query_paging
#
# @return [Array<Hash>, Hash]
#
# @see https://help.puppet.com/pdb/current/topics/nodes.htm#pdbqueryv4nodes
# @see https://help.puppet.com/pdb/current/topics/nodes.htm#pdbqueryv4nodesnode
def get(node: nil, query: nil, **kwargs)
@client.get node ? "#{BASE_PATH}/#{node}" : BASE_PATH,
params: {query: query&.to_json}.merge!(QueryV4.query_paging(**kwargs)).compact
end

# This will return the facts for the given node. Facts from deactivated and expired nodes aren't included in the response.
# This is a shortcut to the {QueryV4#facts} endpoint.
# It behaves the same as a call to {QueryV4#facts} with a query string of ["=", "certname", "<NODE>"].
# Facts from deactivated and expired nodes aren't included in the response.
#
# @param node [String]
# @param name [String] This will return facts with the given name for the given node.
# @param value [String] This will return facts with the given name and value for the given node.
# @macro query
# @macro query_paging
#
# @return [Array<Hash>]
#
# @see https://help.puppet.com/pdb/current/topics/nodes.htm#pdbqueryv4nodesnodefacts
# @see https://help.puppet.com/pdb/current/topics/nodes.htm#pdbqueryv4nodesnodefactsname
# @see https://help.puppet.com/pdb/current/topics/nodes.htm#pdbqueryv4nodesnodefactsnamevalue
def facts(node:, name: nil, value: nil, query: nil, **kwargs)
uri = "#{BASE_PATH}/#{node}/facts"
uri += "/#{name}" if name
uri += "/#{value}" if name && value
@client.get uri, params: {query: query&.to_json}.merge!(QueryV4.query_paging(**kwargs)).compact
end

# This will return the resources for the given node.
# Resources from deactivated and expired nodes aren't included in the response.
# This is a shortcut to the {QueryV4#resources} endpoint.
# It behaves the same as a call to {QueryV4#resources} with a query string of ["=", "certname", "<NODE>"].
#
# @param node [String]
# @param type [String] This will return the resources of the indicated type for the given node.
# @param title [String] This will return the resource of the indicated type and title for the given node.
# @macro query
# @macro query_paging
#
# @return [Array<Hash>]
#
# @see https://help.puppet.com/pdb/current/topics/nodes.htm#pdbqueryv4nodesnoderesources
# @see https://help.puppet.com/pdb/current/topics/nodes.htm#pdbqueryv4nodesnoderesourcestype
# @see https://help.puppet.com/pdb/current/topics/nodes.htm#pdbqueryv4nodesnoderesourcestypetitle
def resources(node:, type: nil, title: nil, query: nil, **kwargs)
uri = "#{BASE_PATH}/#{node}/resources"
uri += "/#{type}" if type
uri += "/#{title}" if type && title
@client.get uri, params: {query: query&.to_json}.merge!(QueryV4.query_paging(**kwargs)).compact
end
end
end
end
end
end
91 changes: 91 additions & 0 deletions lib/pe_client/resources/puppet_db/query.v4/reports.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# frozen_string_literal: true

# Copyright 2025 Perforce Software Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require_relative "../../base"

module PEClient
module Resource
class PuppetDB
class QueryV4
# Puppet agent nodes submit reports after their runs, and the Puppet Server forwards these to PuppetDB. Each report includes:
# - Data about the entire run
# - Metadata about the report
# - Many events, describing what happened during the run
#
# After this information is stored in PuppetDB, it can be queried in various ways.
# - You can query data about the run and report metadata by making an HTTP request to the reports endpoint.
# - You can query data about individual events by making an HTTP request to the {QueryV4#events} endpoint.
# - You can query summaries of event data by making an HTTP request to the {QueryV4#event_counts} or {QueryV4#aggregate_event_counts} endpoints.
#
# @see https://help.puppet.com/pdb/current/topics/reports.htm
class Reports < Base
# The base path for PuppetDB Query v4 Reports endpoints.
BASE_PATH = "#{QueryV4::BASE_PATH}/reports".freeze

# If `:query` is absent, PuppetDB will return all reports.
#
# @macro query
# @macro query_paging
#
# @return [Array<Hash>]
#
# @see https://help.puppet.com/pdb/current/topics/reports.htm#pdbqueryv4reports
def get(query: nil, **kwargs)
@client.get(BASE_PATH, params: {query: query&.to_json}.merge!(QueryV4.query_paging(**kwargs)).compact)
end

# Returns all events for a particular report, designated by its unique hash.
#
# @param hash [String] The unique hash of the report.
# @macro query
# @macro query_paging
#
# @return [Array<Hash>]
#
# @see https://help.puppet.com/pdb/current/topics/reports.htm#pdbqueryv4reportshashevents
def events(hash:, query: nil, **kwargs)
@client.get "#{BASE_PATH}/#{hash}/events",
params: {query: query&.to_json}.merge!(QueryV4.query_paging(**kwargs)).compact
end

# Returns all metrics for a particular report, designated by its unique hash.
# This endpoint does not currently support querying or paging.
#
# @param hash [String] The unique hash of the report.
#
# @return [Array<Hash>]
#
# @see https://help.puppet.com/pdb/current/topics/reports.htm#pdbqueryv4reportshashmetrics
def metrics(hash:)
@client.get "#{BASE_PATH}/#{hash}/metrics"
end

# Returns all logs for a particular report, designated by its unique hash.
# This endpoint does not currently support querying or paging.
#
# @param hash [String] The unique hash of the report.
#
# @return [Array<Hash>]
#
# @see https://help.puppet.com/pdb/current/topics/reports.htm#pdbqueryv4reportshashlogs
def logs(hash:)
@client.get "#{BASE_PATH}/#{hash}/logs"
end
end
end
end
end
end
2 changes: 2 additions & 0 deletions sig/pe_client/client.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ module PEClient
def puppet_v3: -> Resource::PuppetV3
@puppet_ca_v1: Resource::PuppetCAV1
def puppet_ca_v1: -> Resource::PuppetCAV1
@puppet_db: Resource::PuppetDB
def puppet_db: -> Resource::PuppetDB

# Private methods
def handle_response: (Faraday::Response, ?headers_only: bool) -> untyped
Expand Down
Loading
Loading