chef 11.10.4 → 11.12.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +6 -6
- data/README.md +1 -1
- data/lib/chef/api_client.rb +1 -3
- data/lib/chef/application.rb +2 -1
- data/lib/chef/application/client.rb +11 -1
- data/lib/chef/client.rb +24 -9
- data/lib/chef/cookbook/syntax_check.rb +107 -6
- data/lib/chef/dsl/reboot_pending.rb +61 -0
- data/lib/chef/exceptions.rb +12 -1
- data/lib/chef/formatters/error_descriptor.rb +1 -1
- data/lib/chef/http/remote_request_id.rb +46 -0
- data/lib/chef/knife/bootstrap.rb +1 -1
- data/lib/chef/knife/bootstrap/README.md +12 -0
- data/lib/chef/knife/bootstrap/chef-full.erb +3 -0
- data/lib/chef/knife/client_create.rb +6 -0
- data/lib/chef/knife/client_delete.rb +15 -1
- data/lib/chef/knife/raw.rb +1 -0
- data/lib/chef/node.rb +1 -1
- data/lib/chef/node/attribute_collections.rb +8 -1
- data/lib/chef/node/immutable_collections.rb +8 -1
- data/lib/chef/provider/deploy.rb +1 -1
- data/lib/chef/provider/group.rb +1 -1
- data/lib/chef/provider/ifconfig/debian.rb +19 -8
- data/lib/chef/provider/ohai.rb +6 -5
- data/lib/chef/provider/service/macosx.rb +68 -14
- data/lib/chef/recipe.rb +2 -0
- data/lib/chef/request_id.rb +37 -0
- data/lib/chef/resource.rb +2 -0
- data/lib/chef/resource_reporter.rb +7 -4
- data/lib/chef/rest.rb +5 -1
- data/lib/chef/run_status.rb +4 -1
- data/lib/chef/server_api.rb +3 -1
- data/lib/chef/version.rb +2 -2
- data/spec/functional/dsl/reboot_pending_spec.rb +118 -0
- data/spec/functional/resource/base.rb +1 -3
- data/spec/functional/resource/deploy_revision_spec.rb +192 -1
- data/spec/functional/resource/git_spec.rb +1 -1
- data/spec/functional/resource/ohai_spec.rb +65 -0
- data/spec/functional/resource/registry_spec.rb +4 -5
- data/spec/integration/client/client_spec.rb +14 -0
- data/spec/spec_helper.rb +1 -2
- data/spec/support/shared/functional/windows_script.rb +1 -2
- data/spec/unit/api_client_spec.rb +46 -0
- data/spec/unit/client_spec.rb +345 -229
- data/spec/unit/cookbook/syntax_check_spec.rb +0 -1
- data/spec/unit/dsl/reboot_pending_spec.rb +100 -0
- data/spec/unit/knife/client_create_spec.rb +29 -1
- data/spec/unit/knife/client_delete_spec.rb +44 -1
- data/spec/unit/knife_spec.rb +55 -0
- data/spec/unit/node/attribute_spec.rb +7 -0
- data/spec/unit/node/immutable_collections_spec.rb +5 -1
- data/spec/unit/provider/group_spec.rb +5 -0
- data/spec/unit/provider/ifconfig/debian_spec.rb +251 -24
- data/spec/unit/provider/ohai_spec.rb +2 -3
- data/spec/unit/provider/service/macosx_spec.rb +29 -11
- data/spec/unit/resource_reporter_spec.rb +1 -1
- data/spec/unit/rest_spec.rb +38 -13
- metadata +151 -194
@@ -0,0 +1,46 @@
|
|
1
|
+
# Author:: Prajakta Purohit (<prajakta@opscode.com>)
|
2
|
+
# Copyright:: Copyright (c) 2009, 2010, 2013, 2014 Opscode, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef/request_id'
|
19
|
+
|
20
|
+
class Chef
|
21
|
+
class HTTP
|
22
|
+
class RemoteRequestID
|
23
|
+
|
24
|
+
def initialize(opts={})
|
25
|
+
end
|
26
|
+
|
27
|
+
def handle_request(method, url, headers={}, data=false)
|
28
|
+
headers.merge!({'X-REMOTE-REQUEST-ID' => Chef::RequestID.instance.request_id})
|
29
|
+
[method, url, headers, data]
|
30
|
+
end
|
31
|
+
|
32
|
+
def handle_response(http_response, rest_request, return_value)
|
33
|
+
[http_response, rest_request, return_value]
|
34
|
+
end
|
35
|
+
|
36
|
+
def stream_response_handler(response)
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def handle_stream_complete(http_response, rest_request, return_value)
|
41
|
+
[http_response, rest_request, return_value]
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/chef/knife/bootstrap.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
This directory contains bootstrap templates which can be used with the -d flag
|
2
|
+
to 'knife bootstrap' to install Chef in different ways. To simplify installation,
|
3
|
+
and reduce the matrix of common installation patterns to support, we have
|
4
|
+
standardized on the [Omnibus](https://github.com/opscode/omnibus-ruby) built installation
|
5
|
+
packages.
|
6
|
+
|
7
|
+
The 'chef-full' template downloads a script which is used to determine the correct
|
8
|
+
Omnibus package for this system from the [Omnitruck](https://github.com/opscode/opscode-omnitruck) API. All other templates in this directory are deprecated and will be removed
|
9
|
+
in the future.
|
10
|
+
|
11
|
+
You can still utilize custom bootstrap templates on your system if your installation
|
12
|
+
needs are unique. Additional information can be found on the [docs site](http://docs.opscode.com/knife_bootstrap.html#custom-templates).
|
@@ -23,6 +23,7 @@ install_sh="https://www.opscode.com/chef/install.sh"
|
|
23
23
|
version_string="-v <%= chef_version %>"
|
24
24
|
|
25
25
|
if ! exists /usr/bin/chef-client; then
|
26
|
+
echo "Installing Chef Client..."
|
26
27
|
if exists wget; then
|
27
28
|
bash <(wget <%= "--proxy=on " if knife_config[:bootstrap_proxy] %> ${install_sh} -O -) ${version_string}
|
28
29
|
elif exists curl; then
|
@@ -66,4 +67,6 @@ cat > /etc/chef/first-boot.json <<'EOP'
|
|
66
67
|
<%= first_boot.to_json %>
|
67
68
|
EOP
|
68
69
|
|
70
|
+
echo "Starting first Chef Client run..."
|
71
|
+
|
69
72
|
<%= start_chef %>'
|
@@ -38,6 +38,11 @@ class Chef
|
|
38
38
|
:description => "Create the client as an admin",
|
39
39
|
:boolean => true
|
40
40
|
|
41
|
+
option :validator,
|
42
|
+
:long => "--validator",
|
43
|
+
:description => "Create the client as a validator",
|
44
|
+
:boolean => true
|
45
|
+
|
41
46
|
banner "knife client create CLIENT (options)"
|
42
47
|
|
43
48
|
def run
|
@@ -52,6 +57,7 @@ class Chef
|
|
52
57
|
client = Chef::ApiClient.new
|
53
58
|
client.name(@client_name)
|
54
59
|
client.admin(config[:admin])
|
60
|
+
client.validator(config[:validator])
|
55
61
|
|
56
62
|
output = edit_data(client)
|
57
63
|
|
@@ -27,6 +27,11 @@ class Chef
|
|
27
27
|
require 'chef/json_compat'
|
28
28
|
end
|
29
29
|
|
30
|
+
option :force,
|
31
|
+
:short => "-f",
|
32
|
+
:long => "--force",
|
33
|
+
:description => "Force deletion of client if it's a validator"
|
34
|
+
|
30
35
|
banner "knife client delete CLIENT (options)"
|
31
36
|
|
32
37
|
def run
|
@@ -38,7 +43,16 @@ class Chef
|
|
38
43
|
exit 1
|
39
44
|
end
|
40
45
|
|
41
|
-
delete_object(Chef::ApiClient, @client_name)
|
46
|
+
delete_object(Chef::ApiClient, @client_name, 'client') {
|
47
|
+
object = Chef::ApiClient.load(@client_name)
|
48
|
+
if object.validator
|
49
|
+
unless config[:force]
|
50
|
+
ui.fatal("You must specify --force to delete the validator client #{@client_name}")
|
51
|
+
exit 2
|
52
|
+
end
|
53
|
+
end
|
54
|
+
object.destroy
|
55
|
+
}
|
42
56
|
end
|
43
57
|
|
44
58
|
end
|
data/lib/chef/knife/raw.rb
CHANGED
data/lib/chef/node.rb
CHANGED
@@ -312,7 +312,7 @@ class Chef
|
|
312
312
|
if attrs.key?("recipes") || attrs.key?("run_list")
|
313
313
|
raise Chef::Exceptions::AmbiguousRunlistSpecification, "please set the node's run list using the 'run_list' attribute only."
|
314
314
|
end
|
315
|
-
Chef::Log.info("Setting the run_list to #{new_run_list.inspect} from
|
315
|
+
Chef::Log.info("Setting the run_list to #{new_run_list.inspect} from CLI options")
|
316
316
|
run_list(new_run_list)
|
317
317
|
end
|
318
318
|
attrs
|
data/lib/chef/provider/deploy.rb
CHANGED
@@ -266,7 +266,7 @@ class Chef
|
|
266
266
|
|
267
267
|
def copy_cached_repo
|
268
268
|
target_dir_path = @new_resource.deploy_to + "/releases"
|
269
|
-
converge_by("deploy from repo to #{
|
269
|
+
converge_by("deploy from repo to #{target_dir_path} ") do
|
270
270
|
FileUtils.rm_rf(release_path) if ::File.exist?(release_path)
|
271
271
|
FileUtils.mkdir_p(target_dir_path)
|
272
272
|
FileUtils.cp_r(::File.join(@new_resource.destination, "."), release_path, :preserve => true)
|
data/lib/chef/provider/group.rb
CHANGED
@@ -84,7 +84,7 @@ class Chef
|
|
84
84
|
# <false>:: If a change is not required
|
85
85
|
def compare_group
|
86
86
|
@change_desc = [ ]
|
87
|
-
if @new_resource.gid
|
87
|
+
if @new_resource.gid.to_s != @current_resource.gid.to_s
|
88
88
|
@change_desc << "change gid #{@current_resource.gid} to #{@new_resource.gid}"
|
89
89
|
end
|
90
90
|
|
@@ -24,6 +24,9 @@ class Chef
|
|
24
24
|
class Ifconfig
|
25
25
|
class Debian < Chef::Provider::Ifconfig
|
26
26
|
|
27
|
+
INTERFACES_FILE = "/etc/network/interfaces"
|
28
|
+
INTERFACES_DOT_D_DIR = "/etc/network/interfaces.d"
|
29
|
+
|
27
30
|
def initialize(new_resource, run_context)
|
28
31
|
super(new_resource, run_context)
|
29
32
|
@config_template = %{
|
@@ -46,22 +49,30 @@ iface <%= @new_resource.device %> inet static
|
|
46
49
|
<% end %>
|
47
50
|
<% end %>
|
48
51
|
}
|
49
|
-
@config_path = "/
|
52
|
+
@config_path = "#{INTERFACES_DOT_D_DIR}/ifcfg-#{@new_resource.device}"
|
50
53
|
end
|
51
54
|
|
52
55
|
def generate_config
|
53
|
-
|
56
|
+
enforce_interfaces_dot_d_sanity
|
54
57
|
super
|
55
58
|
end
|
56
59
|
|
57
60
|
protected
|
58
61
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
def enforce_interfaces_dot_d_sanity
|
63
|
+
# create /etc/network/interfaces.d via dir resource (to get reporting, etc)
|
64
|
+
dir = Chef::Resource::Directory.new(INTERFACES_DOT_D_DIR, run_context)
|
65
|
+
dir.run_action(:create)
|
66
|
+
new_resource.updated_by_last_action(true) if dir.updated_by_last_action?
|
67
|
+
# roll our own file_edit resource, this will not get reported until we have a file_edit resource
|
68
|
+
interfaces_dot_d_for_regexp = INTERFACES_DOT_D_DIR.gsub(/\./, '\.') # escape dots for the regexp
|
69
|
+
regexp = %r{^\s*source\s+#{interfaces_dot_d_for_regexp}/\*\s*$}
|
70
|
+
unless ::File.exists?(INTERFACES_FILE) && regexp.match(IO.read(INTERFACES_FILE))
|
71
|
+
converge_by("modifying #{INTERFACES_FILE} to source #{INTERFACES_DOT_D_DIR}") do
|
72
|
+
conf = Chef::Util::FileEdit.new(INTERFACES_FILE)
|
73
|
+
conf.insert_line_if_no_match(regexp, "source #{INTERFACES_DOT_D_DIR}/*")
|
74
|
+
conf.write_file
|
75
|
+
end
|
65
76
|
end
|
66
77
|
end
|
67
78
|
|
data/lib/chef/provider/ohai.rb
CHANGED
@@ -33,11 +33,12 @@ class Chef
|
|
33
33
|
def action_reload
|
34
34
|
converge_by("re-run ohai and merge results into node attributes") do
|
35
35
|
ohai = ::Ohai::System.new
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
|
37
|
+
# If @new_resource.plugin is nil, ohai will reload all the plugins
|
38
|
+
# Otherwise it will only reload the specified plugin
|
39
|
+
# Note that any changes to plugins, or new plugins placed on
|
40
|
+
# the path are picked up by ohai.
|
41
|
+
ohai.all_plugins @new_resource.plugin
|
41
42
|
node.automatic_attrs.merge! ohai.data
|
42
43
|
Chef::Log.info("#{@new_resource} reloaded")
|
43
44
|
end
|
@@ -17,6 +17,7 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require 'chef/provider/service'
|
20
|
+
require 'rexml/document'
|
20
21
|
|
21
22
|
class Chef
|
22
23
|
class Provider
|
@@ -41,6 +42,7 @@ class Chef
|
|
41
42
|
@current_resource.service_name(@new_resource.service_name)
|
42
43
|
@plist_size = 0
|
43
44
|
@plist = find_service_plist
|
45
|
+
@service_label = find_service_label
|
44
46
|
set_service_status
|
45
47
|
|
46
48
|
@current_resource
|
@@ -48,14 +50,6 @@ class Chef
|
|
48
50
|
|
49
51
|
def define_resource_requirements
|
50
52
|
#super
|
51
|
-
requirements.assert(:enable) do |a|
|
52
|
-
a.failure_message Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :enable"
|
53
|
-
end
|
54
|
-
|
55
|
-
requirements.assert(:disable) do |a|
|
56
|
-
a.failure_message Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :disable"
|
57
|
-
end
|
58
|
-
|
59
53
|
requirements.assert(:reload) do |a|
|
60
54
|
a.failure_message Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :reload"
|
61
55
|
end
|
@@ -65,6 +59,12 @@ class Chef
|
|
65
59
|
a.failure_message Chef::Exceptions::Service, "Several plist files match service name. Please use full service name."
|
66
60
|
end
|
67
61
|
|
62
|
+
requirements.assert(:all_actions) do |a|
|
63
|
+
a.assertion { !@service_label.to_s.empty? }
|
64
|
+
a.failure_message Chef::Exceptions::Service,
|
65
|
+
"Could not find service's label in plist file '#{@plist}'!"
|
66
|
+
end
|
67
|
+
|
68
68
|
requirements.assert(:all_actions) do |a|
|
69
69
|
a.assertion { @plist_size > 0 }
|
70
70
|
# No failrue here in original code - so we also will not
|
@@ -74,7 +74,6 @@ class Chef
|
|
74
74
|
@current_resource.running(false)
|
75
75
|
end
|
76
76
|
end
|
77
|
-
|
78
77
|
end
|
79
78
|
|
80
79
|
def start_service
|
@@ -111,19 +110,56 @@ class Chef
|
|
111
110
|
end
|
112
111
|
end
|
113
112
|
|
113
|
+
# On OS/X, enabling a service has the side-effect of starting it,
|
114
|
+
# and disabling a service has the side-effect of stopping it.
|
115
|
+
#
|
116
|
+
# This makes some sense on OS/X since launchctl is an "init"-style
|
117
|
+
# supervisor that will restart daemons that are crashing, etc.
|
118
|
+
def enable_service
|
119
|
+
if @current_resource.enabled
|
120
|
+
Chef::Log.debug("#{@new_resource} already enabled, not enabling")
|
121
|
+
else
|
122
|
+
shell_out!(
|
123
|
+
"launchctl load -w '#{@plist}'",
|
124
|
+
:user => @owner_uid, :group => @owner_gid
|
125
|
+
)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def disable_service
|
130
|
+
unless @current_resource.enabled
|
131
|
+
Chef::Log.debug("#{@new_resource} not enabled, not disabling")
|
132
|
+
else
|
133
|
+
shell_out!(
|
134
|
+
"launchctl unload -w '#{@plist}'",
|
135
|
+
:user => @owner_uid, :group => @owner_gid
|
136
|
+
)
|
137
|
+
end
|
138
|
+
end
|
114
139
|
|
115
140
|
def set_service_status
|
116
|
-
return if @plist == nil
|
141
|
+
return if @plist == nil or @service_label.to_s.empty?
|
117
142
|
|
118
|
-
|
143
|
+
cmd = shell_out(
|
144
|
+
"launchctl list #{@service_label}",
|
145
|
+
:user => @owner_uid, :group => @owner_gid
|
146
|
+
)
|
147
|
+
|
148
|
+
if cmd.exitstatus == 0
|
149
|
+
@current_resource.enabled(true)
|
150
|
+
else
|
151
|
+
@current_resource.enabled(false)
|
152
|
+
end
|
119
153
|
|
120
154
|
if @current_resource.enabled
|
121
155
|
@owner_uid = ::File.stat(@plist).uid
|
122
156
|
@owner_gid = ::File.stat(@plist).gid
|
123
157
|
|
124
|
-
shell_out!(
|
158
|
+
shell_out!(
|
159
|
+
"launchctl list", :user => @owner_uid, :group => @owner_gid
|
160
|
+
).stdout.each_line do |line|
|
125
161
|
case line
|
126
|
-
when /(\d+|-)\s+(?:\d+|-)\s+(.*\.?)#{@
|
162
|
+
when /(\d+|-)\s+(?:\d+|-)\s+(.*\.?)#{@service_label}/
|
127
163
|
pid = $1
|
128
164
|
@current_resource.running(!pid.to_i.zero?)
|
129
165
|
end
|
@@ -135,9 +171,27 @@ class Chef
|
|
135
171
|
|
136
172
|
private
|
137
173
|
|
174
|
+
def find_service_label
|
175
|
+
# Most services have the same internal label as the name of the
|
176
|
+
# plist file. However, there is no rule saying that *has* to be
|
177
|
+
# the case, and some core services (notably, ssh) do not follow
|
178
|
+
# this rule.
|
179
|
+
|
180
|
+
# plist files can come in XML or Binary formats. this command
|
181
|
+
# will make sure we get XML every time.
|
182
|
+
plist_xml = shell_out!("plutil -convert xml1 -o - #{@plist}").stdout
|
183
|
+
|
184
|
+
plist_doc = REXML::Document.new(plist_xml)
|
185
|
+
plist_doc.elements[
|
186
|
+
"/plist/dict/key[text()='Label']/following::string[1]/text()"]
|
187
|
+
end
|
188
|
+
|
138
189
|
def find_service_plist
|
139
190
|
plists = PLIST_DIRS.inject([]) do |results, dir|
|
140
|
-
|
191
|
+
edir = ::File.expand_path(dir)
|
192
|
+
entries = Dir.glob(
|
193
|
+
"#{edir}/*#{@current_resource.service_name}*.plist"
|
194
|
+
)
|
141
195
|
entries.any? ? results << entries : results
|
142
196
|
end
|
143
197
|
plists.flatten!
|
data/lib/chef/recipe.rb
CHANGED
@@ -23,6 +23,7 @@ require 'chef/dsl/data_query'
|
|
23
23
|
require 'chef/dsl/platform_introspection'
|
24
24
|
require 'chef/dsl/include_recipe'
|
25
25
|
require 'chef/dsl/registry_helper'
|
26
|
+
require 'chef/dsl/reboot_pending'
|
26
27
|
|
27
28
|
require 'chef/mixin/from_file'
|
28
29
|
|
@@ -38,6 +39,7 @@ class Chef
|
|
38
39
|
include Chef::DSL::IncludeRecipe
|
39
40
|
include Chef::DSL::Recipe
|
40
41
|
include Chef::DSL::RegistryHelper
|
42
|
+
include Chef::DSL::RebootPending
|
41
43
|
|
42
44
|
include Chef::Mixin::FromFile
|
43
45
|
include Chef::Mixin::Deprecation
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Author:: Prajakta Purohit (<prajakta@opscode.com>)
|
2
|
+
# Copyright:: Copyright (c) 2009, 2010, 2013, 2014 Opscode, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef/monkey_patches/securerandom'
|
19
|
+
require 'singleton'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class RequestID
|
23
|
+
include Singleton
|
24
|
+
|
25
|
+
def reset_request_id
|
26
|
+
@request_id = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def request_id
|
30
|
+
@request_id ||= generate_request_id
|
31
|
+
end
|
32
|
+
|
33
|
+
def generate_request_id
|
34
|
+
SecureRandom.uuid
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|