Skip to content

Commit 44c4ea0

Browse files
committed
(PUP-8894) Make ILLEGAL_DEFINITION_LOCATION a deprecation.
1 parent ce6d50d commit 44c4ea0

File tree

3 files changed

+179
-98
lines changed

3 files changed

+179
-98
lines changed

lib/puppet/pops/validation/checker4_0.rb

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ def initialize(diagnostics_producer)
3535

3636
@check_visitor = self.class.check_visitor
3737
@acceptor = diagnostics_producer
38-
@file_to_namespace = {}
3938

4039
# Use null migration checker unless given in context
4140
@migration_checker = (Puppet.lookup(:migration_checker) { Migration::MigrationChecker.new() })
@@ -533,75 +532,103 @@ def internal_check_future_reserved_word(o, name)
533532
end
534533
end
535534

535+
NO_NAMESPACE = :no_namespace
536+
NO_PATH = :no_path
537+
BAD_MODULE_FILE = :bad_module_file
536538
def internal_check_file_namespace(o, name, file)
537-
return if file.nil?
539+
return if file.nil? || file == '' #e.g. puppet apply -e '...'
538540

539-
lc_file = file.downcase
541+
file_namespace = namespace_for_file(file)
542+
return if file_namespace == NO_NAMESPACE
540543

541-
file_namespace = @file_to_namespace[lc_file]
542-
if file_namespace.nil?
543-
return if @file_to_namespace.key?(lc_file)
544-
file_namespace = @file_to_namespace[lc_file] = namespace_for_file(lc_file)
545-
return if file_namespace.nil?
546-
end
547-
548-
if !name.downcase.start_with?(file_namespace)
544+
# Downcasing here because check is case-insensitive
545+
if file_namespace == BAD_MODULE_FILE || !name.downcase.start_with?(file_namespace)
549546
acceptor.accept(Issues::ILLEGAL_DEFINITION_LOCATION, o, {:name => name, :file => file})
550547
end
551548
end
552549

553-
NEVER_MATCH = '\b'.freeze
550+
# @api private
551+
class Puppet::Util::FileNamespaceAdapter < Puppet::Pops::Adaptable::Adapter
552+
attr_accessor :file_to_namespace
553+
end
554554

555555
def namespace_for_file(file)
556-
path = Pathname.new(file)
556+
env = Puppet.lookup(:current_environment)
557+
return NO_NAMESPACE if env.nil?
557558

558-
return nil if path.extname != ".pp"
559+
Puppet::Util::FileNamespaceAdapter.adapt(env) do |adapter|
560+
adapter.file_to_namespace ||= {}
559561

560-
return nil if initial_manifest?(path)
562+
file_namespace = adapter.file_to_namespace[file]
563+
return file_namespace unless file_namespace.nil? # No cache entry, so we do the calculation
561564

562-
path = path.each_filename.to_a
565+
path = Pathname.new(file)
563566

564-
# Example definition dir: manifests in this path:
565-
# <modules dir>/<module name>/manifests/<module subdir>/<classfile>.pp
566-
definition_dir_index = find_module_definition_dir(path)
567+
return adapter.file_to_namespace[file] = NO_NAMESPACE if path.extname != ".pp"
567568

568-
# How can we get this result?
569-
# If it is not an initial manifest, it must come from a module,
570-
# and from the manifests dir there. This may never get used...
571-
return NEVER_MATCH if definition_dir_index.nil? || definition_dir_index == 0
569+
path = path.expand_path
572570

573-
before_definition_dir = definition_dir_index - 1
574-
after_definition_dir = definition_dir_index + 1
575-
names = path[after_definition_dir .. -2] # Directories inside module
576-
names.unshift(path[before_definition_dir]) # Name of the module itself
577-
# Do not include name of module init file at top level of module
578-
filename = path[-1]
579-
if !(path.length == (after_definition_dir+1) && filename == 'init.pp')
580-
names.push(filename[0 .. -4]) # Remove .pp from filename
571+
return adapter.file_to_namespace[file] = NO_NAMESPACE if initial_manifest?(path, env.manifest)
572+
573+
#All auto-loaded files from modules come from a module search path dir
574+
relative_path = get_module_relative_path(path, env.full_modulepath)
575+
576+
return adapter.file_to_namespace[file] = NO_NAMESPACE if relative_path == NO_PATH
577+
578+
#If a file comes from a module, but isn't in the right place, always error
579+
names = dir_to_names(relative_path)
580+
581+
return adapter.file_to_namespace[file] = (names == BAD_MODULE_FILE ? BAD_MODULE_FILE : names.join("::").freeze)
581582
end
583+
end
584+
585+
def initial_manifest?(path, manifest_setting)
586+
return false if manifest_setting.nil? || manifest_setting == :no_manifest
582587

583-
names.join("::").freeze
588+
string_path = path.to_s
589+
590+
string_path == manifest_setting || string_path.start_with?(manifest_setting)
584591
end
585592

586-
def initial_manifest?(path)
587-
manifest_setting = Puppet[:manifest]
593+
def get_module_relative_path(file_path, modulepath_directories)
594+
clean_file = file_path.cleanpath
595+
parent_path = modulepath_directories.find { |path_dir| is_parent_dir_of(path_dir, clean_file) }
596+
return NO_PATH if parent_path.nil?
588597

589-
# Does this ever happen outside of tests?
590-
if manifest_setting.nil?
591-
return path.basename.to_s == 'site.pp'
592-
end
598+
file_path.relative_path_from(Pathname.new(parent_path))
599+
end
600+
601+
def is_parent_dir_of(parent_dir, child_dir)
602+
parent_dir_path = Pathname.new(parent_dir)
603+
clean_parent = parent_dir_path.cleanpath
593604

594-
full_path = path.expand_path.to_s
595-
full_path == manifest_setting || full_path.start_with?(manifest_setting)
605+
return child_dir.to_s.start_with?(clean_parent.to_s)
596606
end
597607

598-
# Returns module root directory index in path for files under 'manifests',
599-
# 'functions', 'types' and 'plans'
600-
def find_module_definition_dir(path)
601-
reverse_index = path.reverse_each.find_index do |dir|
602-
dir == 'manifests' || dir == 'functions' || dir == 'types' || dir == 'plans'
608+
def dir_to_names(relative_path)
609+
# Downcasing here because check is case-insensitive
610+
path_components = relative_path.to_s.downcase.split(File::SEPARATOR)
611+
612+
# Example definition dir: manifests in this path:
613+
# <module name>/manifests/<module subdir>/<classfile>.pp
614+
dir = path_components[1]
615+
616+
# How can we get this result?
617+
# If it is not an initial manifest, it must come from a module,
618+
# and from the manifests dir there. This may never get used...
619+
return BAD_MODULE_FILE unless dir == 'manifests' || dir == 'functions' || dir == 'types' || dir == 'plans'
620+
621+
names = path_components[2 .. -2] # Directories inside module
622+
names.unshift(path_components[0]) # Name of the module itself
623+
624+
# Do not include name of module init file at top level of module
625+
# e.g. <module name>/manifests/init.pp
626+
filename = path_components[-1]
627+
if !(path_components.length == 3 && filename == 'init.pp')
628+
names.push(filename[0 .. -4]) # Remove .pp from filename
603629
end
604-
return reverse_index.nil? ? nil : (path.length - 1) - reverse_index
630+
631+
names
605632
end
606633

607634
RESERVED_PARAMETERS = {

lib/puppet/pops/validation/validator_factory_4_0.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def severity_producer
3636
p[Issues::NAME_WITH_HYPHEN] = :error
3737
p[Issues::EMPTY_RESOURCE_SPECIALIZATION] = :ignore
3838
p[Issues::CLASS_NOT_VIRTUALIZABLE] = Puppet[:strict] == :off ? :warning : Puppet[:strict]
39-
p[Issues::ILLEGAL_DEFINITION_LOCATION] = Puppet[:strict] == :off ? :ignore : Puppet[:strict]
39+
p[Issues::ILLEGAL_DEFINITION_LOCATION] = :deprecation
4040
p
4141
end
4242
end

0 commit comments

Comments
 (0)