# Test whether a given class or definition is defined Puppet::Parser::Functions::newfunction(:defined, :type => :rvalue, :arity => -2, :doc => "Determine whether a given class or resource type is defined. This function can also determine whether a specific resource has been defined, or whether a variable has been assigned a value (including `undef` - as opposed to never having been assigned anything). Returns `true` or `false`. Accepts class names, type names, resource references, and variable reference strings of the form `'$name'`. When more than one argument is supplied, `defined()` returns `true` if any are defined. The `defined` function checks both native and defined types, including types provided as plugins via modules. Types and classes are both checked using their names: defined(\"file\") defined(\"customtype\") defined(\"foo\") defined(\"foo::bar\") defined(\'$name\') Resource declarations are checked using resource references, e.g. `defined( File['/tmp/myfile'] )`. Checking whether a given resource has been declared is, unfortunately, dependent on the evaluation order of the configuration, and the following code will not work: if defined(File['/tmp/foo']) { notify { \"This configuration includes the /tmp/foo file.\":} } file { \"/tmp/foo\": ensure => present, } However, this order requirement refers to evaluation order only, and ordering of resources in the configuration graph (e.g. with `before` or `require`) does not affect the behavior of `defined`. You may also search using types: defined(Resource[\'file\',\'/some/file\']) defined(File[\'/some/file\']) defined(Class[\'foo\']) The `defined` function does not answer if 4.x data types (e.g. `Integer`) are defined. If given the string 'integer' the result is false, and if given a non CatalogEntry type, an error is raised. The rules for asking for undef, empty strings, and the main class are different from 3.x (non future parser) and 4.x (with future parser or in Puppet 4.0.0 and later): defined('') # 3.x => true, 4.x => false defined(undef) # 3.x => true, 4.x => error defined('main') # 3.x => false, 4.x => true With the future parser, it is also possible to ask specifically if a name is a resource type (built in or defined), or a class, by giving its type: defined(Type[Class['foo']]) defined(Type[Resource['foo']]) Which is different from asking: defined('foo') Since the later returns true if 'foo' is either a class, a built-in resource type, or a user defined resource type, and a specific request like `Type[Class['foo']]` only returns true if `'foo'` is a class. - Since 2.7.0 - Since 3.6.0 variable reference and future parser types - Since 3.8.1 type specific requests with future parser") do |vals| vals = [vals] unless vals.is_a?(Array) vals.any? do |val| case val when String if m = /^\$(.+)$/.match(val) exist?(m[1]) else find_resource_type(val) || find_definition(val) || find_hostclass(val) end when Puppet::Resource compiler.findresource(val.type, val.title) when Puppet::Pops::Types::PResourceType raise ArgumentError, "The given resource type is a reference to all kind of types" if val.type_name.nil? if val.title.nil? find_builtin_resource_type(val.type_name) || find_definition(val.type_name) else compiler.findresource(val.type_name, val.title) end when Puppet::Pops::Types::PHostClassType raise ArgumentError, "The given class type is a reference to all classes" if val.class_name.nil? find_hostclass(val.class_name) else raise ArgumentError, "Invalid argument of type '#{val.class}' to 'defined'" end end end