Class: OctocatalogDiff::Catalog
- Inherits:
-
Object
- Object
- OctocatalogDiff::Catalog
- Defined in:
- lib/octocatalog-diff/catalog.rb,
lib/octocatalog-diff/catalog/json.rb,
lib/octocatalog-diff/catalog/noop.rb,
lib/octocatalog-diff/catalog/computed.rb,
lib/octocatalog-diff/catalog/puppetdb.rb,
lib/octocatalog-diff/catalog/puppetmaster.rb
Overview
Basic methods for interacting with a catalog. Generation of the catalog is handled via one of the supported backends listed above as ‘require_relative’. Usually, the ‘computed’ backend will build the catalog from the Puppet command.
Direct Known Subclasses
Defined Under Namespace
Classes: Computed, JSON, Noop, PuppetDB, PuppetMaster
Instance Attribute Summary collapse
-
#built ⇒ Object
readonly
Returns the value of attribute built.
-
#catalog ⇒ Object
readonly
Returns the value of attribute catalog.
-
#catalog_json ⇒ Object
Returns the value of attribute catalog_json.
-
#node ⇒ Object
Returns the value of attribute node.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Class Method Summary collapse
-
.create(options = {}) ⇒ OctocatalogDiff::Catalog::<?>
Guess the backend from the input and return the appropriate catalog object.
Instance Method Summary collapse
-
#build(logger = Logger.new(StringIO.new)) ⇒ Object
Build catalog - this method needs to be called to build the catalog.
-
#build_catalog(_logger) ⇒ Object
Stub method if the backend does not contain a build method.
-
#builder ⇒ String
For logging we may wish to know the backend being used.
-
#compilation_dir ⇒ String
This retrieves the compilation directory from the catalog, or otherwise the passed-in directory.
-
#compilation_dir=(dir) ⇒ Object
The compilation directory can be overridden, e.g.
-
#convert_file_resources(_dry_run = false) ⇒ Object
Stub method for “convert_file_resources” – returns false because if the underlying class does not implement this method, it’s not supported.
-
#environment ⇒ String
Compilation environment.
-
#error_message ⇒ String
Retrieve the error message.
-
#error_message=(error) ⇒ Object
Allow setting the error message.
-
#initialize(options = {}) ⇒ Catalog
constructor
Constructor.
-
#puppet_version ⇒ String
Stub method to return the puppet version if the back end doesn’t support this.
-
#resource(opts = {}) ⇒ Hash
This allows retrieving a resource by type and title.
-
#resources ⇒ Array
This is a compatibility layer for the resources, which are in a different place in Puppet 3.x and Puppet 4.x.
-
#retries ⇒ Integer
Stub method of the the number of retries necessary to compile the catalog.
-
#valid? ⇒ Boolean
Determine if the catalog build was successful.
-
#validate_references ⇒ Object
Determine if all of the (before, notify, require, subscribe) targets are actually in the catalog.
Constructor Details
#initialize(options = {}) ⇒ Catalog
Constructor
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/octocatalog-diff/catalog.rb', line 23 def initialize( = {}) unless .is_a?(Hash) raise ArgumentError, "#{self.class}.initialize requires hash argument, not #{.class}" end @options = # Basic settings @node = [:node] @error_message = nil @catalog = nil @catalog_json = nil @retries = nil # The compilation directory can be overridden, e.g. when testing @override_compilation_dir = [:compilation_dir] # Keep track of whether references have been validated yet. Allow this to be fudged for when we do # not desire reference validation to happen (e.g., for the "from" catalog that is otherwise valid). @references_validated = [:references_validated] || false # Keep track of whether file resources have been converted. @file_resources_converted = false # Keep track of whether it's built yet @built = false end |
Instance Attribute Details
#built ⇒ Object (readonly)
Returns the value of attribute built.
20 21 22 |
# File 'lib/octocatalog-diff/catalog.rb', line 20 def built @built end |
#catalog ⇒ Object (readonly)
Returns the value of attribute catalog.
20 21 22 |
# File 'lib/octocatalog-diff/catalog.rb', line 20 def catalog @catalog end |
#catalog_json ⇒ Object
Returns the value of attribute catalog_json.
20 21 22 |
# File 'lib/octocatalog-diff/catalog.rb', line 20 def catalog_json @catalog_json end |
#node ⇒ Object
Returns the value of attribute node.
19 20 21 |
# File 'lib/octocatalog-diff/catalog.rb', line 19 def node @node end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
20 21 22 |
# File 'lib/octocatalog-diff/catalog.rb', line 20 def @options end |
Class Method Details
.create(options = {}) ⇒ OctocatalogDiff::Catalog::<?>
Guess the backend from the input and return the appropriate catalog object.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/octocatalog-diff/catalog.rb', line 62 def self.create( = {}) # Hard-coded backend if [:backend] return OctocatalogDiff::Catalog::JSON.new() if [:backend] == :json return OctocatalogDiff::Catalog::PuppetDB.new() if [:backend] == :puppetdb return OctocatalogDiff::Catalog::PuppetMaster.new() if [:backend] == :puppetmaster return OctocatalogDiff::Catalog::Computed.new() if [:backend] == :computed return OctocatalogDiff::Catalog::Noop.new() if [:backend] == :noop raise ArgumentError, "Unknown backend :#{[:backend]}" end # Determine backend based on arguments return OctocatalogDiff::Catalog::JSON.new() if [:json] return OctocatalogDiff::Catalog::PuppetDB.new() if [:puppetdb] return OctocatalogDiff::Catalog::PuppetMaster.new() if [:puppet_master] # Default is to build catalog ourselves OctocatalogDiff::Catalog::Computed.new() end |
Instance Method Details
#build(logger = Logger.new(StringIO.new)) ⇒ Object
Build catalog - this method needs to be called to build the catalog. It is separate due to the serialization of the logger object – the parallel gem cannot serialize/deserialize a logger object so it cannot be part of any object that is passed around.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/octocatalog-diff/catalog.rb', line 86 def build(logger = Logger.new(StringIO.new)) # If already built, don't build again return if @built @built = true # The resource hash is computed the first time it's needed. For now initialize it as nil. @resource_hash = nil # Invoke the backend's build method, if there is one. There's a stub below in case there's not. logger.debug "Calling build for object #{self.class}" build_catalog(logger) # Perform post-generation processing of the catalog return unless valid? validate_references return unless valid? convert_file_resources if @options[:compare_file_text] true end |
#build_catalog(_logger) ⇒ Object
Stub method if the backend does not contain a build method.
110 111 |
# File 'lib/octocatalog-diff/catalog.rb', line 110 def build_catalog(_logger) end |
#builder ⇒ String
For logging we may wish to know the backend being used
121 122 123 |
# File 'lib/octocatalog-diff/catalog.rb', line 121 def builder self.class.to_s end |
#compilation_dir ⇒ String
This retrieves the compilation directory from the catalog, or otherwise the passed-in directory.
134 135 136 |
# File 'lib/octocatalog-diff/catalog.rb', line 134 def compilation_dir @override_compilation_dir || @options[:basedir] end |
#compilation_dir=(dir) ⇒ Object
The compilation directory can be overridden, e.g. during testing.
140 141 142 |
# File 'lib/octocatalog-diff/catalog.rb', line 140 def compilation_dir=(dir) @override_compilation_dir = dir end |
#convert_file_resources(_dry_run = false) ⇒ Object
Stub method for “convert_file_resources” – returns false because if the underlying class does not implement this method, it’s not supported.
146 147 148 |
# File 'lib/octocatalog-diff/catalog.rb', line 146 def convert_file_resources(_dry_run = false) false end |
#environment ⇒ String
Compilation environment
115 116 117 |
# File 'lib/octocatalog-diff/catalog.rb', line 115 def environment @environment ||= 'production' end |
#error_message ⇒ String
Retrieve the error message.
152 153 154 155 156 |
# File 'lib/octocatalog-diff/catalog.rb', line 152 def build return nil if @error_message.nil? || !@error_message.is_a?(String) @error_message[0, 20_000] end |
#error_message=(error) ⇒ Object
Allow setting the error message. If the error message is set to a string, the catalog and catalog JSON are set to nil.
161 162 163 164 165 166 167 |
# File 'lib/octocatalog-diff/catalog.rb', line 161 def (error) raise ArgumentError, 'Error message must be a string' unless error.is_a?(String) @error_message = error @catalog = nil @catalog_json = nil @resource_hash = nil end |
#puppet_version ⇒ String
Stub method to return the puppet version if the back end doesn’t support this.
171 172 173 174 |
# File 'lib/octocatalog-diff/catalog.rb', line 171 def puppet_version build @options[:puppet_version] end |
#resource(opts = {}) ⇒ Hash
This allows retrieving a resource by type and title. This is intended for use when a O(1) lookup is required.
180 181 182 183 184 185 186 |
# File 'lib/octocatalog-diff/catalog.rb', line 180 def resource(opts = {}) raise ArgumentError, ':type and :title are required' unless opts[:type] && opts[:title] build build_resource_hash if @resource_hash.nil? return nil unless @resource_hash[opts[:type]].is_a?(Hash) @resource_hash[opts[:type]][opts[:title]] end |
#resources ⇒ Array
This is a compatibility layer for the resources, which are in a different place in Puppet 3.x and Puppet 4.x
190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/octocatalog-diff/catalog.rb', line 190 def resources build raise OctocatalogDiff::Errors::CatalogError, 'Catalog does not appear to have been built' if !valid? && .nil? raise OctocatalogDiff::Errors::CatalogError, unless valid? # Handle the structure returned by the /puppet/v4/catalog Puppetserver endpoint: return @catalog['catalog']['resources'] if @catalog['catalog'].is_a?(Hash) && @catalog['catalog']['resources'].is_a?(Array) return @catalog['data']['resources'] if @catalog['data'].is_a?(Hash) && @catalog['data']['resources'].is_a?(Array) return @catalog['resources'] if @catalog['resources'].is_a?(Array) # This is a bug condition # :nocov: raise "BUG: catalog has no data::resources or ::resources array. Please report this. #{@catalog.inspect}" # :nocov: end |
#retries ⇒ Integer
Stub method of the the number of retries necessary to compile the catalog. If the underlying catalog generation backend does not support retries, nil is returned.
207 208 209 |
# File 'lib/octocatalog-diff/catalog.rb', line 207 def retries nil end |
#valid? ⇒ Boolean
Determine if the catalog build was successful.
213 214 215 216 |
# File 'lib/octocatalog-diff/catalog.rb', line 213 def valid? build !@catalog.nil? end |
#validate_references ⇒ Object
Determine if all of the (before, notify, require, subscribe) targets are actually in the catalog. Raise a OctocatalogDiff::Errors::ReferenceValidationError for any found to be missing. Uses @options to influence which references are checked.
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/octocatalog-diff/catalog.rb', line 221 def validate_references # If we've already done the validation, don't do it again return if @references_validated @references_validated = true # Skip out early if no reference validation has been requested. unless @options[:validate_references].is_a?(Array) && @options[:validate_references].any? return end # Puppet 5 has reference validation built-in and enabled, so there won't even be a valid catalog if # there were invalid references. It's pointless to perform validation of our own. return if puppet_version && puppet_version >= '5.0.0' # Iterate over all the resources and check each one that has one of the attributes being checked. # Keep track of all references that are missing for ultimate inclusion in the error message. missing = [] resources.each do |x| @options[:validate_references].each do |r| next unless x.key?('parameters') next unless x['parameters'].key?(r) missing_resources = resources_missing_from_catalog(x['parameters'][r]) next unless missing_resources.any? missing.concat missing_resources.map { |missing_target| { source: x, target_type: r, target_value: missing_target } } end end return if missing.empty? # At this point there is at least one broken/missing reference. Format an error message and raise. errors = format_missing_references(missing) plural = errors =~ /;/ ? 's' : '' self. = "Catalog has broken reference#{plural}: #{errors}" end |