chef 10.16.4 → 10.16.6.rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +1 -1
- data/lib/chef/monkey_patches/fileutils.rb +65 -0
- data/lib/chef/provider/deploy.rb +2 -1
- data/lib/chef/provider/template.rb +1 -1
- data/lib/chef/version.rb +1 -1
- data/spec/data/git_bundles/sinatra-test-app-with-symlinks.gitbundle +0 -0
- data/spec/functional/knife/cookbook_delete_spec.rb +0 -2
- data/spec/functional/knife/exec_spec.rb +2 -4
- data/spec/functional/knife/ssh_spec.rb +0 -1
- data/spec/functional/resource/cookbook_file_spec.rb +7 -1
- data/spec/functional/resource/deploy_revision_spec.rb +17 -1
- data/spec/functional/resource/link_spec.rb +1 -1
- data/spec/functional/resource/remote_file_spec.rb +10 -3
- data/spec/functional/tiny_server_spec.rb +5 -4
- data/spec/spec_helper.rb +2 -0
- data/spec/support/chef_helpers.rb +13 -0
- data/spec/support/platform_helpers.rb +8 -0
- data/spec/support/shared/functional/file_resource.rb +12 -4
- data/spec/support/shared/functional/securable_resource.rb +4 -0
- data/spec/tiny_server.rb +29 -10
- data/spec/unit/knife/bootstrap_spec.rb +10 -0
- data/spec/unit/provider/deploy/revision_spec.rb +2 -2
- data/spec/unit/provider/deploy_spec.rb +2 -2
- data/spec/unit/provider/directory_spec.rb +7 -4
- data/spec/unit/provider/file_spec.rb +4 -2
- data/spec/unit/provider/link_spec.rb +1 -1
- data/spec/unit/provider/remote_directory_spec.rb +4 -4
- metadata +846 -848
data/Rakefile
CHANGED
@@ -0,0 +1,65 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Stephen Delano (<stephen@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
# == FileUtils::Entry_ (Patch)
|
20
|
+
# On Ruby 1.9.3 and earlier, FileUtils.cp_r(foo, bar, :preserve => true) fails
|
21
|
+
# when attempting to copy a directory containing symlinks. This has been
|
22
|
+
# patched in the trunk of Ruby, and this is a monkey patch of the offending
|
23
|
+
# code.
|
24
|
+
|
25
|
+
unless RUBY_VERSION =~ /^2/
|
26
|
+
require 'fileutils'
|
27
|
+
|
28
|
+
class FileUtils::Entry_
|
29
|
+
def copy_metadata(path)
|
30
|
+
st = lstat()
|
31
|
+
if !st.symlink?
|
32
|
+
File.utime st.atime, st.mtime, path
|
33
|
+
end
|
34
|
+
begin
|
35
|
+
if st.symlink?
|
36
|
+
begin
|
37
|
+
File.lchown st.uid, st.gid, path
|
38
|
+
rescue NotImplementedError
|
39
|
+
end
|
40
|
+
else
|
41
|
+
File.chown st.uid, st.gid, path
|
42
|
+
end
|
43
|
+
rescue Errno::EPERM
|
44
|
+
# clear setuid/setgid
|
45
|
+
if st.symlink?
|
46
|
+
begin
|
47
|
+
File.lchmod st.mode & 01777, path
|
48
|
+
rescue NotImplementedError
|
49
|
+
end
|
50
|
+
else
|
51
|
+
File.chmod st.mode & 01777, path
|
52
|
+
end
|
53
|
+
else
|
54
|
+
if st.symlink?
|
55
|
+
begin
|
56
|
+
File.lchmod st.mode, path
|
57
|
+
rescue NotImplementedError
|
58
|
+
end
|
59
|
+
else
|
60
|
+
File.chmod st.mode, path
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/chef/provider/deploy.rb
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
|
19
19
|
require "chef/mixin/command"
|
20
20
|
require "chef/mixin/from_file"
|
21
|
+
require "chef/monkey_patches/fileutils"
|
21
22
|
require "chef/provider/git"
|
22
23
|
require "chef/provider/subversion"
|
23
24
|
|
@@ -262,7 +263,7 @@ class Chef
|
|
262
263
|
target_dir_path = @new_resource.deploy_to + "/releases"
|
263
264
|
converge_by("deploy from repo to #{@target_dir_path} ") do
|
264
265
|
FileUtils.mkdir_p(target_dir_path)
|
265
|
-
|
266
|
+
FileUtils.cp_r(::File.join(@new_resource.destination, "."), release_path, :preserve => true)
|
266
267
|
Chef::Log.info "#{@new_resource} copied the cached checkout to #{release_path}"
|
267
268
|
release_created(release_path)
|
268
269
|
end
|
@@ -61,7 +61,7 @@ class Chef
|
|
61
61
|
description << diff_current(rendered_template.path)
|
62
62
|
converge_by(description) do
|
63
63
|
backup
|
64
|
-
FileUtils.
|
64
|
+
FileUtils.cp(rendered_template.path, @new_resource.path)
|
65
65
|
Chef::Log.info("#{@new_resource} updated content")
|
66
66
|
access_controls.set_all!
|
67
67
|
stat = ::File.stat(@new_resource.path)
|
data/lib/chef/version.rb
CHANGED
Binary file
|
@@ -6,9 +6,9 @@
|
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
8
8
|
# You may obtain a copy of the License at
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# Unless required by applicable law or agreed to in writing, software
|
13
13
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
14
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -23,8 +23,6 @@ describe Chef::Knife::Exec do
|
|
23
23
|
before(:all) do
|
24
24
|
@original_config = Chef::Config.hash_dup
|
25
25
|
|
26
|
-
Thin::Logging.silent = false
|
27
|
-
|
28
26
|
@server = TinyServer::Manager.new#(:debug => true)
|
29
27
|
@server.start
|
30
28
|
end
|
@@ -24,7 +24,13 @@ describe Chef::Resource::CookbookFile do
|
|
24
24
|
let(:file_base) { 'cookbook_file_spec' }
|
25
25
|
let(:source) { 'java.response' }
|
26
26
|
let(:cookbook_name) { 'java' }
|
27
|
-
let(:expected_content)
|
27
|
+
let(:expected_content) do
|
28
|
+
content = File.open(File.join(CHEF_SPEC_DATA, 'cookbooks', 'java', 'files', 'default', 'java.response'), "rb") do |f|
|
29
|
+
f.read
|
30
|
+
end
|
31
|
+
content.force_encoding(Encoding::BINARY) if content.respond_to?(:force_encoding)
|
32
|
+
content
|
33
|
+
end
|
28
34
|
|
29
35
|
def create_resource
|
30
36
|
# set up cookbook collection for this run to use, based on our
|
@@ -69,16 +69,20 @@ describe Chef::Resource::DeployRevision, :unix_only => true do
|
|
69
69
|
|
70
70
|
let(:git_bundle_with_in_repo_callbacks) { File.expand_path("git_bundles/sinatra-test-app-with-callback-files.gitbundle", CHEF_SPEC_DATA) }
|
71
71
|
|
72
|
+
let(:git_bundle_with_in_repo_symlinks) { File.expand_path("git_bundles/sinatra-test-app-with-symlinks.gitbundle", CHEF_SPEC_DATA) }
|
73
|
+
|
72
74
|
# This is the fourth version
|
73
75
|
let(:latest_rev) { "3eb5ca6c353c83d9179dd3b29347539829b401f3" }
|
74
76
|
|
75
77
|
# This is the third version
|
76
78
|
let(:previous_rev) { "6d19a6dbecc8e37f5b2277345885c0c783eb8fb1" }
|
77
79
|
|
78
|
-
|
79
80
|
# This is the sixth version, it is on the "with-deploy-scripts" branch
|
80
81
|
let(:rev_with_in_repo_callbacks) { "2404d015882659754bdb93ad6e4b4d3d02691a82" }
|
81
82
|
|
83
|
+
# This is the fifth version in the "with-symlinks" branch
|
84
|
+
let(:rev_with_in_repo_symlinks) { "5a4748c52aaea8250b4346a9b8ede95ee3755e28" }
|
85
|
+
|
82
86
|
# Read values from the +observe_order_file+ and split each line. This way you
|
83
87
|
# can see in which order things really happened.
|
84
88
|
def actual_operations_order
|
@@ -494,6 +498,18 @@ describe Chef::Resource::DeployRevision, :unix_only => true do
|
|
494
498
|
end
|
495
499
|
end
|
496
500
|
|
501
|
+
context "when deploying an app with in-repo symlinks" do
|
502
|
+
let(:deploy_with_in_repo_symlinks) do
|
503
|
+
basic_deploy_resource.dup.tap do |r|
|
504
|
+
r.repo git_bundle_with_in_repo_symlinks
|
505
|
+
r.revision rev_with_in_repo_symlinks
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
it "should not raise an exception calling File.utime on symlinks" do
|
510
|
+
lambda { deploy_with_in_repo_symlinks.run_action(:deploy) }.should_not raise_error
|
511
|
+
end
|
512
|
+
end
|
497
513
|
end
|
498
514
|
|
499
515
|
|
@@ -24,7 +24,13 @@ describe Chef::Resource::RemoteFile do
|
|
24
24
|
|
25
25
|
let(:file_base) { "remote_file_spec" }
|
26
26
|
let(:source) { 'http://localhost:9000/nyan_cat.png' }
|
27
|
-
let(:expected_content)
|
27
|
+
let(:expected_content) do
|
28
|
+
content = File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png'), "rb") do |f|
|
29
|
+
f.read
|
30
|
+
end
|
31
|
+
content.force_encoding(Encoding::BINARY) if content.respond_to?(:force_encoding)
|
32
|
+
content
|
33
|
+
end
|
28
34
|
|
29
35
|
def create_resource
|
30
36
|
node = Chef::Node.new
|
@@ -40,13 +46,14 @@ describe Chef::Resource::RemoteFile do
|
|
40
46
|
end
|
41
47
|
|
42
48
|
before(:all) do
|
43
|
-
Thin::Logging.silent = false
|
44
49
|
@server = TinyServer::Manager.new
|
45
50
|
@server.start
|
46
51
|
@api = TinyServer::API.instance
|
47
52
|
@api.clear
|
48
53
|
@api.get("/nyan_cat.png", 200) {
|
49
|
-
|
54
|
+
File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png'), "rb") do |f|
|
55
|
+
f.read
|
56
|
+
end
|
50
57
|
}
|
51
58
|
end
|
52
59
|
|
@@ -37,15 +37,16 @@ describe TinyServer::API do
|
|
37
37
|
|
38
38
|
it "creates a route for a GET request" do
|
39
39
|
@api.get('/foo/bar', 200, 'hello foobar')
|
40
|
-
|
41
|
-
response.
|
40
|
+
# WEBrick gives you the full URI with host, Thin only gave the part after scheme+host+port
|
41
|
+
response = @api.call("REQUEST_METHOD" => "GET", "REQUEST_URI" => 'http://localhost:1974/foo/bar')
|
42
|
+
response.should == [200, {'Content-Type' => 'application/json'}, [ 'hello foobar' ]]
|
42
43
|
end
|
43
44
|
|
44
45
|
it "creates a route for a request with a block" do
|
45
46
|
block_called = false
|
46
47
|
@api.get('/bar/baz', 200) { block_called = true; 'hello barbaz' }
|
47
|
-
response = @api.call("REQUEST_METHOD" => "GET", "REQUEST_URI" => '/bar/baz')
|
48
|
-
response.should == [200, {'Content-Type' => 'application/json'}, 'hello barbaz']
|
48
|
+
response = @api.call("REQUEST_METHOD" => "GET", "REQUEST_URI" => 'http://localhost:1974/bar/baz')
|
49
|
+
response.should == [200, {'Content-Type' => 'application/json'}, [ 'hello barbaz' ]]
|
49
50
|
block_called.should be_true
|
50
51
|
end
|
51
52
|
|
data/spec/spec_helper.rb
CHANGED
@@ -66,11 +66,13 @@ RSpec.configure do |config|
|
|
66
66
|
|
67
67
|
# Add jruby filters here
|
68
68
|
config.filter_run_excluding :windows_only => true unless windows?
|
69
|
+
config.filter_run_excluding :not_supported_on_win2k3 => true if windows_win2k3?
|
69
70
|
config.filter_run_excluding :unix_only => true unless unix?
|
70
71
|
config.filter_run_excluding :ruby_18_only => true unless ruby_18?
|
71
72
|
config.filter_run_excluding :ruby_19_only => true unless ruby_19?
|
72
73
|
config.filter_run_excluding :requires_root => true unless ENV['USER'] == 'root'
|
73
74
|
config.filter_run_excluding :requires_unprivileged_user => true if ENV['USER'] == 'root'
|
75
|
+
config.filter_run_excluding :uses_diff => true unless has_diff?
|
74
76
|
|
75
77
|
config.run_all_when_everything_filtered = true
|
76
78
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
@@ -50,3 +50,16 @@ def make_tmpname(prefix_suffix, n)
|
|
50
50
|
path << "-#{n}" if n
|
51
51
|
path << suffix
|
52
52
|
end
|
53
|
+
|
54
|
+
# NOTE:
|
55
|
+
# This is a temporary fix to get tests passing on systems that have no `diff`
|
56
|
+
# until we can replace shelling out to `diff` with ruby diff-lcs
|
57
|
+
def has_diff?
|
58
|
+
begin
|
59
|
+
diff_cmd = Mixlib::ShellOut.new("diff -v")
|
60
|
+
diff_cmd.run_command
|
61
|
+
true
|
62
|
+
rescue Errno::ENOENT
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
@@ -10,6 +10,14 @@ def windows?
|
|
10
10
|
!!(RUBY_PLATFORM =~ /mswin|mingw|windows/)
|
11
11
|
end
|
12
12
|
|
13
|
+
def windows_win2k3?
|
14
|
+
return false unless windows?
|
15
|
+
require 'ruby-wmi'
|
16
|
+
|
17
|
+
host = WMI::Win32_OperatingSystem.find(:first)
|
18
|
+
(host.version && host.version.start_with?("5.2"))
|
19
|
+
end
|
20
|
+
|
13
21
|
# def jruby?
|
14
22
|
|
15
23
|
def unix?
|
@@ -78,6 +78,14 @@ shared_examples_for "a file resource" do
|
|
78
78
|
# note the stripping of the drive letter from the tmpdir on windows
|
79
79
|
let(:backup_glob) { File.join(CHEF_SPEC_BACKUP_PATH, Dir.tmpdir.sub(/^([A-Za-z]:)/, ""), "#{file_base}*") }
|
80
80
|
|
81
|
+
def binread(file)
|
82
|
+
content = File.open(file, "rb") do |f|
|
83
|
+
f.read
|
84
|
+
end
|
85
|
+
content.force_encoding(Encoding::BINARY) if "".respond_to?(:force_encoding)
|
86
|
+
content
|
87
|
+
end
|
88
|
+
|
81
89
|
context "when the target file does not exist" do
|
82
90
|
it "creates the file when the :create action is run" do
|
83
91
|
resource.run_action(:create)
|
@@ -86,12 +94,12 @@ shared_examples_for "a file resource" do
|
|
86
94
|
|
87
95
|
it "creates the file with the correct content when the :create action is run" do
|
88
96
|
resource.run_action(:create)
|
89
|
-
|
97
|
+
binread(path).should == expected_content
|
90
98
|
end
|
91
99
|
|
92
100
|
it "creates the file with the correct content when the :create_if_missing action is run" do
|
93
101
|
resource.run_action(:create_if_missing)
|
94
|
-
|
102
|
+
binread(path).should == expected_content
|
95
103
|
end
|
96
104
|
|
97
105
|
it "deletes the file when the :delete action is run" do
|
@@ -112,7 +120,7 @@ shared_examples_for "a file resource" do
|
|
112
120
|
|
113
121
|
context "when the target file has the wrong content" do
|
114
122
|
before(:each) do
|
115
|
-
File.open(path, "
|
123
|
+
File.open(path, "wb") { |f| f.print "This is so wrong!!!" }
|
116
124
|
@expected_mtime = File.stat(path).mtime
|
117
125
|
@expected_checksum = sha256_checksum(path)
|
118
126
|
end
|
@@ -136,7 +144,7 @@ shared_examples_for "a file resource" do
|
|
136
144
|
|
137
145
|
context "when the target file has the correct content" do
|
138
146
|
before(:each) do
|
139
|
-
File.open(path, "
|
147
|
+
File.open(path, "wb") { |f| f.print expected_content }
|
140
148
|
@expected_mtime = File.stat(path).mtime
|
141
149
|
@expected_atime = File.stat(path).atime
|
142
150
|
@expected_checksum = sha256_checksum(path)
|
@@ -29,12 +29,16 @@ shared_context "setup correct permissions" do
|
|
29
29
|
before :each do
|
30
30
|
File.chown(Etc.getpwnam('nobody').uid, 1337, path)
|
31
31
|
File.chmod(0776, path)
|
32
|
+
now = Time.now.to_i
|
33
|
+
File.utime(now - 9000, now - 9000, path)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
37
|
context "without root", :requires_unprivileged_user do
|
36
38
|
before :each do
|
37
39
|
File.chmod(0776, path)
|
40
|
+
now = Time.now.to_i
|
41
|
+
File.utime(now - 9000, now - 9000, path)
|
38
42
|
end
|
39
43
|
end
|
40
44
|
end
|
data/spec/tiny_server.rb
CHANGED
@@ -17,11 +17,13 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require 'rubygems'
|
20
|
+
require 'webrick'
|
20
21
|
require 'rack'
|
21
|
-
require 'thin'
|
22
|
+
#require 'thin'
|
22
23
|
require 'singleton'
|
23
24
|
require 'chef/json_compat'
|
24
25
|
require 'open-uri'
|
26
|
+
require 'chef/config'
|
25
27
|
|
26
28
|
module TinyServer
|
27
29
|
|
@@ -29,30 +31,42 @@ module TinyServer
|
|
29
31
|
|
30
32
|
attr_writer :app
|
31
33
|
|
32
|
-
def self.
|
34
|
+
def self.setup(options=nil, &block)
|
33
35
|
tiny_app = new(options)
|
34
36
|
app_code = Rack::Builder.new(&block).to_app
|
35
37
|
tiny_app.app = app_code
|
36
|
-
tiny_app
|
38
|
+
tiny_app
|
39
|
+
end
|
40
|
+
|
41
|
+
def shutdown
|
42
|
+
server.shutdown
|
37
43
|
end
|
38
44
|
end
|
39
45
|
|
40
46
|
class Manager
|
41
47
|
|
42
|
-
|
48
|
+
# 5 == debug, 3 == warning
|
49
|
+
LOGGER = WEBrick::Log.new(STDOUT, 3)
|
50
|
+
DEFAULT_OPTIONS = {
|
51
|
+
:server => 'webrick',
|
52
|
+
:Port => 9000,
|
53
|
+
:Host => 'localhost',
|
54
|
+
:environment => :none,
|
55
|
+
:Logger => LOGGER,
|
56
|
+
:AccessLog => [] # Remove this option to enable the access log when debugging.
|
57
|
+
}
|
43
58
|
|
44
59
|
def initialize(options=nil)
|
45
60
|
@options = options ? DEFAULT_OPTIONS.merge(options) : DEFAULT_OPTIONS
|
46
61
|
@creator = caller.first
|
47
|
-
|
48
|
-
Thin::Logging.silent = !@options[:debug]
|
49
62
|
end
|
50
63
|
|
51
64
|
def start
|
52
65
|
@server_thread = Thread.new do
|
53
|
-
@server = Server.
|
66
|
+
@server = Server.setup(@options) do
|
54
67
|
run API.instance
|
55
68
|
end
|
69
|
+
@server.start
|
56
70
|
end
|
57
71
|
block_until_started
|
58
72
|
end
|
@@ -63,7 +77,10 @@ module TinyServer
|
|
63
77
|
|
64
78
|
def block_until_started
|
65
79
|
200.times do
|
66
|
-
|
80
|
+
if started?
|
81
|
+
raise "ivar weirdness" if @server.nil?
|
82
|
+
return true
|
83
|
+
end
|
67
84
|
end
|
68
85
|
raise "TinyServer failed to boot :/"
|
69
86
|
end
|
@@ -84,6 +101,7 @@ module TinyServer
|
|
84
101
|
|
85
102
|
def stop
|
86
103
|
# yes, this is terrible.
|
104
|
+
@server.shutdown
|
87
105
|
@server_thread.kill
|
88
106
|
@server_thread.join
|
89
107
|
@server_thread = nil
|
@@ -132,7 +150,7 @@ module TinyServer
|
|
132
150
|
debug_info = {:message => "no data matches the request for #{env['REQUEST_URI']}",
|
133
151
|
:available_routes => @routes, :request => env}
|
134
152
|
# Uncomment me for glorious debugging
|
135
|
-
#pp :not_found => debug_info
|
153
|
+
# pp :not_found => debug_info
|
136
154
|
[404, {'Content-Type' => 'application/json'}, debug_info.to_json]
|
137
155
|
end
|
138
156
|
end
|
@@ -152,6 +170,7 @@ module TinyServer
|
|
152
170
|
end
|
153
171
|
|
154
172
|
def matches_request?(uri)
|
173
|
+
uri = URI.parse(uri).request_uri
|
155
174
|
@path_spec === uri
|
156
175
|
end
|
157
176
|
|
@@ -171,7 +190,7 @@ module TinyServer
|
|
171
190
|
|
172
191
|
def call
|
173
192
|
data = @data || @block.call
|
174
|
-
[@response_code, HEADERS, data]
|
193
|
+
[@response_code, HEADERS, Array(data)]
|
175
194
|
end
|
176
195
|
|
177
196
|
def to_s
|