puppet 2.7.4 → 2.7.5
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/CHANGELOG +10 -0
- data/conf/redhat/puppet.spec +8 -2
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application/resource.rb +17 -10
- data/lib/puppet/indirector/resource/active_record.rb +4 -1
- data/lib/puppet/provider/ssh_authorized_key/parsed.rb +10 -9
- data/lib/puppet/type/k5login.rb +3 -1
- data/spec/unit/indirector/resource/active_record_spec.rb +9 -4
- data/spec/unit/indirector/terminus_spec.rb +3 -3
- data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +8 -8
- metadata +4 -6
- data/lib/puppet/indirector/file.rb +0 -79
- data/spec/unit/indirector/file_spec.rb +0 -179
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
2.7.5
|
2
|
+
===
|
3
|
+
a36f39d Updating version numbers for 2.7.5
|
4
|
+
de51f3d (#9832) 2.7.4 StoreConfigs regression with PostgreSQL.
|
5
|
+
1aa9be5 (#9793) "secure" indirector file backed terminus base class.
|
6
|
+
d76c309 (#9792) Predictable temporary filename in ralsh. (CVE-2011-3871)
|
7
|
+
b29b178 Drop privileges before creating and chmodding SSH keys.(CVE-2011-3870)
|
8
|
+
7d4c169 (#9794) k5login can overwrite arbitrary files as root (CVE-2011-3869)
|
9
|
+
|
10
|
+
|
1
11
|
2.7.4
|
2
12
|
===
|
3
13
|
47135fb Resist directory traversal attacks through indirections. (CVE-2011-3484)
|
data/conf/redhat/puppet.spec
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
%global confdir conf/redhat
|
6
6
|
|
7
7
|
Name: puppet
|
8
|
-
Version: 2.7.
|
9
|
-
Release:
|
8
|
+
Version: 2.7.5
|
9
|
+
Release: 1%{?dist}
|
10
10
|
Summary: A network tool for managing many disparate systems
|
11
11
|
License: ASL 2.0
|
12
12
|
URL: http://puppetlabs.com
|
@@ -282,6 +282,12 @@ fi
|
|
282
282
|
rm -rf %{buildroot}
|
283
283
|
|
284
284
|
%changelog
|
285
|
+
* Fri Sep 30 2011 Michael Stahnke <stahnma@puppetlabs.com> - 2.7.5-1
|
286
|
+
- Fixes for CVE-2011-3869, 3870, 3871
|
287
|
+
|
288
|
+
* Wed Sep 28 2011 Michael Stahnke <stahnma@puppetlabs.com> - 2.7.4-1
|
289
|
+
- Fix for CVE-2011-3484
|
290
|
+
|
285
291
|
* Wed Jul 06 2011 Michael Stahnke <stahnma@puppetlabs.com> - 2.7.2-0.2.rc1
|
286
292
|
- Clean up rpmlint errors
|
287
293
|
- Put man pages in correct package
|
data/lib/puppet.rb
CHANGED
@@ -190,18 +190,25 @@ Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
|
|
190
190
|
end.map(&format).join("\n")
|
191
191
|
|
192
192
|
if options[:edit]
|
193
|
-
|
193
|
+
require 'tempfile'
|
194
|
+
# Prefer the current directory, which is more likely to be secure
|
195
|
+
# and, in the case of interactive use, accessible to the user.
|
196
|
+
tmpfile = Tempfile.new('x2puppet', Dir.pwd)
|
194
197
|
begin
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
system("
|
198
|
+
# sync write, so nothing buffers before we invoke the editor.
|
199
|
+
tmpfile.sync = true
|
200
|
+
tmpfile.puts text
|
201
|
+
|
202
|
+
# edit the content
|
203
|
+
system(ENV["EDITOR"] || 'vi', tmpfile.path)
|
204
|
+
|
205
|
+
# ...and, now, pass that file to puppet to apply. Because
|
206
|
+
# many editors rename or replace the original file we need to
|
207
|
+
# feed the pathname, not the file content itself, to puppet.
|
208
|
+
system('puppet -v ' + tmpfile.path)
|
201
209
|
ensure
|
202
|
-
#
|
203
|
-
|
204
|
-
#end
|
210
|
+
# The temporary file will be safely removed.
|
211
|
+
tmpfile.close(true)
|
205
212
|
end
|
206
213
|
else
|
207
214
|
puts text
|
@@ -62,7 +62,10 @@ class Puppet::Resource::ActiveRecord < Puppet::Indirector::ActiveRecord
|
|
62
62
|
# Some versions of ActiveRecord just to_s a symbol, which our type is, but
|
63
63
|
# others preserve the symbol-nature, which causes our storage (string) and
|
64
64
|
# query (symbol) to mismatch. So, manually stringify. --daniel 2011-09-08
|
65
|
-
|
65
|
+
#
|
66
|
+
# Also, PostgreSQL is case sensitive; we need to make sure our type name
|
67
|
+
# here matches what we inject. --daniel 2011-09-30
|
68
|
+
arguments = [true, type.to_s.capitalize]
|
66
69
|
|
67
70
|
if filter then
|
68
71
|
sql, values = filter_to_active_record(filter)
|
@@ -50,21 +50,22 @@ require 'puppet/provider/parsedfile'
|
|
50
50
|
def flush
|
51
51
|
raise Puppet::Error, "Cannot write SSH authorized keys without user" unless @resource.should(:user)
|
52
52
|
raise Puppet::Error, "User '#{@resource.should(:user)}' does not exist" unless uid = Puppet::Util.uid(@resource.should(:user))
|
53
|
-
unless File.exist?(dir = File.dirname(target))
|
54
|
-
Puppet.debug "Creating #{dir}"
|
55
|
-
Dir.mkdir(dir, dir_perm)
|
56
|
-
File.chown(uid, nil, dir)
|
57
|
-
end
|
58
|
-
|
59
53
|
# ParsedFile usually calls backup_target much later in the flush process,
|
60
54
|
# but our SUID makes that fail to open filebucket files for writing.
|
61
55
|
# Fortunately, there's already logic to make sure it only ever happens once,
|
62
56
|
# so calling it here supresses the later attempt by our superclass's flush method.
|
63
57
|
self.class.backup_target(target)
|
64
58
|
|
65
|
-
Puppet::Util::SUIDManager.asuser(@resource.should(:user))
|
66
|
-
|
67
|
-
|
59
|
+
Puppet::Util::SUIDManager.asuser(@resource.should(:user)) do
|
60
|
+
unless File.exist?(dir = File.dirname(target))
|
61
|
+
Puppet.debug "Creating #{dir}"
|
62
|
+
Dir.mkdir(dir, dir_perm)
|
63
|
+
end
|
64
|
+
|
65
|
+
super
|
66
|
+
|
67
|
+
File.chmod(file_perm, target)
|
68
|
+
end
|
68
69
|
end
|
69
70
|
|
70
71
|
# parse sshv2 option strings, wich is a comma separated list of
|
data/lib/puppet/type/k5login.rb
CHANGED
@@ -70,7 +70,7 @@ describe "Puppet::Resource::ActiveRecord", :if => (Puppet.features.rails? and de
|
|
70
70
|
host = Puppet::Rails::Host.create!(:name => 'one.local')
|
71
71
|
Puppet::Rails::Resource.
|
72
72
|
create!(:host => host,
|
73
|
-
:restype => '
|
73
|
+
:restype => 'Exec', :title => 'whammo',
|
74
74
|
:exported => true)
|
75
75
|
|
76
76
|
end
|
@@ -80,12 +80,12 @@ describe "Puppet::Resource::ActiveRecord", :if => (Puppet.features.rails? and de
|
|
80
80
|
found.length.should == 1
|
81
81
|
found.map do |item|
|
82
82
|
item.should respond_to :to_resource
|
83
|
-
item.restype.should == "
|
83
|
+
item.restype.should == "Exec"
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
87
|
it "should not filter resources that have been found before" do
|
88
|
-
search("
|
88
|
+
search("Exec").should == search("Exec")
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
@@ -137,7 +137,12 @@ describe "Puppet::Resource::ActiveRecord", :if => (Puppet.features.rails? and de
|
|
137
137
|
got.keys.should =~ [:conditions]
|
138
138
|
got[:conditions][0].should be_include "(exported=? AND restype=?)"
|
139
139
|
got[:conditions][1].should == true
|
140
|
-
got[:conditions][2].should == type.to_s
|
140
|
+
got[:conditions][2].should == type.to_s.capitalize
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should capitalize the type, since PGSQL is case sensitive" do
|
144
|
+
got = query(type, 'whatever')
|
145
|
+
got[:conditions][2].should == 'Notify'
|
141
146
|
end
|
142
147
|
end
|
143
148
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
require 'puppet/defaults'
|
4
4
|
require 'puppet/indirector'
|
5
|
-
require 'puppet/indirector/
|
5
|
+
require 'puppet/indirector/memory'
|
6
6
|
|
7
7
|
describe Puppet::Indirector::Terminus, :'fails_on_ruby_1.9.2' => true do
|
8
8
|
before :each do
|
@@ -201,14 +201,14 @@ describe Puppet::Indirector::Terminus, " when parsing class constants for indire
|
|
201
201
|
@subclass.expects(:indirection=).with(:test_ind)
|
202
202
|
@subclass.stubs(:name=)
|
203
203
|
@subclass.stubs(:terminus_type=)
|
204
|
-
Puppet::Indirector::
|
204
|
+
Puppet::Indirector::Memory.inherited(@subclass)
|
205
205
|
end
|
206
206
|
|
207
207
|
it "should convert the indirection name to a downcased symbol" do
|
208
208
|
@subclass.expects(:indirection=).with(:test_ind)
|
209
209
|
@subclass.stubs(:name=)
|
210
210
|
@subclass.stubs(:terminus_type=)
|
211
|
-
Puppet::Indirector::
|
211
|
+
Puppet::Indirector::Memory.inherited(@subclass)
|
212
212
|
end
|
213
213
|
|
214
214
|
it "should convert camel case to lower case with underscores as word separators" do
|
@@ -110,15 +110,15 @@ describe provider_class, :unless => Puppet.features.microsoft_windows? do
|
|
110
110
|
@provider.flush
|
111
111
|
end
|
112
112
|
|
113
|
-
it "should chown the directory to the user" do
|
113
|
+
it "should absolutely not chown the directory to the user" do
|
114
114
|
uid = Puppet::Util.uid("random_bob")
|
115
|
-
File.expects(:chown).
|
115
|
+
File.expects(:chown).never
|
116
116
|
@provider.flush
|
117
117
|
end
|
118
118
|
|
119
|
-
it "should chown the key file to the user" do
|
119
|
+
it "should absolutely not chown the key file to the user" do
|
120
120
|
uid = Puppet::Util.uid("random_bob")
|
121
|
-
File.expects(:chown).
|
121
|
+
File.expects(:chown).never
|
122
122
|
@provider.flush
|
123
123
|
end
|
124
124
|
|
@@ -153,11 +153,11 @@ describe provider_class, :unless => Puppet.features.microsoft_windows? do
|
|
153
153
|
@provider.flush
|
154
154
|
end
|
155
155
|
|
156
|
-
it "should chown the directory to the user if it creates it" do
|
156
|
+
it "should absolutely not chown the directory to the user if it creates it" do
|
157
157
|
File.stubs(:exist?).with(@dir).returns false
|
158
158
|
Dir.stubs(:mkdir).with(@dir,0700)
|
159
159
|
uid = Puppet::Util.uid("nobody")
|
160
|
-
File.expects(:chown).
|
160
|
+
File.expects(:chown).never
|
161
161
|
@provider.flush
|
162
162
|
end
|
163
163
|
|
@@ -168,9 +168,9 @@ describe provider_class, :unless => Puppet.features.microsoft_windows? do
|
|
168
168
|
@provider.flush
|
169
169
|
end
|
170
170
|
|
171
|
-
it "should chown the key file to the user" do
|
171
|
+
it "should absolutely not chown the key file to the user" do
|
172
172
|
uid = Puppet::Util.uid("nobody")
|
173
|
-
File.expects(:chown).
|
173
|
+
File.expects(:chown).never
|
174
174
|
@provider.flush
|
175
175
|
end
|
176
176
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 7
|
9
|
-
-
|
10
|
-
version: 2.7.
|
9
|
+
- 5
|
10
|
+
version: 2.7.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Puppet Labs
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-09-
|
18
|
+
date: 2011-09-30 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: facter
|
@@ -215,7 +215,6 @@ files:
|
|
215
215
|
- lib/puppet/indirector/facts/rest.rb
|
216
216
|
- lib/puppet/indirector/facts/store_configs.rb
|
217
217
|
- lib/puppet/indirector/facts/yaml.rb
|
218
|
-
- lib/puppet/indirector/file.rb
|
219
218
|
- lib/puppet/indirector/file_bucket_file/file.rb
|
220
219
|
- lib/puppet/indirector/file_bucket_file/rest.rb
|
221
220
|
- lib/puppet/indirector/file_content/file.rb
|
@@ -1332,7 +1331,6 @@ files:
|
|
1332
1331
|
- spec/unit/indirector/file_metadata/file_spec.rb
|
1333
1332
|
- spec/unit/indirector/file_metadata/rest_spec.rb
|
1334
1333
|
- spec/unit/indirector/file_server_spec.rb
|
1335
|
-
- spec/unit/indirector/file_spec.rb
|
1336
1334
|
- spec/unit/indirector/indirection_spec.rb
|
1337
1335
|
- spec/unit/indirector/inventory/yaml_spec.rb
|
1338
1336
|
- spec/unit/indirector/key/ca_spec.rb
|
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'puppet/indirector/terminus'
|
2
|
-
|
3
|
-
# Store instances as files, usually serialized using some format.
|
4
|
-
class Puppet::Indirector::File < Puppet::Indirector::Terminus
|
5
|
-
# Where do we store our data?
|
6
|
-
def data_directory
|
7
|
-
name = Puppet.run_mode.master? ? :server_datadir : :client_datadir
|
8
|
-
|
9
|
-
File.join(Puppet.settings[name], self.class.indirection_name.to_s)
|
10
|
-
end
|
11
|
-
|
12
|
-
def file_format(path)
|
13
|
-
path =~ /\.(\w+)$/ and return $1
|
14
|
-
end
|
15
|
-
|
16
|
-
def file_path(request)
|
17
|
-
File.join(data_directory, request.key + ".#{serialization_format}")
|
18
|
-
end
|
19
|
-
|
20
|
-
def latest_path(request)
|
21
|
-
files = Dir.glob(File.join(data_directory, request.key + ".*"))
|
22
|
-
return nil if files.empty?
|
23
|
-
|
24
|
-
# Return the newest file.
|
25
|
-
files.sort { |a, b| File.stat(b).mtime <=> File.stat(a).mtime }[0]
|
26
|
-
end
|
27
|
-
|
28
|
-
def serialization_format
|
29
|
-
model.default_format
|
30
|
-
end
|
31
|
-
|
32
|
-
# Remove files on disk.
|
33
|
-
def destroy(request)
|
34
|
-
begin
|
35
|
-
removed = false
|
36
|
-
Dir.glob(File.join(data_directory, request.key.to_s + ".*")).each do |file|
|
37
|
-
removed = true
|
38
|
-
File.unlink(file)
|
39
|
-
end
|
40
|
-
rescue => detail
|
41
|
-
raise Puppet::Error, "Could not remove #{request.key}: #{detail}"
|
42
|
-
end
|
43
|
-
|
44
|
-
raise Puppet::Error, "Could not find files for #{request.key} to remove" unless removed
|
45
|
-
end
|
46
|
-
|
47
|
-
# Return a model instance for a given file on disk.
|
48
|
-
def find(request)
|
49
|
-
return nil unless path = latest_path(request)
|
50
|
-
format = file_format(path)
|
51
|
-
|
52
|
-
raise ArgumentError, "File format #{format} is not supported by #{self.class.indirection_name}" unless model.support_format?(format)
|
53
|
-
|
54
|
-
begin
|
55
|
-
return model.convert_from(format, File.read(path))
|
56
|
-
rescue => detail
|
57
|
-
raise Puppet::Error, "Could not convert path #{path} into a #{self.class.indirection_name}: #{detail}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# Save a new file to disk.
|
62
|
-
def save(request)
|
63
|
-
path = file_path(request)
|
64
|
-
|
65
|
-
dir = File.dirname(path)
|
66
|
-
|
67
|
-
raise Puppet::Error.new("Cannot save #{request.key}; parent directory #{dir} does not exist") unless File.directory?(dir)
|
68
|
-
|
69
|
-
begin
|
70
|
-
File.open(path, "w") { |f| f.print request.instance.render(serialization_format) }
|
71
|
-
rescue => detail
|
72
|
-
raise Puppet::Error, "Could not write #{request.key}: #{detail}" % [request.key, detail]
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def path(key)
|
77
|
-
key
|
78
|
-
end
|
79
|
-
end
|
@@ -1,179 +0,0 @@
|
|
1
|
-
#!/usr/bin/env rspec
|
2
|
-
require 'spec_helper'
|
3
|
-
require 'puppet/indirector/file'
|
4
|
-
|
5
|
-
|
6
|
-
describe Puppet::Indirector::File do
|
7
|
-
before :all do
|
8
|
-
Puppet::Indirector::Terminus.stubs(:register_terminus_class)
|
9
|
-
@model = mock 'model'
|
10
|
-
@indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model
|
11
|
-
Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection)
|
12
|
-
|
13
|
-
module Testing; end
|
14
|
-
@file_class = class Testing::MyFile < Puppet::Indirector::File
|
15
|
-
self
|
16
|
-
end
|
17
|
-
|
18
|
-
@searcher = @file_class.new
|
19
|
-
|
20
|
-
@path = "/my/file"
|
21
|
-
@dir = "/my"
|
22
|
-
|
23
|
-
@request = stub 'request', :key => @path
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "when finding files" do
|
27
|
-
it "should provide a method to return file contents at a specified path" do
|
28
|
-
@searcher.should respond_to(:find)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should use the server data directory plus the indirection name if the run_mode is master" do
|
32
|
-
Puppet.run_mode.expects(:master?).returns true
|
33
|
-
Puppet.settings.expects(:value).with(:server_datadir).returns "/my/dir"
|
34
|
-
|
35
|
-
@searcher.data_directory.should == File.join("/my/dir", "mystuff")
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should use the client data directory plus the indirection name if the run_mode is not master" do
|
39
|
-
Puppet.run_mode.expects(:master?).returns false
|
40
|
-
Puppet.settings.expects(:value).with(:client_datadir).returns "/my/dir"
|
41
|
-
|
42
|
-
@searcher.data_directory.should == File.join("/my/dir", "mystuff")
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should use the newest file in the data directory matching the indirection key without extension" do
|
46
|
-
@searcher.expects(:data_directory).returns "/data/dir"
|
47
|
-
@request.stubs(:key).returns "foo"
|
48
|
-
Dir.expects(:glob).with("/data/dir/foo.*").returns %w{/data1.stuff /data2.stuff}
|
49
|
-
|
50
|
-
stat1 = stub 'data1', :mtime => (Time.now - 5)
|
51
|
-
stat2 = stub 'data2', :mtime => Time.now
|
52
|
-
File.expects(:stat).with("/data1.stuff").returns stat1
|
53
|
-
File.expects(:stat).with("/data2.stuff").returns stat2
|
54
|
-
|
55
|
-
@searcher.latest_path(@request).should == "/data2.stuff"
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should return nil when no files are found" do
|
59
|
-
@searcher.stubs(:latest_path).returns nil
|
60
|
-
|
61
|
-
@searcher.find(@request).should be_nil
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should determine the file format from the file extension" do
|
65
|
-
@searcher.file_format("/data2.pson").should == "pson"
|
66
|
-
end
|
67
|
-
|
68
|
-
it "should fail if the model does not support the file format" do
|
69
|
-
@searcher.stubs(:latest_path).returns "/my/file.pson"
|
70
|
-
|
71
|
-
@model.expects(:support_format?).with("pson").returns false
|
72
|
-
|
73
|
-
lambda { @searcher.find(@request) }.should raise_error(ArgumentError)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
describe "when saving files" do
|
78
|
-
before do
|
79
|
-
@content = "my content"
|
80
|
-
@file = stub 'file', :content => @content, :path => @path, :name => @path, :render => "mydata"
|
81
|
-
@request.stubs(:instance).returns @file
|
82
|
-
end
|
83
|
-
|
84
|
-
it "should provide a method to save file contents at a specified path" do
|
85
|
-
@searcher.should respond_to(:save)
|
86
|
-
end
|
87
|
-
|
88
|
-
it "should choose the file extension based on the default format of the model" do
|
89
|
-
@model.expects(:default_format).returns "pson"
|
90
|
-
|
91
|
-
@searcher.serialization_format.should == "pson"
|
92
|
-
end
|
93
|
-
|
94
|
-
it "should place the file in the data directory, named after the indirection, key, and format" do
|
95
|
-
@searcher.stubs(:data_directory).returns "/my/dir"
|
96
|
-
@searcher.stubs(:serialization_format).returns "pson"
|
97
|
-
|
98
|
-
@request.stubs(:key).returns "foo"
|
99
|
-
@searcher.file_path(@request).should == File.join("/my/dir", "foo.pson")
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should fail intelligently if the file's parent directory does not exist" do
|
103
|
-
@searcher.stubs(:file_path).returns "/my/dir/file.pson"
|
104
|
-
@searcher.stubs(:serialization_format).returns "pson"
|
105
|
-
|
106
|
-
@request.stubs(:key).returns "foo"
|
107
|
-
File.expects(:directory?).with(File.join("/my/dir")).returns(false)
|
108
|
-
|
109
|
-
proc { @searcher.save(@request) }.should raise_error(Puppet::Error)
|
110
|
-
end
|
111
|
-
|
112
|
-
it "should render the instance using the file format and print it to the file path" do
|
113
|
-
@searcher.stubs(:file_path).returns "/my/file.pson"
|
114
|
-
@searcher.stubs(:serialization_format).returns "pson"
|
115
|
-
|
116
|
-
File.stubs(:directory?).returns true
|
117
|
-
|
118
|
-
@request.instance.expects(:render).with("pson").returns "data"
|
119
|
-
|
120
|
-
fh = mock 'filehandle'
|
121
|
-
File.expects(:open).with("/my/file.pson", "w").yields fh
|
122
|
-
fh.expects(:print).with("data")
|
123
|
-
|
124
|
-
@searcher.save(@request)
|
125
|
-
end
|
126
|
-
|
127
|
-
it "should fail intelligently if a file cannot be written" do
|
128
|
-
filehandle = mock 'file'
|
129
|
-
File.stubs(:directory?).returns(true)
|
130
|
-
File.stubs(:open).yields(filehandle)
|
131
|
-
filehandle.expects(:print).raises(ArgumentError)
|
132
|
-
|
133
|
-
@searcher.stubs(:file_path).returns "/my/file.pson"
|
134
|
-
@model.stubs(:default_format).returns "pson"
|
135
|
-
|
136
|
-
@instance.stubs(:render).returns "stuff"
|
137
|
-
|
138
|
-
proc { @searcher.save(@request) }.should raise_error(Puppet::Error)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
describe "when removing files" do
|
143
|
-
it "should provide a method to remove files" do
|
144
|
-
@searcher.should respond_to(:destroy)
|
145
|
-
end
|
146
|
-
|
147
|
-
it "should remove files in all formats found in the data directory that match the request key" do
|
148
|
-
@searcher.stubs(:data_directory).returns "/my/dir"
|
149
|
-
@request.stubs(:key).returns "me"
|
150
|
-
|
151
|
-
Dir.expects(:glob).with(File.join("/my/dir", "me.*")).returns %w{/one /two}
|
152
|
-
|
153
|
-
File.expects(:unlink).with("/one")
|
154
|
-
File.expects(:unlink).with("/two")
|
155
|
-
|
156
|
-
@searcher.destroy(@request)
|
157
|
-
end
|
158
|
-
|
159
|
-
it "should throw an exception if no file is found" do
|
160
|
-
@searcher.stubs(:data_directory).returns "/my/dir"
|
161
|
-
@request.stubs(:key).returns "me"
|
162
|
-
|
163
|
-
Dir.expects(:glob).with(File.join("/my/dir", "me.*")).returns []
|
164
|
-
|
165
|
-
proc { @searcher.destroy(@request) }.should raise_error(Puppet::Error)
|
166
|
-
end
|
167
|
-
|
168
|
-
it "should fail intelligently if a file cannot be removed" do
|
169
|
-
@searcher.stubs(:data_directory).returns "/my/dir"
|
170
|
-
@request.stubs(:key).returns "me"
|
171
|
-
|
172
|
-
Dir.expects(:glob).with(File.join("/my/dir", "me.*")).returns %w{/one}
|
173
|
-
|
174
|
-
File.expects(:unlink).with("/one").raises ArgumentError
|
175
|
-
|
176
|
-
proc { @searcher.destroy(@request) }.should raise_error(Puppet::Error)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|