puppet 3.2.3 → 3.2.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/Rakefile +0 -2
- data/ext/build_defaults.yaml +1 -1
- data/ext/redhat/puppet.spec.erb +6 -2
- data/lib/puppet.rb +2 -0
- data/lib/puppet/file_system.rb +3 -0
- data/lib/puppet/file_system/path_pattern.rb +97 -0
- data/lib/puppet/module.rb +26 -4
- data/lib/puppet/module_tool/applications/unpacker.rb +3 -2
- data/lib/puppet/module_tool/tar/gnu.rb +5 -2
- data/lib/puppet/module_tool/tar/mini.rb +1 -1
- data/lib/puppet/module_tool/tar/solaris.rb +5 -2
- data/lib/puppet/parser/files.rb +21 -16
- data/lib/puppet/parser/parser_support.rb +10 -1
- data/lib/puppet/parser/type_loader.rb +54 -31
- data/lib/puppet/version.rb +1 -1
- data/spec/unit/file_system/path_pattern_spec.rb +138 -0
- data/spec/unit/module_spec.rb +13 -6
- data/spec/unit/module_tool/tar/gnu_spec.rb +5 -2
- data/spec/unit/module_tool/tar/mini_spec.rb +4 -4
- data/spec/unit/module_tool/tar/solaris_spec.rb +5 -2
- data/spec/unit/parser/files_spec.rb +15 -71
- data/spec/unit/parser/parser_spec.rb +10 -8
- data/spec/unit/parser/type_loader_spec.rb +17 -28
- data/spec/unit/resource/type_collection_spec.rb +40 -68
- metadata +6 -2
data/Rakefile
CHANGED
@@ -10,8 +10,6 @@ $LOAD_PATH << File.join(RAKE_ROOT, 'tasks')
|
|
10
10
|
begin
|
11
11
|
require 'rubygems'
|
12
12
|
require 'rubygems/package_task'
|
13
|
-
require 'rspec'
|
14
|
-
require 'rspec/core/rake_task'
|
15
13
|
rescue LoadError
|
16
14
|
# Users of older versions of Rake (0.8.7 for example) will not necessarily
|
17
15
|
# have rubygems installed, or the newer rubygems package_task for that
|
data/ext/build_defaults.yaml
CHANGED
@@ -9,7 +9,7 @@ gpg_name: 'info@puppetlabs.com'
|
|
9
9
|
gpg_key: '4BD6EC30'
|
10
10
|
sign_tar: FALSE
|
11
11
|
# a space separated list of mock configs
|
12
|
-
final_mocks: 'pl-el-5-i386 pl-el-6-i386 pl-fedora-17-i386 pl-fedora-18-i386'
|
12
|
+
final_mocks: 'pl-el-5-i386 pl-el-6-i386 pl-fedora-17-i386 pl-fedora-18-i386 pl-fedora-19-i386'
|
13
13
|
yum_host: 'burji.puppetlabs.com'
|
14
14
|
yum_repo_path: '/opt/repository/yum/'
|
15
15
|
build_gem: TRUE
|
data/ext/redhat/puppet.spec.erb
CHANGED
@@ -37,9 +37,8 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
|
37
37
|
BuildRequires: facter < 1:2.0
|
38
38
|
# Puppet 3.x drops ruby 1.8.5 support and adds ruby 1.9 support
|
39
39
|
BuildRequires: ruby >= 1.8.7
|
40
|
-
|
41
40
|
BuildArch: noarch
|
42
|
-
Requires: ruby
|
41
|
+
Requires: ruby >= 1.8
|
43
42
|
Requires: ruby-shadow
|
44
43
|
|
45
44
|
# Pull in ruby selinux bindings where available
|
@@ -67,6 +66,11 @@ Requires: shadow-utils
|
|
67
66
|
%if 0%{?_with_systemd}
|
68
67
|
# Required for %%post, %%preun, %%postun
|
69
68
|
Requires: systemd
|
69
|
+
%if 0%{?fedora} >= 18
|
70
|
+
BuildRequires: systemd
|
71
|
+
%else
|
72
|
+
BuildRequires: systemd-units
|
73
|
+
%endif
|
70
74
|
%else
|
71
75
|
# Required for %%post and %%preun
|
72
76
|
Requires: chkconfig
|
data/lib/puppet.rb
CHANGED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Puppet::FileSystem
|
4
|
+
class PathPattern
|
5
|
+
class InvalidPattern < Puppet::Error; end
|
6
|
+
|
7
|
+
TRAVERSAL = /^\.\.$/
|
8
|
+
ABSOLUTE_UNIX = /^\//
|
9
|
+
ABSOLUTE_WINDOWS = /^[a-z]:/i
|
10
|
+
#ABSOLUT_VODKA #notappearinginthisclass
|
11
|
+
CURRENT_DRIVE_RELATIVE_WINDOWS = /^\\/
|
12
|
+
|
13
|
+
def self.relative(pattern)
|
14
|
+
RelativePathPattern.new(pattern)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.absolute(pattern)
|
18
|
+
AbsolutePathPattern.new(pattern)
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
protected :new
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param prefix [AbsolutePathPattern] An absolute path pattern instance
|
26
|
+
# @return [AbsolutePathPattern] A new AbsolutePathPattern prepended with
|
27
|
+
# the passed prefix's pattern.
|
28
|
+
def prefix_with(prefix)
|
29
|
+
new_pathname = prefix.pathname + pathname
|
30
|
+
self.class.absolute(new_pathname.to_s)
|
31
|
+
end
|
32
|
+
|
33
|
+
def glob
|
34
|
+
Dir.glob(pathname.to_s)
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
pathname.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
attr_reader :pathname
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def validate
|
48
|
+
@pathname.each_filename do |e|
|
49
|
+
if e =~ TRAVERSAL
|
50
|
+
raise(InvalidPattern, "PathPatterns cannot be created with directory traversals.")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
case @pathname.to_s
|
54
|
+
when CURRENT_DRIVE_RELATIVE_WINDOWS
|
55
|
+
raise(InvalidPattern, "A PathPattern cannot be a Windows current drive relative path.")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(pattern)
|
60
|
+
begin
|
61
|
+
@pathname = Pathname.new(pattern.strip)
|
62
|
+
rescue ArgumentError => error
|
63
|
+
raise InvalidPattern.new("PathPatterns cannot be created with a zero byte.", error)
|
64
|
+
end
|
65
|
+
validate
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class RelativePathPattern < PathPattern
|
70
|
+
def absolute?
|
71
|
+
false
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate
|
75
|
+
super
|
76
|
+
case @pathname.to_s
|
77
|
+
when ABSOLUTE_WINDOWS
|
78
|
+
raise(InvalidPattern, "A relative PathPattern cannot be prefixed with a drive.")
|
79
|
+
when ABSOLUTE_UNIX
|
80
|
+
raise(InvalidPattern, "A relative PathPattern cannot be an absolute path.")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class AbsolutePathPattern < PathPattern
|
86
|
+
def absolute?
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
def validate
|
91
|
+
super
|
92
|
+
if @pathname.to_s !~ ABSOLUTE_UNIX and @pathname.to_s !~ ABSOLUTE_WINDOWS
|
93
|
+
raise(InvalidPattern, "An absolute PathPattern cannot be a relative path.")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/puppet/module.rb
CHANGED
@@ -11,6 +11,7 @@ class Puppet::Module
|
|
11
11
|
class IncompatiblePlatform < Error; end
|
12
12
|
class MissingMetadata < Error; end
|
13
13
|
class InvalidName < Error; end
|
14
|
+
class InvalidFilePattern < Error; end
|
14
15
|
|
15
16
|
include Puppet::Util::Logging
|
16
17
|
|
@@ -45,6 +46,8 @@ class Puppet::Module
|
|
45
46
|
load_metadata if has_metadata?
|
46
47
|
|
47
48
|
validate_puppet_version
|
49
|
+
|
50
|
+
@absolute_path_to_manifests = Puppet::FileSystem::PathPattern.absolute(manifests)
|
48
51
|
end
|
49
52
|
|
50
53
|
def has_metadata?
|
@@ -132,10 +135,16 @@ class Puppet::Module
|
|
132
135
|
# Return the list of manifests matching the given glob pattern,
|
133
136
|
# defaulting to 'init.{pp,rb}' for empty modules.
|
134
137
|
def match_manifests(rest)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
138
|
+
if rest
|
139
|
+
wanted_manifests = wanted_manifests_from(rest)
|
140
|
+
searched_manifests = wanted_manifests.glob.reject { |f| FileTest.directory?(f) }
|
141
|
+
else
|
142
|
+
searched_manifests = []
|
143
|
+
end
|
144
|
+
|
145
|
+
# (#4220) Always ensure init.pp in case class is defined there.
|
146
|
+
init_manifests = [manifest("init.pp"), manifest("init.rb")].compact
|
147
|
+
init_manifests + searched_manifests
|
139
148
|
end
|
140
149
|
|
141
150
|
def metadata_file
|
@@ -275,6 +284,19 @@ class Puppet::Module
|
|
275
284
|
|
276
285
|
private
|
277
286
|
|
287
|
+
def wanted_manifests_from(pattern)
|
288
|
+
begin
|
289
|
+
extended = File.extname(pattern).empty? ? "#{pattern}.{pp,rb}" : pattern
|
290
|
+
relative_pattern = Puppet::FileSystem::PathPattern.relative(extended)
|
291
|
+
rescue Puppet::FileSystem::PathPattern::InvalidPattern => error
|
292
|
+
raise Puppet::Module::InvalidFilePattern.new(
|
293
|
+
"The pattern \"#{pattern}\" to find manifests in the module \"#{name}\" " +
|
294
|
+
"is invalid and potentially unsafe.", error)
|
295
|
+
end
|
296
|
+
|
297
|
+
relative_pattern.prefix_with(@absolute_path_to_manifests)
|
298
|
+
end
|
299
|
+
|
278
300
|
def subpath(type)
|
279
301
|
File.join(path, type)
|
280
302
|
end
|
@@ -10,7 +10,8 @@ module Puppet::ModuleTool
|
|
10
10
|
parsed = parse_filename(filename)
|
11
11
|
@module_name = parsed[:module_name]
|
12
12
|
super(options)
|
13
|
-
@
|
13
|
+
@module_path = Pathname(options[:target_dir])
|
14
|
+
@module_dir = @module_path + parsed[:dir_name]
|
14
15
|
end
|
15
16
|
|
16
17
|
def run
|
@@ -37,7 +38,7 @@ module Puppet::ModuleTool
|
|
37
38
|
build_dir.mkpath
|
38
39
|
begin
|
39
40
|
begin
|
40
|
-
Puppet::ModuleTool::Tar.instance(@module_name).unpack(@filename.to_s, build_dir.to_s)
|
41
|
+
Puppet::ModuleTool::Tar.instance(@module_name).unpack(@filename.to_s, build_dir.to_s, [@module_path.stat.uid, @module_path.stat.gid].join(':'))
|
41
42
|
rescue Puppet::ExecutionFailure => e
|
42
43
|
raise RuntimeError, "Could not extract contents of module archive: #{e.message}"
|
43
44
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
class Puppet::ModuleTool::Tar::Gnu
|
2
|
-
def unpack(sourcefile, destdir)
|
3
|
-
Puppet::Util::Execution.execute("tar xzf #{sourcefile} -C #{destdir}")
|
2
|
+
def unpack(sourcefile, destdir, owner)
|
3
|
+
Puppet::Util::Execution.execute("tar xzf #{sourcefile} --no-same-permissions --no-same-owner -C #{destdir}")
|
4
|
+
Puppet::Util::Execution.execute("find #{destdir} -type d -exec chmod 755 {} +")
|
5
|
+
Puppet::Util::Execution.execute("find #{destdir} -type f -exec chmod 644 {} +")
|
6
|
+
Puppet::Util::Execution.execute("chown -R #{owner} #{destdir}")
|
4
7
|
end
|
5
8
|
|
6
9
|
def pack(sourcedir, destfile)
|
@@ -3,7 +3,7 @@ class Puppet::ModuleTool::Tar::Mini
|
|
3
3
|
@module_name = module_name
|
4
4
|
end
|
5
5
|
|
6
|
-
def unpack(sourcefile, destdir)
|
6
|
+
def unpack(sourcefile, destdir, _)
|
7
7
|
Zlib::GzipReader.open(sourcefile) do |reader|
|
8
8
|
Archive::Tar::Minitar.unpack(reader, destdir) do |action, name, stats|
|
9
9
|
case action
|
@@ -1,5 +1,8 @@
|
|
1
1
|
class Puppet::ModuleTool::Tar::Solaris < Puppet::ModuleTool::Tar::Gnu
|
2
|
-
def unpack(sourcefile, destdir)
|
3
|
-
Puppet::Util::Execution.execute("gtar xzf #{sourcefile} -C #{destdir}")
|
2
|
+
def unpack(sourcefile, destdir, owner)
|
3
|
+
Puppet::Util::Execution.execute("gtar xzf #{sourcefile} --no-same-permissions --no-same-owner -C #{destdir}")
|
4
|
+
Puppet::Util::Execution.execute("find #{destdir} -type d -exec chmod 755 {} +")
|
5
|
+
Puppet::Util::Execution.execute("find #{destdir} -type f -exec chmod 644 {} +")
|
6
|
+
Puppet::Util::Execution.execute("chown -R #{owner} #{destdir}")
|
4
7
|
end
|
5
8
|
end
|
data/lib/puppet/parser/files.rb
CHANGED
@@ -6,26 +6,28 @@ require 'puppet/module'
|
|
6
6
|
# doesn't really belong in the Puppet::Module class,
|
7
7
|
# but it doesn't really belong anywhere else, either.
|
8
8
|
module Puppet; module Parser; module Files
|
9
|
-
|
9
|
+
|
10
10
|
module_function
|
11
11
|
|
12
|
-
# Return a list of manifests
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
# Return a list of manifests as absolute filenames matching the given
|
13
|
+
# pattern.
|
14
|
+
#
|
15
|
+
# @param pattern [String] A reference for a file in a module. It is the format "<modulename>/<file glob>"
|
16
|
+
# @param environment [Puppet::Node::Environment] the environment of modules
|
17
|
+
#
|
18
|
+
# @return [Array(String, Array<String>)] the module name and the list of files found
|
19
|
+
# @api private
|
20
|
+
def find_manifests_in_modules(pattern, environment)
|
21
|
+
module_name, file_pattern = split_file_path(pattern)
|
20
22
|
begin
|
21
|
-
if mod = Puppet::Module.find(module_name,
|
22
|
-
return [mod.name, mod.match_manifests(
|
23
|
+
if mod = Puppet::Module.find(module_name, environment)
|
24
|
+
return [mod.name, mod.match_manifests(file_pattern)]
|
23
25
|
end
|
24
26
|
rescue Puppet::Module::InvalidName
|
25
|
-
#
|
27
|
+
# one of the modules being loaded might have an invalid name and so
|
28
|
+
# looking for one might blow up since we load them lazily.
|
26
29
|
end
|
27
|
-
|
28
|
-
[nil, Dir.glob(abspat + (File.extname(abspat).empty? ? '{.pp,.rb}' : '' )).uniq.reject { |f| FileTest.directory?(f) }]
|
30
|
+
[nil, []]
|
29
31
|
end
|
30
32
|
|
31
33
|
# Find the concrete file denoted by +file+. If +file+ is absolute,
|
@@ -81,9 +83,12 @@ module Puppet; module Parser; module Files
|
|
81
83
|
|
82
84
|
# Split the path into the module and the rest of the path, or return
|
83
85
|
# nil if the path is empty or absolute (starts with a /).
|
84
|
-
# This method can return nil & anyone calling it needs to handle that.
|
85
86
|
def split_file_path(path)
|
86
|
-
|
87
|
+
if path == "" or Puppet::Util.absolute_path?(path)
|
88
|
+
nil
|
89
|
+
else
|
90
|
+
path.split(File::SEPARATOR, 2)
|
91
|
+
end
|
87
92
|
end
|
88
93
|
|
89
94
|
end; end; end
|
@@ -98,7 +98,16 @@ class Puppet::Parser::Parser
|
|
98
98
|
def_delegators :known_resource_types, :watch_file, :version
|
99
99
|
|
100
100
|
def import(file)
|
101
|
-
|
101
|
+
if @lexer.file
|
102
|
+
# use a path relative to the file doing the importing
|
103
|
+
dir = File.dirname(@lexer.file)
|
104
|
+
else
|
105
|
+
# otherwise assume that everything needs to be from where the user is
|
106
|
+
# executing this command. Normally, this would be in a "puppet apply -e"
|
107
|
+
dir = Dir.pwd
|
108
|
+
end
|
109
|
+
|
110
|
+
known_resource_types.loader.import(file, dir)
|
102
111
|
end
|
103
112
|
|
104
113
|
def initialize(env)
|
@@ -62,50 +62,48 @@ class Puppet::Parser::TypeLoader
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
# Import
|
66
|
-
|
65
|
+
# Import manifest files that match a given file glob pattern.
|
66
|
+
#
|
67
|
+
# @param pattern [String] the file glob to apply when determining which files
|
68
|
+
# to load
|
69
|
+
# @param dir [String] base directory to use when the file is not
|
70
|
+
# found in a module
|
71
|
+
# @api private
|
72
|
+
def import(pattern, dir)
|
67
73
|
return if Puppet[:ignoreimport]
|
68
74
|
|
69
|
-
|
70
|
-
if
|
71
|
-
|
72
|
-
|
73
|
-
dir = "."
|
74
|
-
end
|
75
|
-
if dir == ""
|
76
|
-
dir = "."
|
77
|
-
end
|
75
|
+
modname, files = Puppet::Parser::Files.find_manifests_in_modules(pattern, environment)
|
76
|
+
if files.empty?
|
77
|
+
abspat = File.expand_path(pattern, dir)
|
78
|
+
file_pattern = abspat + (File.extname(abspat).empty? ? '{.pp,.rb}' : '' )
|
78
79
|
|
79
|
-
|
80
|
-
|
81
|
-
if files.size == 0
|
82
|
-
raise Puppet::ImportError.new("No file(s) found for import of '#{pat}'")
|
83
|
-
end
|
80
|
+
files = Dir.glob(file_pattern).uniq.reject { |f| FileTest.directory?(f) }
|
81
|
+
modname = nil
|
84
82
|
|
85
|
-
|
86
|
-
|
87
|
-
unless Puppet::Util.absolute_path?(file)
|
88
|
-
file = File.join(dir, file)
|
83
|
+
if files.empty?
|
84
|
+
raise_no_files_found(pattern)
|
89
85
|
end
|
90
|
-
@loading_helper.do_once(file) do
|
91
|
-
loaded_asts << parse_file(file)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
loaded_asts.inject([]) do |loaded_types, ast|
|
95
|
-
loaded_types + known_resource_types.import_ast(ast, modname)
|
96
86
|
end
|
87
|
+
|
88
|
+
load_files(modname, files)
|
97
89
|
end
|
98
90
|
|
91
|
+
# Load all of the manifest files in all known modules.
|
92
|
+
# @api private
|
99
93
|
def import_all
|
100
94
|
# And then load all files from each module, but (relying on system
|
101
95
|
# behavior) only load files from the first module of a given name. E.g.,
|
102
96
|
# given first/foo and second/foo, only files from first/foo will be loaded.
|
103
97
|
environment.modules.each do |mod|
|
104
|
-
|
105
|
-
|
106
|
-
|
98
|
+
manifest_files = []
|
99
|
+
if File.exists?(mod.manifests)
|
100
|
+
Find.find(mod.manifests) do |path|
|
101
|
+
if path.end_with?(".pp") || path.end_with?(".rb")
|
102
|
+
manifest_files << path
|
103
|
+
end
|
107
104
|
end
|
108
105
|
end
|
106
|
+
load_files(mod.name, manifest_files)
|
109
107
|
end
|
110
108
|
end
|
111
109
|
|
@@ -121,7 +119,7 @@ class Puppet::Parser::TypeLoader
|
|
121
119
|
return nil if fqname == "" # special-case main.
|
122
120
|
name2files(fqname).each do |filename|
|
123
121
|
begin
|
124
|
-
imported_types =
|
122
|
+
imported_types = import_from_modules(filename)
|
125
123
|
if result = imported_types.find { |t| t.type == type and t.name == fqname }
|
126
124
|
Puppet.debug "Automatically imported #{fqname} from #{filename} into #{environment}"
|
127
125
|
return result
|
@@ -138,7 +136,6 @@ class Puppet::Parser::TypeLoader
|
|
138
136
|
|
139
137
|
def parse_file(file)
|
140
138
|
Puppet.debug("importing '#{file}' in environment #{environment}")
|
141
|
-
# parser = Puppet::Parser::Parser.new(environment)
|
142
139
|
parser = Puppet::Parser::ParserFactory.parser(environment)
|
143
140
|
parser.file = file
|
144
141
|
return parser.parse
|
@@ -146,6 +143,32 @@ class Puppet::Parser::TypeLoader
|
|
146
143
|
|
147
144
|
private
|
148
145
|
|
146
|
+
def import_from_modules(pattern)
|
147
|
+
modname, files = Puppet::Parser::Files.find_manifests_in_modules(pattern, environment)
|
148
|
+
if files.empty?
|
149
|
+
raise_no_files_found(pattern)
|
150
|
+
end
|
151
|
+
|
152
|
+
load_files(modname, files)
|
153
|
+
end
|
154
|
+
|
155
|
+
def raise_no_files_found(pattern)
|
156
|
+
raise Puppet::ImportError, "No file(s) found for import of '#{pattern}'"
|
157
|
+
end
|
158
|
+
|
159
|
+
def load_files(modname, files)
|
160
|
+
loaded_asts = []
|
161
|
+
files.each do |file|
|
162
|
+
@loading_helper.do_once(file) do
|
163
|
+
loaded_asts << parse_file(file)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
loaded_asts.collect do |ast|
|
168
|
+
known_resource_types.import_ast(ast, modname)
|
169
|
+
end.flatten
|
170
|
+
end
|
171
|
+
|
149
172
|
# Return a list of all file basenames that should be tried in order
|
150
173
|
# to load the object with the given fully qualified name.
|
151
174
|
def name2files(fqname)
|
data/lib/puppet/version.rb
CHANGED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'puppet_spec/files'
|
3
|
+
require 'puppet/file_system'
|
4
|
+
|
5
|
+
describe Puppet::FileSystem::PathPattern do
|
6
|
+
include PuppetSpec::Files
|
7
|
+
InvalidPattern = Puppet::FileSystem::PathPattern::InvalidPattern
|
8
|
+
|
9
|
+
describe 'relative' do
|
10
|
+
it "can not be created with a traversal up the directory tree" do
|
11
|
+
expect do
|
12
|
+
Puppet::FileSystem::PathPattern.relative("my/../other")
|
13
|
+
end.to raise_error(InvalidPattern, "PathPatterns cannot be created with directory traversals.")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "can be created with a '..' prefixing a filename" do
|
17
|
+
expect(Puppet::FileSystem::PathPattern.relative("my/..other").to_s).to eq("my/..other")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "can be created with a '..' suffixing a filename" do
|
21
|
+
expect(Puppet::FileSystem::PathPattern.relative("my/other..").to_s).to eq("my/other..")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can be created with a '..' embedded in a filename" do
|
25
|
+
expect(Puppet::FileSystem::PathPattern.relative("my/ot..her").to_s).to eq("my/ot..her")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can not be created with a \\0 byte embedded" do
|
29
|
+
expect do
|
30
|
+
Puppet::FileSystem::PathPattern.relative("my/\0/other")
|
31
|
+
end.to raise_error(InvalidPattern, "PathPatterns cannot be created with a zero byte.")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can not be created with a windows drive" do
|
35
|
+
expect do
|
36
|
+
Puppet::FileSystem::PathPattern.relative("c:\\relative\\path")
|
37
|
+
end.to raise_error(InvalidPattern, "A relative PathPattern cannot be prefixed with a drive.")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "can not be created with a windows drive (with space)" do
|
41
|
+
expect do
|
42
|
+
Puppet::FileSystem::PathPattern.relative(" c:\\relative\\path")
|
43
|
+
end.to raise_error(InvalidPattern, "A relative PathPattern cannot be prefixed with a drive.")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "can not create an absolute relative path" do
|
47
|
+
expect do
|
48
|
+
Puppet::FileSystem::PathPattern.relative("/no/absolutes")
|
49
|
+
end.to raise_error(InvalidPattern, "A relative PathPattern cannot be an absolute path.")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "can not create an absolute relative path (with space)" do
|
53
|
+
expect do
|
54
|
+
Puppet::FileSystem::PathPattern.relative("\t/no/absolutes")
|
55
|
+
end.to raise_error(InvalidPattern, "A relative PathPattern cannot be an absolute path.")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "can not create a relative path that is a windows path relative to the current drive" do
|
59
|
+
expect do
|
60
|
+
Puppet::FileSystem::PathPattern.relative("\\no\relatives")
|
61
|
+
end.to raise_error(InvalidPattern, "A PathPattern cannot be a Windows current drive relative path.")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "creates a relative PathPattern from a valid relative path" do
|
65
|
+
expect(Puppet::FileSystem::PathPattern.relative("a/relative/path").to_s).to eq("a/relative/path")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "is not absolute" do
|
69
|
+
expect(Puppet::FileSystem::PathPattern.relative("a/relative/path")).to_not be_absolute
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'absolute' do
|
74
|
+
it "can not create a relative absolute path" do
|
75
|
+
expect do
|
76
|
+
Puppet::FileSystem::PathPattern.absolute("no/relatives")
|
77
|
+
end.to raise_error(InvalidPattern, "An absolute PathPattern cannot be a relative path.")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "can not create an absolute path that is a windows path relative to the current drive" do
|
81
|
+
expect do
|
82
|
+
Puppet::FileSystem::PathPattern.absolute("\\no\\relatives")
|
83
|
+
end.to raise_error(InvalidPattern, "A PathPattern cannot be a Windows current drive relative path.")
|
84
|
+
end
|
85
|
+
|
86
|
+
it "creates an absolute PathPattern from a valid absolute path" do
|
87
|
+
expect(Puppet::FileSystem::PathPattern.absolute("/an/absolute/path").to_s).to eq("/an/absolute/path")
|
88
|
+
end
|
89
|
+
|
90
|
+
it "creates an absolute PathPattern from a valid Windows absolute path" do
|
91
|
+
expect(Puppet::FileSystem::PathPattern.absolute("c:/absolute/windows/path").to_s).to eq("c:/absolute/windows/path")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "can be created with a '..' embedded in a filename on windows", :if => Puppet.features.microsoft_windows? do
|
95
|
+
expect(Puppet::FileSystem::PathPattern.absolute(%q{c:\..my\ot..her\one..}).to_s).to eq(%q{c:\..my\ot..her\one..})
|
96
|
+
end
|
97
|
+
|
98
|
+
it "is absolute" do
|
99
|
+
expect(Puppet::FileSystem::PathPattern.absolute("c:/absolute/windows/path")).to be_absolute
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it "prefixes the relative path pattern with another path" do
|
104
|
+
pattern = Puppet::FileSystem::PathPattern.relative("docs/*_thoughts.txt")
|
105
|
+
prefix = Puppet::FileSystem::PathPattern.absolute("/prefix")
|
106
|
+
|
107
|
+
absolute_pattern = pattern.prefix_with(prefix)
|
108
|
+
|
109
|
+
expect(absolute_pattern).to be_absolute
|
110
|
+
expect(absolute_pattern.to_s).to eq(File.join("/prefix", "docs/*_thoughts.txt"))
|
111
|
+
end
|
112
|
+
|
113
|
+
it "refuses to prefix with a relative pattern" do
|
114
|
+
pattern = Puppet::FileSystem::PathPattern.relative("docs/*_thoughts.txt")
|
115
|
+
prefix = Puppet::FileSystem::PathPattern.relative("prefix")
|
116
|
+
|
117
|
+
expect do
|
118
|
+
pattern.prefix_with(prefix)
|
119
|
+
end.to raise_error(InvalidPattern, "An absolute PathPattern cannot be a relative path.")
|
120
|
+
end
|
121
|
+
|
122
|
+
it "applies the pattern to the filesystem as a glob" do
|
123
|
+
dir = tmpdir('globtest')
|
124
|
+
create_file_in(dir, "found_one")
|
125
|
+
create_file_in(dir, "found_two")
|
126
|
+
create_file_in(dir, "third_not_found")
|
127
|
+
|
128
|
+
pattern = Puppet::FileSystem::PathPattern.relative("found_*").prefix_with(
|
129
|
+
Puppet::FileSystem::PathPattern.absolute(dir))
|
130
|
+
|
131
|
+
expect(pattern.glob).to match_array([File.join(dir, "found_one"),
|
132
|
+
File.join(dir, "found_two")])
|
133
|
+
end
|
134
|
+
|
135
|
+
def create_file_in(dir, name)
|
136
|
+
File.open(File.join(dir, name), "w") { |f| f.puts "data" }
|
137
|
+
end
|
138
|
+
end
|
data/spec/unit/module_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Puppet::Module do
|
|
8
8
|
include PuppetSpec::Files
|
9
9
|
|
10
10
|
let(:env) { mock("environment") }
|
11
|
-
let(:path) { "path" }
|
11
|
+
let(:path) { "/path" }
|
12
12
|
let(:name) { "mymod" }
|
13
13
|
let(:mod) { Puppet::Module.new(name, path, env) }
|
14
14
|
|
@@ -339,7 +339,7 @@ describe Puppet::Module do
|
|
339
339
|
end
|
340
340
|
|
341
341
|
it "should fail if its name is not alphanumeric" do
|
342
|
-
lambda { Puppet::Module.new(".something", "path", env) }.should raise_error(Puppet::Module::InvalidName)
|
342
|
+
lambda { Puppet::Module.new(".something", "/path", env) }.should raise_error(Puppet::Module::InvalidName)
|
343
343
|
end
|
344
344
|
|
345
345
|
it "should require a name at initialization" do
|
@@ -347,7 +347,7 @@ describe Puppet::Module do
|
|
347
347
|
end
|
348
348
|
|
349
349
|
it "should accept an environment at initialization" do
|
350
|
-
Puppet::Module.new("foo", "path", env).environment.should == env
|
350
|
+
Puppet::Module.new("foo", "/path", env).environment.should == env
|
351
351
|
end
|
352
352
|
|
353
353
|
describe '#modulepath' do
|
@@ -418,7 +418,8 @@ describe Puppet::Module, "when finding matching manifests" do
|
|
418
418
|
end
|
419
419
|
|
420
420
|
it "should default to the 'init' file if no glob pattern is specified" do
|
421
|
-
|
421
|
+
FileTest.expects(:exist?).with("/a/manifests/init.pp").returns(true)
|
422
|
+
FileTest.expects(:exist?).with("/a/manifests/init.rb").returns(false)
|
422
423
|
|
423
424
|
@mod.match_manifests(nil).should == %w{/a/manifests/init.pp}
|
424
425
|
end
|
@@ -440,6 +441,12 @@ describe Puppet::Module, "when finding matching manifests" do
|
|
440
441
|
|
441
442
|
@mod.match_manifests(@pq_glob_with_extension).should == []
|
442
443
|
end
|
444
|
+
|
445
|
+
it "should raise an error if the pattern tries to leave the manifest directory" do
|
446
|
+
expect do
|
447
|
+
@mod.match_manifests("something/../../*")
|
448
|
+
end.to raise_error(Puppet::Module::InvalidFilePattern, 'The pattern "something/../../*" to find manifests in the module "mymod" is invalid and potentially unsafe.')
|
449
|
+
end
|
443
450
|
end
|
444
451
|
|
445
452
|
describe Puppet::Module do
|
@@ -509,13 +516,13 @@ describe Puppet::Module do
|
|
509
516
|
Puppet::Module.any_instance.expects(:has_metadata?).returns true
|
510
517
|
Puppet::Module.any_instance.expects(:load_metadata)
|
511
518
|
|
512
|
-
Puppet::Module.new("yay", "path", mock("env"))
|
519
|
+
Puppet::Module.new("yay", "/path", mock("env"))
|
513
520
|
end
|
514
521
|
|
515
522
|
def a_module_with_metadata(data)
|
516
523
|
text = data.to_pson
|
517
524
|
|
518
|
-
mod = Puppet::Module.new("foo", "path", mock("env"))
|
525
|
+
mod = Puppet::Module.new("foo", "/path", mock("env"))
|
519
526
|
mod.stubs(:metadata_file).returns "/my/file"
|
520
527
|
File.stubs(:read).with("/my/file").returns text
|
521
528
|
mod
|
@@ -8,8 +8,11 @@ describe Puppet::ModuleTool::Tar::Gnu do
|
|
8
8
|
let(:destfile) { '/the/dest/file.tar.gz' }
|
9
9
|
|
10
10
|
it "unpacks a tar file" do
|
11
|
-
Puppet::Util::Execution.expects(:execute).with("tar xzf #{sourcefile} -C #{destdir}")
|
12
|
-
|
11
|
+
Puppet::Util::Execution.expects(:execute).with("tar xzf #{sourcefile} --no-same-permissions --no-same-owner -C #{destdir}")
|
12
|
+
Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type d -exec chmod 755 {} +")
|
13
|
+
Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type f -exec chmod 644 {} +")
|
14
|
+
Puppet::Util::Execution.expects(:execute).with("chown -R <owner:group> #{destdir}")
|
15
|
+
subject.unpack(sourcefile, destdir, '<owner:group>')
|
13
16
|
end
|
14
17
|
|
15
18
|
it "packs a tar file" do
|
@@ -11,14 +11,14 @@ describe Puppet::ModuleTool::Tar::Mini, :if => (Puppet.features.minitar? and Pup
|
|
11
11
|
it "unpacks a tar file" do
|
12
12
|
unpacks_the_entry(:file_start, 'thefile')
|
13
13
|
|
14
|
-
minitar.unpack(sourcefile, destdir)
|
14
|
+
minitar.unpack(sourcefile, destdir, 'uid')
|
15
15
|
end
|
16
16
|
|
17
17
|
it "does not allow an absolute path" do
|
18
18
|
unpacks_the_entry(:file_start, '/thefile')
|
19
19
|
|
20
20
|
expect {
|
21
|
-
minitar.unpack(sourcefile, destdir)
|
21
|
+
minitar.unpack(sourcefile, destdir, 'uid')
|
22
22
|
}.to raise_error(Puppet::ModuleTool::Errors::InvalidPathInPackageError,
|
23
23
|
"Attempt to install file into \"/thefile\" under \"#{destdir}\"")
|
24
24
|
end
|
@@ -27,7 +27,7 @@ describe Puppet::ModuleTool::Tar::Mini, :if => (Puppet.features.minitar? and Pup
|
|
27
27
|
unpacks_the_entry(:file_start, '../../thefile')
|
28
28
|
|
29
29
|
expect {
|
30
|
-
minitar.unpack(sourcefile, destdir)
|
30
|
+
minitar.unpack(sourcefile, destdir, 'uid')
|
31
31
|
}.to raise_error(Puppet::ModuleTool::Errors::InvalidPathInPackageError,
|
32
32
|
"Attempt to install file into \"#{File.expand_path('/the/thefile')}\" under \"#{destdir}\"")
|
33
33
|
end
|
@@ -36,7 +36,7 @@ describe Puppet::ModuleTool::Tar::Mini, :if => (Puppet.features.minitar? and Pup
|
|
36
36
|
unpacks_the_entry(:dir, '../../thedir')
|
37
37
|
|
38
38
|
expect {
|
39
|
-
minitar.unpack(sourcefile, destdir)
|
39
|
+
minitar.unpack(sourcefile, destdir, 'uid')
|
40
40
|
}.to raise_error(Puppet::ModuleTool::Errors::InvalidPathInPackageError,
|
41
41
|
"Attempt to install file into \"#{File.expand_path('/the/thedir')}\" under \"#{destdir}\"")
|
42
42
|
end
|
@@ -8,8 +8,11 @@ describe Puppet::ModuleTool::Tar::Solaris do
|
|
8
8
|
let(:destfile) { '/the/dest/file.tar.gz' }
|
9
9
|
|
10
10
|
it "unpacks a tar file" do
|
11
|
-
Puppet::Util::Execution.expects(:execute).with("gtar xzf #{sourcefile} -C #{destdir}")
|
12
|
-
|
11
|
+
Puppet::Util::Execution.expects(:execute).with("gtar xzf #{sourcefile} --no-same-permissions --no-same-owner -C #{destdir}")
|
12
|
+
Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type d -exec chmod 755 {} +")
|
13
|
+
Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type f -exec chmod 644 {} +")
|
14
|
+
Puppet::Util::Execution.expects(:execute).with("chown -R <owner:group> #{destdir}")
|
15
|
+
subject.unpack(sourcefile, destdir, '<owner:group>')
|
13
16
|
end
|
14
17
|
|
15
18
|
it "packs a tar file" do
|
@@ -10,14 +10,6 @@ describe Puppet::Parser::Files do
|
|
10
10
|
@basepath = make_absolute("/somepath")
|
11
11
|
end
|
12
12
|
|
13
|
-
it "should have a method for finding a template" do
|
14
|
-
Puppet::Parser::Files.should respond_to(:find_template)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should have a method for finding manifests" do
|
18
|
-
Puppet::Parser::Files.should respond_to(:find_manifests)
|
19
|
-
end
|
20
|
-
|
21
13
|
describe "when searching for templates" do
|
22
14
|
it "should return fully-qualified templates directly" do
|
23
15
|
Puppet::Parser::Files.expects(:modulepath).never
|
@@ -127,90 +119,42 @@ describe Puppet::Parser::Files do
|
|
127
119
|
describe "when searching for manifests" do
|
128
120
|
it "should ignore invalid modules" do
|
129
121
|
mod = mock 'module'
|
130
|
-
Puppet::Node::Environment.new
|
122
|
+
env = Puppet::Node::Environment.new
|
123
|
+
env.expects(:module).with("mymod").raises(Puppet::Module::InvalidName, "name is invalid")
|
131
124
|
Puppet.expects(:value).with(:modulepath).never
|
132
125
|
Dir.stubs(:glob).returns %w{foo}
|
133
126
|
|
134
|
-
Puppet::Parser::Files.
|
127
|
+
Puppet::Parser::Files.find_manifests_in_modules("mymod/init.pp", env)
|
135
128
|
end
|
136
129
|
end
|
137
130
|
|
138
|
-
describe "when searching for manifests
|
139
|
-
before do
|
140
|
-
File.stubs(:find).returns(nil)
|
141
|
-
end
|
142
|
-
|
143
|
-
it "should not look for modules when paths are fully qualified" do
|
144
|
-
Puppet.expects(:value).with(:modulepath).never
|
145
|
-
file = @basepath + "/fully/qualified/file.pp"
|
146
|
-
Dir.stubs(:glob).with(file).returns([file])
|
147
|
-
Puppet::Parser::Files.find_manifests(file)
|
148
|
-
end
|
149
|
-
|
150
|
-
it "should return nil and an array of fully qualified files" do
|
151
|
-
file = @basepath + "/fully/qualified/file.pp"
|
152
|
-
Dir.stubs(:glob).with(file).returns([file])
|
153
|
-
Puppet::Parser::Files.find_manifests(file).should == [nil, [file]]
|
154
|
-
end
|
155
|
-
|
156
|
-
it "should match against provided fully qualified patterns" do
|
157
|
-
pattern = @basepath + "/fully/qualified/pattern/*"
|
158
|
-
Dir.expects(:glob).with(pattern+'{.pp,.rb}').returns(%w{my file list})
|
159
|
-
['my', 'file','list'].each do |w|
|
160
|
-
FileTest.expects(:'directory?').with(w).returns false
|
161
|
-
end
|
162
|
-
Puppet::Parser::Files.find_manifests(pattern)[1].should == %w{my file list}
|
163
|
-
end
|
164
|
-
|
165
|
-
it "should look for files relative to the current directory" do
|
166
|
-
# We expand_path to normalize backslashes and slashes on Windows
|
167
|
-
cwd = File.expand_path(Dir.getwd)
|
168
|
-
Dir.expects(:glob).with("#{cwd}/foobar/init.pp").returns(["#{cwd}/foobar/init.pp"])
|
169
|
-
Puppet::Parser::Files.find_manifests("foobar/init.pp")[1].should == ["#{cwd}/foobar/init.pp"]
|
170
|
-
end
|
171
|
-
|
172
|
-
it "should only return files, not directories" do
|
173
|
-
pattern = @basepath + "/fully/qualified/pattern/*"
|
174
|
-
file = @basepath + "/my/file"
|
175
|
-
dir = @basepath + "/my/directory"
|
176
|
-
Dir.expects(:glob).with(pattern+'{.pp,.rb}').returns([file, dir])
|
177
|
-
FileTest.expects(:directory?).with(file).returns(false)
|
178
|
-
FileTest.expects(:directory?).with(dir).returns(true)
|
179
|
-
Puppet::Parser::Files.find_manifests(pattern)[1].should == [file]
|
180
|
-
end
|
181
|
-
|
182
|
-
it "should return files once only" do
|
183
|
-
pattern = @basepath + "/fully/qualified/pattern/*"
|
184
|
-
Dir.expects(:glob).with(pattern+'{.pp,.rb}').returns(%w{one two one})
|
185
|
-
Puppet::Parser::Files.find_manifests(pattern)[1].should == %w{one two}
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
describe "when searching for manifests in a found module" do
|
131
|
+
describe "when searching for manifests in a module" do
|
190
132
|
def a_module_in_environment(env, name)
|
191
133
|
mod = Puppet::Module.new(name, "/one/#{name}", env)
|
192
134
|
env.stubs(:module).with(name).returns mod
|
193
135
|
mod.stubs(:match_manifests).with("init.pp").returns(["/one/#{name}/manifests/init.pp"])
|
194
136
|
end
|
195
137
|
|
196
|
-
|
197
|
-
a_module_in_environment(Puppet::Node::Environment.new, "mymod")
|
138
|
+
let(:environment) { Puppet::Node::Environment.new }
|
198
139
|
|
199
|
-
|
200
|
-
|
140
|
+
it "returns no files when no module is found" do
|
141
|
+
module_name, files = Puppet::Parser::Files.find_manifests_in_modules("not_here_module/foo", environment)
|
142
|
+
expect(files).to be_empty
|
143
|
+
expect(module_name).to be_nil
|
201
144
|
end
|
202
145
|
|
203
|
-
it "should
|
204
|
-
a_module_in_environment(
|
146
|
+
it "should return the name of the module and the manifests from the first found module" do
|
147
|
+
a_module_in_environment(environment, "mymod")
|
205
148
|
|
206
|
-
Puppet::Parser::Files.
|
149
|
+
Puppet::Parser::Files.find_manifests_in_modules("mymod/init.pp", environment).should ==
|
207
150
|
["mymod", ["/one/mymod/manifests/init.pp"]]
|
208
151
|
end
|
209
152
|
|
210
153
|
it "does not find the module when it is a different environment" do
|
211
|
-
|
154
|
+
different_env = Puppet::Node::Environment.new("different")
|
155
|
+
a_module_in_environment(environment, "mymod")
|
212
156
|
|
213
|
-
Puppet::Parser::Files.
|
157
|
+
Puppet::Parser::Files.find_manifests_in_modules("mymod/init.pp", different_env).should_not include("mymod")
|
214
158
|
end
|
215
159
|
end
|
216
160
|
end
|
@@ -35,16 +35,18 @@ describe Puppet::Parser do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
context "when importing" do
|
38
|
-
it "
|
39
|
-
parser
|
40
|
-
|
41
|
-
parser.
|
42
|
-
|
38
|
+
it "uses the directory of the currently parsed file" do
|
39
|
+
@parser.lexer.stubs(:file).returns "/tmp/current_file"
|
40
|
+
|
41
|
+
@parser.known_resource_types.loader.expects(:import).with("newfile", "/tmp")
|
42
|
+
|
43
|
+
@parser.import("newfile")
|
43
44
|
end
|
44
45
|
|
45
|
-
it "
|
46
|
-
@parser.known_resource_types.loader.expects(:import).with('one',
|
47
|
-
@parser.known_resource_types.loader.expects(:import).with('two',
|
46
|
+
it "uses the current working directory, when there is no file being parsed" do
|
47
|
+
@parser.known_resource_types.loader.expects(:import).with('one', Dir.pwd)
|
48
|
+
@parser.known_resource_types.loader.expects(:import).with('two', Dir.pwd)
|
49
|
+
|
48
50
|
@parser.parse("import 'one', 'two'")
|
49
51
|
end
|
50
52
|
end
|
@@ -37,67 +37,56 @@ describe Puppet::Parser::TypeLoader do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should attempt to import each generated name" do
|
40
|
-
@loader.expects(:
|
41
|
-
@loader.expects(:
|
40
|
+
@loader.expects(:import_from_modules).with("foo/bar").returns([])
|
41
|
+
@loader.expects(:import_from_modules).with("foo").returns([])
|
42
42
|
@loader.try_load_fqname(:hostclass, "foo::bar") { |f| false }
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
46
|
describe "when importing" do
|
47
47
|
before do
|
48
|
-
Puppet::Parser::Files.stubs(:
|
48
|
+
Puppet::Parser::Files.stubs(:find_manifests_in_modules).returns ["modname", %w{file}]
|
49
49
|
parser_class.any_instance.stubs(:parse).returns(Puppet::Parser::AST::Hostclass.new(''))
|
50
50
|
parser_class.any_instance.stubs(:file=)
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should return immediately when imports are being ignored" do
|
54
|
-
Puppet::Parser::Files.expects(:
|
54
|
+
Puppet::Parser::Files.expects(:find_manifests_in_modules).never
|
55
55
|
Puppet[:ignoreimport] = true
|
56
|
-
@loader.import("foo").should be_nil
|
56
|
+
@loader.import("foo", "/path").should be_nil
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should find all manifests matching the file or pattern" do
|
60
|
-
Puppet::Parser::Files.expects(:
|
61
|
-
@loader.import("myfile")
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should use the directory of the current file if one is set" do
|
65
|
-
Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| opts[:cwd] == make_absolute("/current") }.returns ["modname", %w{one}]
|
66
|
-
@loader.import("myfile", make_absolute("/current/file"))
|
60
|
+
Puppet::Parser::Files.expects(:find_manifests_in_modules).with("myfile", anything).returns ["modname", %w{one}]
|
61
|
+
@loader.import("myfile", "/path")
|
67
62
|
end
|
68
63
|
|
69
64
|
it "should pass the environment when looking for files" do
|
70
|
-
Puppet::Parser::Files.expects(:
|
71
|
-
@loader.import("myfile")
|
65
|
+
Puppet::Parser::Files.expects(:find_manifests_in_modules).with(anything, @loader.environment).returns ["modname", %w{one}]
|
66
|
+
@loader.import("myfile", "/path")
|
72
67
|
end
|
73
68
|
|
74
69
|
it "should fail if no files are found" do
|
75
|
-
Puppet::Parser::Files.expects(:
|
76
|
-
lambda { @loader.import("myfile") }.should raise_error(Puppet::ImportError)
|
70
|
+
Puppet::Parser::Files.expects(:find_manifests_in_modules).returns [nil, []]
|
71
|
+
lambda { @loader.import("myfile", "/path") }.should raise_error(Puppet::ImportError)
|
77
72
|
end
|
78
73
|
|
79
74
|
it "should parse each found file" do
|
80
|
-
Puppet::Parser::Files.expects(:
|
75
|
+
Puppet::Parser::Files.expects(:find_manifests_in_modules).returns ["modname", [make_absolute("/one")]]
|
81
76
|
@loader.expects(:parse_file).with(make_absolute("/one")).returns(Puppet::Parser::AST::Hostclass.new(''))
|
82
|
-
@loader.import("myfile")
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should make each file qualified before attempting to parse it" do
|
86
|
-
Puppet::Parser::Files.expects(:find_manifests).returns ["modname", %w{one}]
|
87
|
-
@loader.expects(:parse_file).with(make_absolute("/current/one")).returns(Puppet::Parser::AST::Hostclass.new(''))
|
88
|
-
@loader.import("myfile", make_absolute("/current/file"))
|
77
|
+
@loader.import("myfile", "/path")
|
89
78
|
end
|
90
79
|
|
91
80
|
it "should not attempt to import files that have already been imported" do
|
92
81
|
@loader = Puppet::Parser::TypeLoader.new(:myenv)
|
93
82
|
|
94
|
-
Puppet::Parser::Files.expects(:
|
83
|
+
Puppet::Parser::Files.expects(:find_manifests_in_modules).returns ["modname", %w{/one}]
|
95
84
|
parser_class.any_instance.expects(:parse).once.returns(Puppet::Parser::AST::Hostclass.new(''))
|
96
85
|
other_parser_class.any_instance.expects(:parse).never.returns(Puppet::Parser::AST::Hostclass.new(''))
|
97
|
-
@loader.import("myfile")
|
86
|
+
@loader.import("myfile", "/path")
|
98
87
|
|
99
88
|
# This will fail if it tries to reimport the file.
|
100
|
-
@loader.import("myfile")
|
89
|
+
@loader.import("myfile", "/path")
|
101
90
|
end
|
102
91
|
end
|
103
92
|
|
@@ -219,7 +208,7 @@ describe Puppet::Parser::TypeLoader do
|
|
219
208
|
it "should be able to add classes to the current resource type collection" do
|
220
209
|
file = tmpfile("simple_file.pp")
|
221
210
|
File.open(file, "w") { |f| f.puts "class foo {}" }
|
222
|
-
@loader.import(file)
|
211
|
+
@loader.import(File.basename(file), File.dirname(file))
|
223
212
|
|
224
213
|
@loader.known_resource_types.hostclass("foo").should be_instance_of(Puppet::Resource::Type)
|
225
214
|
end
|
@@ -55,6 +55,14 @@ describe Puppet::Resource::TypeCollection do
|
|
55
55
|
@code.node("foo").should equal(node)
|
56
56
|
end
|
57
57
|
|
58
|
+
it "should fail if a duplicate node is added" do
|
59
|
+
@code.add(Puppet::Resource::Type.new(:node, "foo"))
|
60
|
+
|
61
|
+
expect do
|
62
|
+
@code.add(Puppet::Resource::Type.new(:node, "foo"))
|
63
|
+
end.to raise_error(Puppet::ParseError, /cannot redefine/)
|
64
|
+
end
|
65
|
+
|
58
66
|
it "should store hostclasses as hostclasses" do
|
59
67
|
klass = Puppet::Resource::Type.new(:hostclass, "foo")
|
60
68
|
|
@@ -62,6 +70,16 @@ describe Puppet::Resource::TypeCollection do
|
|
62
70
|
@code.hostclass("foo").should equal(klass)
|
63
71
|
end
|
64
72
|
|
73
|
+
it "merge together hostclasses of the same name" do
|
74
|
+
klass1 = Puppet::Resource::Type.new(:hostclass, "foo", :doc => "first")
|
75
|
+
klass2 = Puppet::Resource::Type.new(:hostclass, "foo", :doc => "second")
|
76
|
+
|
77
|
+
@code.add(klass1)
|
78
|
+
@code.add(klass2)
|
79
|
+
|
80
|
+
@code.hostclass("foo").doc.should == "firstsecond"
|
81
|
+
end
|
82
|
+
|
65
83
|
it "should store definitions as definitions" do
|
66
84
|
define = Puppet::Resource::Type.new(:definition, "foo")
|
67
85
|
|
@@ -69,13 +87,12 @@ describe Puppet::Resource::TypeCollection do
|
|
69
87
|
@code.definition("foo").should equal(define)
|
70
88
|
end
|
71
89
|
|
72
|
-
it "should
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
loader.add(second)
|
90
|
+
it "should fail if a duplicate definition is added" do
|
91
|
+
@code.add(Puppet::Resource::Type.new(:definition, "foo"))
|
92
|
+
|
93
|
+
expect do
|
94
|
+
@code.add(Puppet::Resource::Type.new(:definition, "foo"))
|
95
|
+
end.to raise_error(Puppet::ParseError, /cannot be redefined/)
|
79
96
|
end
|
80
97
|
|
81
98
|
it "should remove all nodes, classes, and definitions when cleared" do
|
@@ -180,58 +197,27 @@ describe Puppet::Resource::TypeCollection do
|
|
180
197
|
end
|
181
198
|
|
182
199
|
%w{hostclass node definition}.each do |data|
|
183
|
-
|
184
|
-
@instance = Puppet::Resource::Type.new(data, "foo")
|
185
|
-
end
|
200
|
+
describe "behavior of add for #{data}" do
|
186
201
|
|
187
|
-
|
188
|
-
Puppet::Resource::TypeCollection.new("env").should respond_to("add_#{data}")
|
189
|
-
end
|
190
|
-
|
191
|
-
it "should use the name of the instance to add it" do
|
192
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
193
|
-
loader.send("add_#{data}", @instance)
|
194
|
-
loader.send(data, @instance.name).should equal(@instance)
|
195
|
-
end
|
196
|
-
|
197
|
-
unless data == "hostclass"
|
198
|
-
it "should fail to add a #{data} when one already exists" do
|
202
|
+
it "should return the added #{data}" do
|
199
203
|
loader = Puppet::Resource::TypeCollection.new("env")
|
200
|
-
|
201
|
-
lambda { loader.add(@instance) }.should raise_error(Puppet::ParseError)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
it "should return the added #{data}" do
|
206
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
204
|
+
instance = Puppet::Resource::Type.new(data, "foo")
|
207
205
|
|
208
|
-
|
209
|
-
|
206
|
+
loader.add(instance).should equal(instance)
|
207
|
+
end
|
210
208
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
loader.add instance
|
215
|
-
loader.send(data, "bar").should equal(instance)
|
216
|
-
end
|
209
|
+
it "should retrieve #{data} insensitive to case" do
|
210
|
+
loader = Puppet::Resource::TypeCollection.new("env")
|
211
|
+
instance = Puppet::Resource::Type.new(data, "Bar")
|
217
212
|
|
218
|
-
|
219
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
220
|
-
instance = Puppet::Resource::Type.new(data, "Bar")
|
221
|
-
loader.add instance
|
222
|
-
loader.send(data, "bAr").should equal(instance)
|
223
|
-
end
|
213
|
+
loader.add instance
|
224
214
|
|
225
|
-
|
226
|
-
|
227
|
-
end
|
215
|
+
loader.send(data, "bAr").should equal(instance)
|
216
|
+
end
|
228
217
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
instance = Puppet::Resource::Type.new(data, "foo")
|
233
|
-
loader.add instance
|
234
|
-
loader.send(plurals[data]).should == { "foo" => instance }
|
218
|
+
it "should return nil when asked for a #{data} that has not been added" do
|
219
|
+
Puppet::Resource::TypeCollection.new("env").send(data, "foo").should be_nil
|
220
|
+
end
|
235
221
|
end
|
236
222
|
end
|
237
223
|
|
@@ -319,12 +305,12 @@ describe Puppet::Resource::TypeCollection do
|
|
319
305
|
it "should only look in the topclass, if the name is qualified" do
|
320
306
|
@loader.find_hostclass("foo", "::bar").name.should == 'bar'
|
321
307
|
end
|
322
|
-
|
308
|
+
|
323
309
|
it "should only look in the topclass, if we assume the name is fully qualified" do
|
324
310
|
@loader.find_hostclass("foo", "bar", :assume_fqname => true).name.should == 'bar'
|
325
311
|
end
|
326
312
|
end
|
327
|
-
|
313
|
+
|
328
314
|
it "should not look in the local scope for classes when the name is qualified" do
|
329
315
|
@loader = Puppet::Resource::TypeCollection.new("env")
|
330
316
|
@loader.add Puppet::Resource::Type.new(:hostclass, "foo::bar")
|
@@ -341,18 +327,6 @@ describe Puppet::Resource::TypeCollection do
|
|
341
327
|
loader.find_node(stub("ignored"), "bar").should == node
|
342
328
|
end
|
343
329
|
|
344
|
-
it "should use the 'find_or_load' method to find hostclasses" do
|
345
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
346
|
-
loader.expects(:find_or_load).with("foo", "bar", :hostclass, {})
|
347
|
-
loader.find_hostclass("foo", "bar")
|
348
|
-
end
|
349
|
-
|
350
|
-
it "should use the 'find_or_load' method to find definitions" do
|
351
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
352
|
-
loader.expects(:find_or_load).with("foo", "bar", :definition)
|
353
|
-
loader.find_definition("foo", "bar")
|
354
|
-
end
|
355
|
-
|
356
330
|
it "should indicate whether any nodes are defined" do
|
357
331
|
loader = Puppet::Resource::TypeCollection.new("env")
|
358
332
|
loader.add_node(Puppet::Resource::Type.new(:node, "foo"))
|
@@ -458,7 +432,5 @@ describe Puppet::Resource::TypeCollection do
|
|
458
432
|
|
459
433
|
lambda { @code.version }.should raise_error(Puppet::ParseError)
|
460
434
|
end
|
461
|
-
|
462
435
|
end
|
463
|
-
|
464
436
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: facter
|
@@ -878,6 +878,7 @@ files:
|
|
878
878
|
- lib/puppet/forge/repository.rb
|
879
879
|
- lib/puppet/forge/cache.rb
|
880
880
|
- lib/puppet/file_serving.rb
|
881
|
+
- lib/puppet/file_system/path_pattern.rb
|
881
882
|
- lib/puppet/network/authentication.rb
|
882
883
|
- lib/puppet/network/rights.rb
|
883
884
|
- lib/puppet/network/rest_controller.rb
|
@@ -919,6 +920,7 @@ files:
|
|
919
920
|
- lib/puppet/forge.rb
|
920
921
|
- lib/puppet/data_binding.rb
|
921
922
|
- lib/puppet/simple_graph.rb
|
923
|
+
- lib/puppet/file_system.rb
|
922
924
|
- lib/puppet/daemon.rb
|
923
925
|
- lib/puppet/network.rb
|
924
926
|
- lib/puppet/parameter/value.rb
|
@@ -1969,6 +1971,7 @@ files:
|
|
1969
1971
|
- spec/unit/forge/repository_spec.rb
|
1970
1972
|
- spec/unit/forge/errors_spec.rb
|
1971
1973
|
- spec/unit/daemon_spec.rb
|
1974
|
+
- spec/unit/file_system/path_pattern_spec.rb
|
1972
1975
|
- spec/unit/status_spec.rb
|
1973
1976
|
- spec/unit/network/authentication_spec.rb
|
1974
1977
|
- spec/unit/network/rights_spec.rb
|
@@ -2878,6 +2881,7 @@ test_files:
|
|
2878
2881
|
- spec/unit/forge/repository_spec.rb
|
2879
2882
|
- spec/unit/forge/errors_spec.rb
|
2880
2883
|
- spec/unit/daemon_spec.rb
|
2884
|
+
- spec/unit/file_system/path_pattern_spec.rb
|
2881
2885
|
- spec/unit/status_spec.rb
|
2882
2886
|
- spec/unit/network/authentication_spec.rb
|
2883
2887
|
- spec/unit/network/rights_spec.rb
|