| The require function has been implemented using the 4x function API, so you'll want to look at https://github.com/puppetlabs/puppet/blob/96029b003cfbb5303426cbc110f350a0d4b6af06/lib/puppet/functions/require.rb#L71-L72. Note resource is an instance of Puppet::Parser::Resource while ref is an instance of Puppet::Resource, and the former subclasses the latter. So you can compare the value objects directly to determine if they are equivalent. Given the following manifest:
class a { |
require a |
} |
include a
|
We expect it to raise a parse error during compilation with file, line, etc info. One option is to: 1. Add a new issue constant to Puppet::Pops::Issues 2. If resource == ref then call
raise Puppet::ParseErrorWithIssue.from_issue_and_stack( |
Puppet::Pops::Issues::YOUR_NEW_CONSTANT, |
{:operation => 'require'})
|
3. Add a test to spec/unit/functions/require_spec.rb to verify the excepted exception is raised when calling compile_to_catalog with the circular requirement. 4. Note this won't catch cycles among classes, e.g. A -> B -> A. Those will be caught later on. Alternatively, you could add logic to https://github.com/puppetlabs/puppet/blob/96029b003cfbb5303426cbc110f350a0d4b6af06/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb#L25 to ensure the resource is not the same as the found object:
if !found |
msg = _("Could not find resource '%{res}' in parameter '%{param}'") % { res: res, param: param.name.to_s } |
raise CatalogValidationError.new(msg, param.file, param.line) |
elsif found == resource |
msg = _("Resource '%{res}' cannot '%{param}' itself") % { res: res, param: param.name.to_s } |
raise CatalogValidationError.new(msg, param.file, param.line) |
end
|
|