Skip to content

Commit cf8bf1b

Browse files
committed
Merge branch 'CHEF-89' of git://github.com/seancribbs/chef into integration
2 parents 94505da + 3bc705c commit cf8bf1b

3 files changed

Lines changed: 104 additions & 72 deletions

File tree

NOTICE

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ Contributors and Copyright holders:
99
* Copyright 2008, Arjuna Christensen <aj@hjksolutions.com>
1010
* Copyright 2008, Bryan McLellan <btm@loftninjas.org>
1111
* Copyright 2008, Ezra Zygmuntowicz <ezra@engineyard.com>
12-
12+
* Copyright 2008, Sean Cribbs <seancribbs@gmail.com>
13+
1314
Chef incorporates code modified from Open4 (http://www.codeforpeople.com/lib/ruby/open4/), which was written by Ara T. Howard.
1415

1516
Chef incorporates code modified from Merb (http://www.merbivore.com), which is Copyright (c) 2008 Engine Yard.

chef/lib/chef/provider/remote_file.rb

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
# Licensed under the Apache License, Version 2.0 (the "License");
77
# you may not use this file except in compliance with the License.
88
# You may obtain a copy of the License at
9-
#
9+
#
1010
# http://www.apache.org/licenses/LICENSE-2.0
11-
#
11+
#
1212
# Unless required by applicable law or agreed to in writing, software
1313
# distributed under the License is distributed on an "AS IS" BASIS,
1414
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -26,71 +26,43 @@
2626
class Chef
2727
class Provider
2828
class RemoteFile < Chef::Provider::File
29-
29+
3030
include Chef::Mixin::FindPreferredFile
31-
32-
def action_create
31+
32+
def action_create
3333
Chef::Log.debug("Checking #{@new_resource} for changes")
3434
do_remote_file(@new_resource.source, @current_resource.path)
3535
end
36-
36+
3737
def action_create_if_missing
3838
if ::File.exists?(@new_resource.path)
3939
Chef::Log.debug("File #{@new_resource.path} exists, taking no action.")
4040
else
4141
action_create
4242
end
4343
end
44-
44+
4545
def do_remote_file(source, path)
46-
# The remote filehandle
47-
raw_file = nil
48-
4946
# The current files checksum
50-
current_checksum = nil
5147
current_checksum = self.checksum(path) if ::File.exists?(path)
52-
53-
# If we are solo, try and find the file in a local cookbook
54-
# assuming we find it, we open it up and set it to raw_file.
55-
if Chef::Config[:solo]
56-
filename = find_preferred_file(
57-
@new_resource.cookbook_name.to_s,
58-
:remote_file,
59-
source,
60-
@node[:fqdn],
61-
@node[:platform],
62-
@node[:platform_version]
63-
)
64-
Chef::Log.debug("Using local file for remote_file:#{filename}")
65-
raw_file = ::File.open(filename)
66-
else
67-
# Otherwise, we need to go get it from the chef server
68-
# This results in a tmpfile as raw_file
69-
r = Chef::REST.new(Chef::Config[:remotefile_url])
70-
71-
url = generate_url(
72-
source,
73-
"files",
74-
{
75-
:checksum => current_checksum
76-
}
77-
)
78-
79-
begin
80-
raw_file = r.get_rest(url, true)
81-
rescue Net::HTTPRetriableError => e
82-
if e.response.kind_of?(Net::HTTPNotModified)
83-
Chef::Log.debug("File #{path} is unchanged")
84-
return false
85-
else
86-
raise e
87-
end
48+
49+
begin
50+
# The remote filehandle
51+
raw_file = get_from_uri(source) ||
52+
get_from_server(source, current_checksum) ||
53+
get_from_local_cookbook(source)
54+
rescue Net::HTTPRetriableError => e
55+
if e.response.kind_of?(Net::HTTPNotModified)
56+
Chef::Log.debug("File #{path} is unchanged")
57+
return false
58+
else
59+
raise e
8860
end
8961
end
90-
62+
9163
# If the file exists
9264
if ::File.exists?(@new_resource.path)
93-
# And it matches the checsum of the raw file
65+
# And it matches the checksum of the raw file
9466
@new_resource.checksum(self.checksum(raw_file.path))
9567
if @new_resource.checksum != @current_resource.checksum
9668
# Updating target file, let's perform a backup!
@@ -102,17 +74,50 @@ def do_remote_file(source, path)
10274
# We're creating a new file
10375
Chef::Log.info("Creating #{@new_resource} at #{@new_resource.path}")
10476
end
105-
77+
10678
FileUtils.cp(raw_file.path, @new_resource.path)
10779
@new_resource.updated = true
80+
81+
set_owner if @new_resource.owner
82+
set_group if @new_resource.group
83+
set_mode if @new_resource.mode
10884

109-
set_owner if @new_resource.owner != nil
110-
set_group if @new_resource.group != nil
111-
set_mode if @new_resource.mode != nil
85+
# We're done with the file, so make sure to close it if it was open.
86+
raw_file.close
87+
true
88+
end
11289

113-
return true
90+
def get_from_uri(source)
91+
uri = URI.parse(source)
92+
if uri.absolute
93+
r = Chef::REST.new(source)
94+
r.get_rest(source, true).open
95+
end
96+
rescue URI::InvalidURIError
97+
nil
11498
end
115-
99+
100+
def get_from_server(source, current_checksum)
101+
unless Chef::Config[:solo]
102+
r = Chef::REST.new(Chef::Config[:remotefile_url])
103+
url = generate_url(source, "files", :checksum => current_checksum)
104+
r.get_rest(url, true).open
105+
end
106+
end
107+
108+
def get_from_local_cookbook(source)
109+
filename = find_preferred_file(
110+
@new_resource.cookbook_name.to_s,
111+
:remote_file,
112+
source,
113+
@node[:fqdn],
114+
@node[:platform],
115+
@node[:platform_version]
116+
)
117+
Chef::Log.debug("Using local file for remote_file:#{filename}")
118+
::File.open(filename)
119+
end
120+
116121
end
117122
end
118123
end

chef/spec/unit/provider/remote_file_spec.rb

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
before(:each) do
4141
@rest = mock(Chef::REST, { })
4242
@tempfile = mock(Tempfile, { :path => "/tmp/foo", })
43+
@tempfile.stub!(:open).and_return(@tempfile)
44+
@tempfile.stub!(:close)
4345
@rest.stub!(:get_rest).and_return(@tempfile)
4446
@resource = Chef::Resource::RemoteFile.new("seattle")
4547
@resource.path(File.join(File.dirname(__FILE__), "..", "..", "data", "seattle.txt"))
@@ -61,7 +63,41 @@ def do_remote_file
6163
Chef::REST.stub!(:new).and_return(@rest)
6264
@provider.do_remote_file(@resource.source, @resource.path)
6365
end
66+
67+
describe "when given a URI source" do
68+
it "should download the file from the remote URL" do
69+
@resource.source("http://opscode.com/seattle.txt")
70+
@rest.should_receive(:get_rest).with("http://opscode.com/seattle.txt", true).and_return(@tempfile)
71+
do_remote_file
72+
end
73+
end
6474

75+
describe "when given a non-URI source" do
76+
describe "and using chef-solo" do
77+
it "should load the file from the local cookbook" do
78+
Chef::Config[:solo] = true
79+
File.stub!(:open).and_return(@tempfile)
80+
@provider.should_receive(:find_preferred_file).with("monkey", :remote_file, @resource.source, "latte.local", nil, nil).and_return(@tempfile.path)
81+
do_remote_file
82+
end
83+
end
84+
85+
it "should call generate_url with the current checksum as an extra attribute" do
86+
@provider.should_receive(:generate_url).with(@resource.source, "files", { :checksum => "0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa"})
87+
do_remote_file
88+
end
89+
90+
it "should call get_rest with a correctly composed url" do
91+
url = "cookbooks/#{@resource.cookbook_name}/files?id=#{@resource.source}"
92+
url += "&platform=mac_os_x"
93+
url += "&version=10.5.1"
94+
url += "&fqdn=latte.local"
95+
url += "&checksum=0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa"
96+
@rest.should_receive(:get_rest).with(url, true).and_return(@tempfile)
97+
do_remote_file
98+
end
99+
end
100+
65101
it "should set the checksum if the file exists" do
66102
@provider.should_receive(:checksum).with(@resource.path)
67103
do_remote_file
@@ -72,22 +108,7 @@ def do_remote_file
72108
@provider.should_not_receive(:checksum).with(@resource.path)
73109
do_remote_file
74110
end
75-
76-
it "should call generate_url with the current checksum as an extra attribute" do
77-
@provider.should_receive(:generate_url).with(@resource.source, "files", { :checksum => "0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa"})
78-
do_remote_file
79-
end
80-
81-
it "should call get_rest with a correctly composed url" do
82-
url = "cookbooks/#{@resource.cookbook_name}/files?id=#{@resource.source}"
83-
url += "&platform=mac_os_x"
84-
url += "&version=10.5.1"
85-
url += "&fqdn=latte.local"
86-
url += "&checksum=0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa"
87-
@rest.should_receive(:get_rest).with(url, true).and_return(@tempfile)
88-
do_remote_file
89-
end
90-
111+
91112
it "should not transfer the file if it has not been changed" do
92113
r = Net::HTTPNotModified.new("one", "two", "three")
93114
e = Net::HTTPRetriableError.new("304", r)
@@ -117,6 +138,7 @@ def do_remote_file
117138
describe "when the target file already exists" do
118139
before do
119140
::File.stub!(:exists?).and_return(true)
141+
@provider.stub!(:get_from_server).and_return(@tempfile)
120142
end
121143

122144
it "should backup the original file if it is different" do
@@ -160,6 +182,10 @@ def do_remote_file
160182
do_remote_file
161183
end
162184

185+
it "should close the file when done" do
186+
@tempfile.should_receive(:close)
187+
do_remote_file
188+
end
163189
# TODO: Finish these tests
164190

165191
end

0 commit comments

Comments
 (0)