chef 12.5.1-universal-mingw32 → 12.6.0-universal-mingw32
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.
- checksums.yaml +4 -4
- data/Gemfile +6 -1
- data/README.md +6 -4
- data/Rakefile +1 -4
- data/chef-windows.gemspec +21 -0
- data/chef.gemspec +58 -0
- data/lib/chef/api_client/registration.rb +9 -4
- data/lib/chef/application.rb +3 -84
- data/lib/chef/application/apply.rb +9 -2
- data/lib/chef/application/client.rb +8 -3
- data/lib/chef/application/solo.rb +7 -1
- data/lib/chef/application/windows_service.rb +21 -6
- data/lib/chef/application/windows_service_manager.rb +2 -3
- data/lib/chef/audit/runner.rb +1 -0
- data/lib/chef/chef_class.rb +1 -11
- data/lib/chef/chef_fs/chef_fs_data_store.rb +181 -2
- data/lib/chef/chef_fs/file_system/cookbook_subdir.rb +5 -0
- data/lib/chef/chef_fs/file_system/file_system_entry.rb +11 -7
- data/lib/chef/client.rb +28 -1
- data/lib/chef/cookbook/cookbook_collection.rb +14 -1
- data/lib/chef/cookbook/cookbook_version_loader.rb +1 -1
- data/lib/chef/cookbook/metadata.rb +115 -9
- data/lib/chef/cookbook/remote_file_vendor.rb +1 -1
- data/lib/chef/cookbook_version.rb +6 -2
- data/lib/chef/data_bag.rb +1 -1
- data/lib/chef/data_bag_item.rb +1 -1
- data/lib/chef/digester.rb +5 -1
- data/lib/chef/dsl/chef_provisioning.rb +57 -0
- data/lib/chef/dsl/cheffish.rb +64 -0
- data/lib/chef/dsl/declare_resource.rb +108 -0
- data/lib/chef/dsl/platform_introspection.rb +3 -3
- data/lib/chef/dsl/recipe.rb +3 -73
- data/lib/chef/dsl/resources.rb +27 -1
- data/lib/chef/event_dispatch/base.rb +3 -0
- data/lib/chef/event_dispatch/dispatcher.rb +5 -0
- data/lib/chef/event_dispatch/events_output_stream.rb +8 -0
- data/lib/chef/exceptions.rb +21 -1
- data/lib/chef/file_access_control/unix.rb +12 -12
- data/lib/chef/file_content_management/deploy/cp.rb +2 -2
- data/lib/chef/file_content_management/deploy/mv_unix.rb +4 -4
- data/lib/chef/file_content_management/deploy/mv_windows.rb +1 -1
- data/lib/chef/formatters/base.rb +7 -0
- data/lib/chef/formatters/error_inspectors/compile_error_inspector.rb +2 -2
- data/lib/chef/formatters/indentable_output_stream.rb +5 -0
- data/lib/chef/http.rb +19 -3
- data/lib/chef/http/decompressor.rb +2 -2
- data/lib/chef/json_compat.rb +1 -0
- data/lib/chef/knife.rb +16 -2
- data/lib/chef/knife/bootstrap.rb +55 -10
- data/lib/chef/knife/cookbook_site_install.rb +5 -1
- data/lib/chef/knife/core/bootstrap_context.rb +2 -1
- data/lib/chef/knife/core/node_presenter.rb +1 -1
- data/lib/chef/knife/ssh.rb +30 -16
- data/lib/chef/knife/ssl_check.rb +4 -2
- data/lib/chef/knife/ssl_fetch.rb +3 -2
- data/lib/chef/knife/status.rb +14 -1
- data/lib/chef/log.rb +14 -0
- data/lib/chef/mixin/get_source_from_package.rb +7 -2
- data/lib/chef/mixin/properties.rb +302 -0
- data/lib/chef/mixin/proxified_socket.rb +38 -0
- data/lib/chef/mixin/subclass_directive.rb +37 -0
- data/lib/chef/node.rb +13 -5
- data/lib/chef/platform/query_helpers.rb +14 -3
- data/lib/chef/platform/service_helpers.rb +20 -38
- data/lib/chef/policy_builder/expand_node_object.rb +3 -0
- data/lib/chef/policy_builder/policyfile.rb +1 -0
- data/lib/chef/property.rb +51 -12
- data/lib/chef/provider.rb +40 -35
- data/lib/chef/provider/deploy.rb +1 -1
- data/lib/chef/provider/dsc_resource.rb +54 -20
- data/lib/chef/provider/execute.rb +25 -4
- data/lib/chef/provider/group.rb +1 -1
- data/lib/chef/provider/lwrp_base.rb +1 -0
- data/lib/chef/provider/package.rb +76 -30
- data/lib/chef/provider/package/dpkg.rb +152 -69
- data/lib/chef/provider/package/openbsd.rb +6 -8
- data/lib/chef/provider/package/solaris.rb +2 -0
- data/lib/chef/provider/package/windows.rb +95 -14
- data/lib/chef/provider/package/windows/exe.rb +129 -0
- data/lib/chef/provider/package/windows/msi.rb +37 -13
- data/lib/chef/provider/package/windows/registry_uninstall_entry.rb +89 -0
- data/lib/chef/provider/package/yum.rb +13 -3
- data/lib/chef/provider/powershell_script.rb +3 -0
- data/lib/chef/provider/remote_file/cache_control_data.rb +37 -4
- data/lib/chef/provider/remote_file/http.rb +1 -1
- data/lib/chef/provider/script.rb +1 -0
- data/lib/chef/provider/service.rb +13 -10
- data/lib/chef/provider/service/solaris.rb +43 -17
- data/lib/chef/provider/service/upstart.rb +3 -3
- data/lib/chef/provider/user.rb +1 -1
- data/lib/chef/provider/user/dscl.rb +111 -100
- data/lib/chef/provider/user/windows.rb +5 -3
- data/lib/chef/recipe.rb +3 -5
- data/lib/chef/resource.rb +77 -320
- data/lib/chef/resource/action_class.rb +4 -0
- data/lib/chef/resource/dpkg_package.rb +4 -3
- data/lib/chef/resource/dsc_resource.rb +40 -2
- data/lib/chef/resource/execute.rb +9 -1
- data/lib/chef/resource/ksh.rb +32 -0
- data/lib/chef/resource/lwrp_base.rb +6 -10
- data/lib/chef/resource/package.rb +8 -9
- data/lib/chef/resource/registry_key.rb +1 -1
- data/lib/chef/resource/resource_notification.rb +14 -1
- data/lib/chef/resource/script.rb +1 -1
- data/lib/chef/resource/windows_package.rb +1 -1
- data/lib/chef/resource_builder.rb +14 -7
- data/lib/chef/resource_reporter.rb +6 -0
- data/lib/chef/resources.rb +1 -7
- data/lib/chef/rest.rb +1 -1
- data/lib/chef/run_context.rb +45 -2
- data/lib/chef/run_list/run_list_expansion.rb +47 -0
- data/lib/chef/runner.rb +25 -0
- data/lib/chef/search/query.rb +16 -2
- data/lib/chef/util/diff.rb +2 -2
- data/lib/chef/util/powershell/ps_credential.rb +2 -3
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api/file.rb +51 -1
- data/lib/chef/win32/file.rb +5 -0
- data/lib/chef/win32/file/version_info.rb +93 -0
- data/lib/chef/win32/mutex.rb +1 -1
- data/spec/data/apt/chef-integration-test2-1.0/debian/changelog +5 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.debhelper.log +45 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.substvars +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/conffiles +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/control +10 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/md5sums +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/compat +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/conffiles +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/control +13 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/copyright +34 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/files +1 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/rules +13 -0
- data/spec/data/apt/chef-integration-test2-1.0/debian/source/format +1 -0
- data/spec/data/apt/chef-integration-test2_1.0-1.debian.tar.gz +0 -0
- data/spec/data/apt/chef-integration-test2_1.0-1.dsc +18 -0
- data/spec/data/apt/chef-integration-test2_1.0-1_amd64.build +91 -0
- data/spec/data/apt/chef-integration-test2_1.0-1_amd64.changes +31 -0
- data/spec/data/apt/chef-integration-test2_1.0-1_amd64.deb +0 -0
- data/spec/data/apt/chef-integration-test2_1.0.orig.tar.gz +0 -0
- data/spec/functional/application_spec.rb +1 -1
- data/spec/functional/audit/runner_spec.rb +4 -0
- data/spec/functional/knife/ssh_spec.rb +5 -5
- data/spec/functional/notifications_spec.rb +74 -4
- data/spec/functional/resource/aix_service_spec.rb +2 -2
- data/spec/functional/resource/dpkg_package_spec.rb +339 -0
- data/spec/functional/resource/ifconfig_spec.rb +3 -1
- data/spec/functional/resource/mount_spec.rb +5 -2
- data/spec/functional/resource/package_spec.rb +1 -1
- data/spec/functional/resource/user/windows_spec.rb +8 -0
- data/spec/functional/resource/windows_package_spec.rb +177 -0
- data/spec/functional/win32/version_info_spec.rb +50 -0
- data/spec/integration/client/client_spec.rb +80 -0
- data/spec/integration/knife/download_spec.rb +9 -0
- data/spec/integration/knife/upload_spec.rb +28 -1
- data/spec/integration/recipes/lwrp_inline_resources_spec.rb +93 -23
- data/spec/integration/recipes/resource_action_spec.rb +211 -116
- data/spec/integration/recipes/resource_converge_if_changed_spec.rb +72 -0
- data/spec/integration/solo/solo_spec.rb +34 -0
- data/spec/spec_helper.rb +11 -1
- data/spec/support/platform_helpers.rb +8 -0
- data/spec/support/shared/integration/integration_helper.rb +6 -0
- data/spec/support/shared/unit/execute_resource.rb +5 -0
- data/spec/support/shared/unit/platform_introspector.rb +7 -0
- data/spec/tiny_server.rb +6 -2
- data/spec/unit/api_client/registration_spec.rb +5 -4
- data/spec/unit/application_spec.rb +1 -181
- data/spec/unit/chef_fs/file_system/cookbook_subdir_spec.rb +34 -0
- data/spec/unit/cookbook/metadata_spec.rb +122 -2
- data/spec/unit/http_spec.rb +102 -0
- data/spec/unit/knife/bootstrap_spec.rb +55 -13
- data/spec/unit/knife/core/bootstrap_context_spec.rb +10 -3
- data/spec/unit/knife/ssl_check_spec.rb +7 -3
- data/spec/unit/knife/ssl_fetch_spec.rb +2 -2
- data/spec/unit/knife/status_spec.rb +13 -13
- data/spec/unit/knife_spec.rb +26 -2
- data/spec/unit/lwrp_spec.rb +1 -1
- data/spec/unit/mixin/properties_spec.rb +97 -0
- data/spec/unit/mixin/proxified_socket_spec.rb +94 -0
- data/spec/unit/mixin/subclass_directive_spec.rb +45 -0
- data/spec/unit/node_spec.rb +9 -1
- data/spec/unit/policy_builder/policyfile_spec.rb +2 -0
- data/spec/unit/property/validation_spec.rb +14 -12
- data/spec/unit/property_spec.rb +56 -0
- data/spec/unit/provider/deploy_spec.rb +1 -1
- data/spec/unit/provider/dsc_resource_spec.rb +63 -24
- data/spec/unit/provider/execute_spec.rb +95 -28
- data/spec/unit/provider/package/dpkg_spec.rb +185 -96
- data/spec/unit/provider/package/windows/exe_spec.rb +251 -0
- data/spec/unit/provider/package/windows/msi_spec.rb +94 -10
- data/spec/unit/provider/package/windows_spec.rb +227 -26
- data/spec/unit/provider/package/yum_spec.rb +6 -0
- data/spec/unit/provider/package_spec.rb +495 -366
- data/spec/unit/provider/remote_file/cache_control_data_spec.rb +62 -36
- data/spec/unit/provider/script_spec.rb +2 -2
- data/spec/unit/provider/service/solaris_smf_service_spec.rb +110 -39
- data/spec/unit/provider/service/upstart_service_spec.rb +19 -0
- data/spec/unit/provider/user/dscl_spec.rb +14 -0
- data/spec/unit/provider/user/windows_spec.rb +2 -2
- data/spec/unit/provider/user_spec.rb +9 -0
- data/spec/unit/provider_resolver_spec.rb +6 -30
- data/spec/unit/recipe_spec.rb +46 -20
- data/spec/unit/resource/chef_gem_spec.rb +1 -1
- data/spec/unit/resource/dsc_resource_spec.rb +14 -3
- data/spec/unit/resource/ksh_spec.rb +40 -0
- data/spec/unit/resource/registry_key_spec.rb +2 -2
- data/spec/unit/resource/resource_notification_spec.rb +44 -45
- data/spec/unit/resource_reporter_spec.rb +7 -0
- data/spec/unit/resource_spec.rb +268 -253
- data/spec/unit/rest_spec.rb +2 -2
- data/spec/unit/run_list/run_list_expansion_spec.rb +18 -3
- data/spec/unit/search/query_spec.rb +19 -1
- data/spec/unit/util/powershell/ps_credential_spec.rb +8 -1
- data/spec/unit/windows_service_spec.rb +83 -38
- data/tasks/external_tests.rb +19 -9
- data/tasks/rspec.rb +1 -1
- metadata +70 -21
- data/spec/support/pedant/Gemfile +0 -3
- data/spec/support/pedant/pedant_config.rb +0 -129
- data/spec/support/pedant/run_pedant.rb +0 -63
- data/spec/support/pedant/stickywicket.pem +0 -27
- data/spec/unit/provider/package_spec.rbe +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
-
# Copyright:: Copyright (c) 2011
|
3
|
+
# Copyright:: Copyright (c) 2011-2015 Chef Software, Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -51,8 +51,7 @@ class Chef
|
|
51
51
|
option :log_location,
|
52
52
|
:short => "-L LOGLOCATION",
|
53
53
|
:long => "--logfile LOGLOCATION",
|
54
|
-
:description => "Set the log file location for chef-service"
|
55
|
-
:default => "#{ENV['SYSTEMDRIVE']}/chef/client.log"
|
54
|
+
:description => "Set the log file location for chef-service"
|
56
55
|
|
57
56
|
option :help,
|
58
57
|
:short => "-h",
|
data/lib/chef/audit/runner.rb
CHANGED
data/lib/chef/chef_class.rb
CHANGED
@@ -205,17 +205,7 @@ class Chef
|
|
205
205
|
# @api private this will likely be removed in favor of an as-yet unwritten
|
206
206
|
# `Chef.log`
|
207
207
|
def log_deprecation(message, location=nil)
|
208
|
-
|
209
|
-
# Pick the first caller that is *not* part of the Chef gem, that's the
|
210
|
-
# thing the user wrote.
|
211
|
-
chef_gem_path = File.expand_path("../..", __FILE__)
|
212
|
-
caller(0..10).each do |c|
|
213
|
-
if !c.start_with?(chef_gem_path)
|
214
|
-
location = c
|
215
|
-
break
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
208
|
+
location ||= Chef::Log.caller_location
|
219
209
|
# `run_context.events` is the primary deprecation target if we're in a
|
220
210
|
# run. If we are not yet in a run, print to `Chef::Log`.
|
221
211
|
if run_context && run_context.events
|
@@ -66,12 +66,65 @@ class Chef
|
|
66
66
|
# - ChefFSDataStore lets cookbooks be uploaded into a temporary memory
|
67
67
|
# storage, and when the cookbook is committed, copies the files onto the
|
68
68
|
# disk in the correct place (/cookbooks/apache2/recipes/default.rb).
|
69
|
+
#
|
69
70
|
# 3. Data bags:
|
70
71
|
# - The Chef server expects data bags in /data/BAG/ITEM
|
71
72
|
# - The repository stores data bags in /data_bags/BAG/ITEM
|
72
73
|
#
|
73
74
|
# 4. JSON filenames are generally NAME.json in the repository (e.g. /nodes/foo.json).
|
74
75
|
#
|
76
|
+
# 5. Org membership:
|
77
|
+
# chef-zero stores user membership in an org as a series of empty files.
|
78
|
+
# If an org has jkeiser and cdoherty as members, chef-zero expects these
|
79
|
+
# files to exist:
|
80
|
+
#
|
81
|
+
# - `users/jkeiser` (content: '{}')
|
82
|
+
# - `users/cdoherty` (content: '{}')
|
83
|
+
#
|
84
|
+
# ChefFS, on the other hand, stores user membership in an org as a single
|
85
|
+
# file, `members.json`, with content:
|
86
|
+
#
|
87
|
+
# ```json
|
88
|
+
# [
|
89
|
+
# { "user": { "username": "jkeiser" } },
|
90
|
+
# { "user": { "username": "cdoherty" } }
|
91
|
+
# ]
|
92
|
+
# ```
|
93
|
+
#
|
94
|
+
# To translate between the two, we need to intercept requests to `users`
|
95
|
+
# like so:
|
96
|
+
#
|
97
|
+
# - `list(users)` -> `get(/members.json)`
|
98
|
+
# - `get(users/NAME)` -> `get(/members.json)`, see if it's in there
|
99
|
+
# - `create(users/NAME)` -> `get(/members.json)`, add name, `set(/members.json)`
|
100
|
+
# - `delete(users/NAME)` -> `get(/members.json)`, remove name, `set(/members.json)`
|
101
|
+
#
|
102
|
+
# 6. Org invitations:
|
103
|
+
# chef-zero stores org membership invitations as a series of empty files.
|
104
|
+
# If an org has invited jkeiser and cdoherty (and they have not yet accepted
|
105
|
+
# the invite), chef-zero expects these files to exist:
|
106
|
+
#
|
107
|
+
# - `association_requests/jkeiser` (content: '{}')
|
108
|
+
# - `association_requests/cdoherty` (content: '{}')
|
109
|
+
#
|
110
|
+
# ChefFS, on the other hand, stores invitations as a single file,
|
111
|
+
# `invitations.json`, with content:
|
112
|
+
#
|
113
|
+
# ```json
|
114
|
+
# [
|
115
|
+
# { "id" => "jkeiser-chef", 'username' => 'jkeiser' },
|
116
|
+
# { "id" => "cdoherty-chef", 'username' => 'cdoherty' }
|
117
|
+
# ]
|
118
|
+
# ```
|
119
|
+
#
|
120
|
+
# To translate between the two, we need to intercept requests to `users`
|
121
|
+
# like so:
|
122
|
+
#
|
123
|
+
# - `list(association_requests)` -> `get(/invitations.json)`
|
124
|
+
# - `get(association_requests/NAME)` -> `get(/invitations.json)`, see if it's in there
|
125
|
+
# - `create(association_requests/NAME)` -> `get(/invitations.json)`, add name, `set(/invitations.json)`
|
126
|
+
# - `delete(association_requests/NAME)` -> `get(/invitations.json)`, remove name, `set(/invitations.json)`
|
127
|
+
#
|
75
128
|
class ChefFSDataStore
|
76
129
|
#
|
77
130
|
# Create a new ChefFSDataStore
|
@@ -83,9 +136,10 @@ class Chef
|
|
83
136
|
# Generally will be a +ChefFS::FileSystem::ChefRepositoryFileSystemRoot+
|
84
137
|
# object, created from +ChefFS::Config.local_fs+.
|
85
138
|
#
|
86
|
-
def initialize(chef_fs)
|
139
|
+
def initialize(chef_fs, chef_config=Chef::Config)
|
87
140
|
@chef_fs = chef_fs
|
88
141
|
@memory_store = ChefZero::DataStore::MemoryStore.new
|
142
|
+
@repo_mode = chef_config[:repo_mode]
|
89
143
|
end
|
90
144
|
|
91
145
|
def publish_description
|
@@ -93,6 +147,7 @@ class Chef
|
|
93
147
|
end
|
94
148
|
|
95
149
|
attr_reader :chef_fs
|
150
|
+
attr_reader :repo_mode
|
96
151
|
|
97
152
|
def create_dir(path, name, *options)
|
98
153
|
if use_memory_store?(path)
|
@@ -108,6 +163,24 @@ class Chef
|
|
108
163
|
end
|
109
164
|
end
|
110
165
|
|
166
|
+
#
|
167
|
+
# If you want to get the contents of /data/x/y from the server,
|
168
|
+
# you say chef_fs.child('data').child('x').child('y').read.
|
169
|
+
# It will make exactly one network request: GET /data/x/y
|
170
|
+
# And that will return 404 if it doesn't exist.
|
171
|
+
#
|
172
|
+
# ChefFS objects do not go to the network until you ask them for data.
|
173
|
+
# This means you can construct a /data/x/y ChefFS entry early.
|
174
|
+
#
|
175
|
+
# Alternative:
|
176
|
+
# chef_fs.child('data') could have done a GET /data preemptively,
|
177
|
+
# allowing it to know whether child('x') was valid (GET /data gives you
|
178
|
+
# a list of data bags). Then child('x') could have done a GET /data/x,
|
179
|
+
# allowing it to know whether child('y') (the item) existed. Finally,
|
180
|
+
# we would do the GET /data/x/y to read the contents. Three network
|
181
|
+
# requests instead of 1.
|
182
|
+
#
|
183
|
+
|
111
184
|
def create(path, name, data, *options)
|
112
185
|
if use_memory_store?(path)
|
113
186
|
@memory_store.create(path, name, data, *options)
|
@@ -115,6 +188,32 @@ class Chef
|
|
115
188
|
elsif path[0] == 'cookbooks' && path.length == 2
|
116
189
|
# Do nothing. The entry gets created when the cookbook is created.
|
117
190
|
|
191
|
+
# create [/organizations/ORG]/users/NAME (with content '{}')
|
192
|
+
# Manipulate the `members.json` file that contains a list of all users
|
193
|
+
elsif is_org? && path == [ 'users' ]
|
194
|
+
update_json('members.json', []) do |members|
|
195
|
+
# Format of each entry: { "user": { "username": "jkeiser" } }
|
196
|
+
if members.any? { |member| member['user']['username'] == name }
|
197
|
+
raise ChefZero::DataStore::DataAlreadyExistsError.new(path, entry)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Actually add the user
|
201
|
+
members << { "user" => { "username" => name } }
|
202
|
+
end
|
203
|
+
|
204
|
+
# create [/organizations/ORG]/association_requests/NAME (with content '{}')
|
205
|
+
# Manipulate the `invitations.json` file that contains a list of all users
|
206
|
+
elsif is_org? && path == [ 'association_requests' ]
|
207
|
+
update_json('invitations.json', []) do |invitations|
|
208
|
+
# Format of each entry: { "id" => "jkeiser-chef", 'username' => 'jkeiser' }
|
209
|
+
if invitations.any? { |member| member['username'] == name }
|
210
|
+
raise ChefZero::DataStore::DataAlreadyExistsError.new(path)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Actually add the user (TODO insert org name??)
|
214
|
+
invitations << { "username" => name }
|
215
|
+
end
|
216
|
+
|
118
217
|
else
|
119
218
|
if !data.is_a?(String)
|
120
219
|
raise "set only works with strings"
|
@@ -142,6 +241,24 @@ class Chef
|
|
142
241
|
raise ChefZero::DataStore::DataNotFoundError.new(to_zero_path(e.entry), e)
|
143
242
|
end
|
144
243
|
|
244
|
+
# GET [/organizations/ORG]/users/NAME -> /users/NAME
|
245
|
+
# Manipulates members.json
|
246
|
+
elsif is_org? && path[0] == 'users' && path.length == 2
|
247
|
+
if get_json('members.json', []).any? { |member| member['user']['username'] == path[1] }
|
248
|
+
'{}'
|
249
|
+
else
|
250
|
+
raise ChefZero::DataStore::DataNotFoundError.new(path)
|
251
|
+
end
|
252
|
+
|
253
|
+
# GET [/organizations/ORG]/association_requests/NAME -> /users/NAME
|
254
|
+
# Manipulates invites.json
|
255
|
+
elsif is_org? && path[0] == 'association_requests' && path.length == 2
|
256
|
+
if get_json('invites.json', []).any? { |member| member['user']['username'] == path[1] }
|
257
|
+
'{}'
|
258
|
+
else
|
259
|
+
raise ChefZero::DataStore::DataNotFoundError.new(path)
|
260
|
+
end
|
261
|
+
|
145
262
|
else
|
146
263
|
with_entry(path) do |entry|
|
147
264
|
if path[0] == 'cookbooks' && path.length == 3
|
@@ -209,6 +326,29 @@ class Chef
|
|
209
326
|
def delete(path)
|
210
327
|
if use_memory_store?(path)
|
211
328
|
@memory_store.delete(path)
|
329
|
+
|
330
|
+
# DELETE [/organizations/ORG]/users/NAME
|
331
|
+
# Manipulates members.json
|
332
|
+
elsif is_org? && path[0] == 'users' && path.length == 2
|
333
|
+
update_json('members.json', []) do |members|
|
334
|
+
result = members.reject { |member| member['user']['username'] == path[1] }
|
335
|
+
if result.size == members.size
|
336
|
+
raise ChefZero::DataStore::DataNotFoundError.new(path)
|
337
|
+
end
|
338
|
+
result
|
339
|
+
end
|
340
|
+
|
341
|
+
# DELETE [/organizations/ORG]/users/NAME
|
342
|
+
# Manipulates members.json
|
343
|
+
elsif is_org? && path[0] == 'association_requests' && path.length == 2
|
344
|
+
update_json('invitations.json', []) do |invitations|
|
345
|
+
result = invitations.reject { |invitation| invitation['username'] == path[1] }
|
346
|
+
if result.size == invitations.size
|
347
|
+
raise ChefZero::DataStore::DataNotFoundError.new(path)
|
348
|
+
end
|
349
|
+
result
|
350
|
+
end
|
351
|
+
|
212
352
|
else
|
213
353
|
with_entry(path) do |entry|
|
214
354
|
begin
|
@@ -394,9 +534,22 @@ class Chef
|
|
394
534
|
end
|
395
535
|
end
|
396
536
|
end
|
537
|
+
|
538
|
+
elsif path[0] == 'acls'
|
539
|
+
# /acls/containers|nodes|.../x.json
|
540
|
+
# /acls/organization.json
|
541
|
+
if path.length == 3 || path == [ 'acls', 'organization' ]
|
542
|
+
path = path.dup
|
543
|
+
path[-1] = "#{path[-1]}.json"
|
544
|
+
end
|
545
|
+
|
546
|
+
# /acls/containers|nodes|... do NOT drop into the next elsif, and do
|
547
|
+
# not get .json appended
|
548
|
+
|
549
|
+
# /nodes|clients|.../x.json
|
397
550
|
elsif path.length == 2
|
398
551
|
path = path.dup
|
399
|
-
path[1] = "#{path[1]}.json"
|
552
|
+
path[-1] = "#{path[-1]}.json"
|
400
553
|
end
|
401
554
|
path
|
402
555
|
end
|
@@ -477,6 +630,32 @@ class Chef
|
|
477
630
|
metadata = ChefZero::CookbookData.metadata_from(dir, path[1], nil, [])
|
478
631
|
metadata[:version] || '0.0.0'
|
479
632
|
end
|
633
|
+
|
634
|
+
def update_json(path, default_value)
|
635
|
+
entry = Chef::ChefFS::FileSystem.resolve_path(chef_fs, path)
|
636
|
+
begin
|
637
|
+
input = Chef::JSONCompat.parse(entry.read)
|
638
|
+
output = yield input.dup
|
639
|
+
entry.write(Chef::JSONCompat.to_json_pretty(output)) if output != input
|
640
|
+
rescue Chef::ChefFS::FileSystem::NotFoundError
|
641
|
+
# Send the default value to the caller, and create the entry if the caller updates it
|
642
|
+
output = yield default_value
|
643
|
+
entry.parent.create_child(entry.name, Chef::JSONCompat.to_json_pretty(output)) if output != []
|
644
|
+
end
|
645
|
+
end
|
646
|
+
|
647
|
+
def get_json(path, default_value)
|
648
|
+
entry = Chef::ChefFS::FileSystem.resolve_path(chef_fs, path)
|
649
|
+
begin
|
650
|
+
Chef::JSONCompat.parse(entry.read)
|
651
|
+
rescue Chef::ChefFS::FileSystem::NotFoundError
|
652
|
+
default_value
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
def is_org?
|
657
|
+
repo_mode == 'hosted_everything'
|
658
|
+
end
|
480
659
|
end
|
481
660
|
end
|
482
661
|
end
|
@@ -72,18 +72,22 @@ class Chef
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def delete(recurse)
|
75
|
-
|
76
|
-
if
|
77
|
-
|
75
|
+
begin
|
76
|
+
if dir?
|
77
|
+
if !recurse
|
78
|
+
raise MustDeleteRecursivelyError.new(self, $!)
|
79
|
+
end
|
80
|
+
FileUtils.rm_r(file_path)
|
81
|
+
else
|
82
|
+
File.delete(file_path)
|
78
83
|
end
|
79
|
-
|
80
|
-
|
81
|
-
File.delete(file_path)
|
84
|
+
rescue Errno::ENOENT
|
85
|
+
raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
|
82
86
|
end
|
83
87
|
end
|
84
88
|
|
85
89
|
def exists?
|
86
|
-
File.exists?(file_path) && parent.can_have_child?(name, dir?)
|
90
|
+
File.exists?(file_path) && (parent.nil? || parent.can_have_child?(name, dir?))
|
87
91
|
end
|
88
92
|
|
89
93
|
def read
|
data/lib/chef/client.rb
CHANGED
@@ -232,6 +232,8 @@ class Chef
|
|
232
232
|
# @return Always returns true.
|
233
233
|
#
|
234
234
|
def run
|
235
|
+
start_profiling
|
236
|
+
|
235
237
|
run_error = nil
|
236
238
|
|
237
239
|
runlock = RunLock.new(Chef::Config.lockfile)
|
@@ -271,7 +273,7 @@ class Chef
|
|
271
273
|
|
272
274
|
if Chef::Config[:why_run] == true
|
273
275
|
# why_run should probably be renamed to why_converge
|
274
|
-
Chef::Log.debug("Not running controls in '
|
276
|
+
Chef::Log.debug("Not running controls in 'why-run' mode - this mode is used to see potential converge changes")
|
275
277
|
elsif Chef::Config[:audit_mode] != :disabled
|
276
278
|
audit_error = run_audits(run_context)
|
277
279
|
end
|
@@ -284,6 +286,9 @@ class Chef
|
|
284
286
|
run_completed_successfully
|
285
287
|
events.run_completed(node)
|
286
288
|
|
289
|
+
# keep this inside the main loop to get exception backtraces
|
290
|
+
end_profiling
|
291
|
+
|
287
292
|
# rebooting has to be the last thing we do, no exceptions.
|
288
293
|
Chef::Platform::Rebooter.reboot_if_needed!(node)
|
289
294
|
rescue Exception => run_error
|
@@ -891,6 +896,28 @@ class Chef
|
|
891
896
|
attr_reader :override_runlist
|
892
897
|
attr_reader :specific_recipes
|
893
898
|
|
899
|
+
def profiling_prereqs!
|
900
|
+
require 'ruby-prof'
|
901
|
+
rescue LoadError
|
902
|
+
raise "You must have the ruby-prof gem installed in order to use --profile-ruby"
|
903
|
+
end
|
904
|
+
|
905
|
+
def start_profiling
|
906
|
+
return unless Chef::Config[:profile_ruby]
|
907
|
+
profiling_prereqs!
|
908
|
+
RubyProf.start
|
909
|
+
end
|
910
|
+
|
911
|
+
def end_profiling
|
912
|
+
return unless Chef::Config[:profile_ruby]
|
913
|
+
profiling_prereqs!
|
914
|
+
path = Chef::FileCache.create_cache_path("graph_profile.out", false)
|
915
|
+
File.open(path, "w+") do |file|
|
916
|
+
RubyProf::GraphPrinter.new(RubyProf.stop).print(file, {})
|
917
|
+
end
|
918
|
+
Chef::Log.warn("Ruby execution profile dumped to #{path}")
|
919
|
+
end
|
920
|
+
|
894
921
|
def empty_directory?(path)
|
895
922
|
!File.exists?(path) || (Dir.entries(path).size <= 2)
|
896
923
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#--
|
2
2
|
# Author:: Tim Hinderliter (<tim@opscode.com>)
|
3
3
|
# Author:: Christopher Walters (<cw@opscode.com>)
|
4
|
-
# Copyright:: Copyright (c) 2010
|
4
|
+
# Copyright:: Copyright (c) 2010-2015 Chef Software, Inc.
|
5
5
|
# License:: Apache License, Version 2.0
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -41,5 +41,18 @@ class Chef
|
|
41
41
|
cookbook_versions.each{ |cookbook_name, cookbook_version| self[cookbook_name] = cookbook_version }
|
42
42
|
end
|
43
43
|
|
44
|
+
# Validates that the cookbook metadata allows it to run on this instance.
|
45
|
+
#
|
46
|
+
# Currently checks chef_version and ohai_version in the cookbook metadata
|
47
|
+
# against the running Chef::VERSION and Ohai::VERSION.
|
48
|
+
#
|
49
|
+
# @raises [Chef::Exceptions::CookbookChefVersionMismatch] if the Chef::VERSION fails validation
|
50
|
+
# @raises [Chef::Exceptions::CookbookOhaiVersionMismatch] if the Ohai::VERSION fails validation
|
51
|
+
def validate!
|
52
|
+
each do |cookbook_name, cookbook_version|
|
53
|
+
cookbook_version.metadata.validate_chef_version!
|
54
|
+
cookbook_version.metadata.validate_ohai_version!
|
55
|
+
end
|
56
|
+
end
|
44
57
|
end
|
45
58
|
end
|
@@ -91,7 +91,7 @@ class Chef
|
|
91
91
|
remove_ignored_files
|
92
92
|
|
93
93
|
if empty?
|
94
|
-
Chef::Log.warn "
|
94
|
+
Chef::Log.warn "Found a directory #{cookbook_name} in the cookbook path, but it contains no cookbook files. skipping."
|
95
95
|
end
|
96
96
|
@cookbook_settings
|
97
97
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
3
|
# Author:: AJ Christensen (<aj@opscode.com>)
|
4
4
|
# Author:: Seth Falcon (<seth@opscode.com>)
|
5
|
-
# Copyright:: Copyright 2008-
|
5
|
+
# Copyright:: Copyright 2008-2015 Chef Software, Inc.
|
6
6
|
# License:: Apache License, Version 2.0
|
7
7
|
#
|
8
8
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -55,19 +55,23 @@ class Chef
|
|
55
55
|
SOURCE_URL = 'source_url'.freeze
|
56
56
|
ISSUES_URL = 'issues_url'.freeze
|
57
57
|
PRIVACY = 'privacy'.freeze
|
58
|
+
CHEF_VERSIONS = 'chef_versions'.freeze
|
59
|
+
OHAI_VERSIONS = 'ohai_versions'.freeze
|
58
60
|
|
59
61
|
COMPARISON_FIELDS = [ :name, :description, :long_description, :maintainer,
|
60
62
|
:maintainer_email, :license, :platforms, :dependencies,
|
61
63
|
:recommendations, :suggestions, :conflicting, :providing,
|
62
64
|
:replacing, :attributes, :groupings, :recipes, :version,
|
63
|
-
:source_url, :issues_url, :privacy ]
|
65
|
+
:source_url, :issues_url, :privacy, :chef_versions, :ohai_versions ]
|
64
66
|
|
65
|
-
VERSION_CONSTRAINTS = {:depends
|
66
|
-
:recommends
|
67
|
-
:suggests
|
68
|
-
:conflicts
|
69
|
-
:provides
|
70
|
-
:replaces
|
67
|
+
VERSION_CONSTRAINTS = {:depends => DEPENDENCIES,
|
68
|
+
:recommends => RECOMMENDATIONS,
|
69
|
+
:suggests => SUGGESTIONS,
|
70
|
+
:conflicts => CONFLICTING,
|
71
|
+
:provides => PROVIDING,
|
72
|
+
:replaces => REPLACING,
|
73
|
+
:chef_version => CHEF_VERSIONS,
|
74
|
+
:ohai_version => OHAI_VERSIONS }
|
71
75
|
|
72
76
|
include Chef::Mixin::ParamsValidate
|
73
77
|
include Chef::Mixin::FromFile
|
@@ -84,6 +88,11 @@ class Chef
|
|
84
88
|
attr_reader :recipes
|
85
89
|
attr_reader :version
|
86
90
|
|
91
|
+
# @return [Array<Gem::Dependency>] Array of supported Chef versions
|
92
|
+
attr_reader :chef_versions
|
93
|
+
# @return [Array<Gem::Dependency>] Array of supported Ohai versions
|
94
|
+
attr_reader :ohai_versions
|
95
|
+
|
87
96
|
# Builds a new Chef::Cookbook::Metadata object.
|
88
97
|
#
|
89
98
|
# === Parameters
|
@@ -118,6 +127,8 @@ class Chef
|
|
118
127
|
@source_url = ''
|
119
128
|
@issues_url = ''
|
120
129
|
@privacy = false
|
130
|
+
@chef_versions = []
|
131
|
+
@ohai_versions = []
|
121
132
|
|
122
133
|
@errors = []
|
123
134
|
end
|
@@ -386,6 +397,28 @@ class Chef
|
|
386
397
|
@replacing[cookbook]
|
387
398
|
end
|
388
399
|
|
400
|
+
# Metadata DSL to set a valid chef_version. May be declared multiple times
|
401
|
+
# with the result being 'OR'd such that if any statements match, the version
|
402
|
+
# is considered supported. Uses Gem::Requirement for its implementation.
|
403
|
+
#
|
404
|
+
# @param version_args [Array<String>] Version constraint in String form
|
405
|
+
# @return [Array<Gem::Dependency>] Current chef_versions array
|
406
|
+
def chef_version(*version_args)
|
407
|
+
@chef_versions << Gem::Dependency.new('chef', *version_args) unless version_args.empty?
|
408
|
+
@chef_versions
|
409
|
+
end
|
410
|
+
|
411
|
+
# Metadata DSL to set a valid ohai_version. May be declared multiple times
|
412
|
+
# with the result being 'OR'd such that if any statements match, the version
|
413
|
+
# is considered supported. Uses Gem::Requirement for its implementation.
|
414
|
+
#
|
415
|
+
# @param version_args [Array<String>] Version constraint in String form
|
416
|
+
# @return [Array<Gem::Dependency>] Current ohai_versions array
|
417
|
+
def ohai_version(*version_args)
|
418
|
+
@ohai_versions << Gem::Dependency.new('ohai', *version_args) unless version_args.empty?
|
419
|
+
@ohai_versions
|
420
|
+
end
|
421
|
+
|
389
422
|
# Adds a description for a recipe.
|
390
423
|
#
|
391
424
|
# === Parameters
|
@@ -481,6 +514,40 @@ class Chef
|
|
481
514
|
@groupings[name]
|
482
515
|
end
|
483
516
|
|
517
|
+
# Convert an Array of Gem::Dependency objects (chef_version/ohai_version) to an Array.
|
518
|
+
#
|
519
|
+
# Gem::Dependencey#to_s is not useful, and there is no #to_json defined on it or its component
|
520
|
+
# objets, so we have to write our own rendering method.
|
521
|
+
#
|
522
|
+
# [ Gem::Dependency.new(">= 12.5"), Gem::Dependency.new(">= 11.18.0", "< 12.0") ]
|
523
|
+
#
|
524
|
+
# results in:
|
525
|
+
#
|
526
|
+
# [ [ ">= 12.5" ], [ ">= 11.18.0", "< 12.0" ] ]
|
527
|
+
#
|
528
|
+
# @param deps [Array<Gem::Dependency>] Multiple Gem-style version constraints
|
529
|
+
# @return [Array<Array<String>]] Simple object representation of version constraints (for json)
|
530
|
+
def gem_requirements_to_array(*deps)
|
531
|
+
deps.map do |dep|
|
532
|
+
dep.requirement.requirements.map do |op, version|
|
533
|
+
"#{op} #{version}"
|
534
|
+
end.sort
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
# Convert an Array of Gem::Dependency objects (chef_version/ohai_version) to a hash.
|
539
|
+
#
|
540
|
+
# This is the inverse of #gem_requirements_to_array
|
541
|
+
#
|
542
|
+
# @param what [String] What version constraint we are constructing ('chef' or 'ohai' presently)
|
543
|
+
# @param array [Array<Array<String>]] Simple object representation of version constraints (from json)
|
544
|
+
# @return [Array<Gem::Dependency>] Multiple Gem-style version constraints
|
545
|
+
def gem_requirements_from_array(what, array)
|
546
|
+
array.map do |dep|
|
547
|
+
Gem::Dependency.new(what, *dep)
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
484
551
|
def to_hash
|
485
552
|
{
|
486
553
|
NAME => self.name,
|
@@ -502,7 +569,9 @@ class Chef
|
|
502
569
|
VERSION => self.version,
|
503
570
|
SOURCE_URL => self.source_url,
|
504
571
|
ISSUES_URL => self.issues_url,
|
505
|
-
PRIVACY => self.privacy
|
572
|
+
PRIVACY => self.privacy,
|
573
|
+
CHEF_VERSIONS => gem_requirements_to_array(*self.chef_versions),
|
574
|
+
OHAI_VERSIONS => gem_requirements_to_array(*self.ohai_versions)
|
506
575
|
}
|
507
576
|
end
|
508
577
|
|
@@ -537,6 +606,8 @@ class Chef
|
|
537
606
|
@source_url = o[SOURCE_URL] if o.has_key?(SOURCE_URL)
|
538
607
|
@issues_url = o[ISSUES_URL] if o.has_key?(ISSUES_URL)
|
539
608
|
@privacy = o[PRIVACY] if o.has_key?(PRIVACY)
|
609
|
+
@chef_versions = gem_requirements_from_array("chef", o[CHEF_VERSIONS]) if o.has_key?(CHEF_VERSIONS)
|
610
|
+
@ohai_versions = gem_requirements_from_array("ohai", o[OHAI_VERSIONS]) if o.has_key?(OHAI_VERSIONS)
|
540
611
|
self
|
541
612
|
end
|
542
613
|
|
@@ -612,8 +683,43 @@ class Chef
|
|
612
683
|
)
|
613
684
|
end
|
614
685
|
|
686
|
+
# Validates that the Ohai::VERSION of the running chef-client matches one of the
|
687
|
+
# configured ohai_version statements in this cookbooks metadata.
|
688
|
+
#
|
689
|
+
# @raises [Chef::Exceptions::CookbookOhaiVersionMismatch] if the cookbook fails validation
|
690
|
+
def validate_ohai_version!
|
691
|
+
unless gem_dep_matches?("ohai", Gem::Version.new(Ohai::VERSION), *ohai_versions)
|
692
|
+
raise Exceptions::CookbookOhaiVersionMismatch.new(Ohai::VERSION, name, version, *ohai_versions)
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
# Validates that the Chef::VERSION of the running chef-client matches one of the
|
697
|
+
# configured chef_version statements in this cookbooks metadata.
|
698
|
+
#
|
699
|
+
# @raises [Chef::Exceptions::CookbookChefVersionMismatch] if the cookbook fails validation
|
700
|
+
def validate_chef_version!
|
701
|
+
unless gem_dep_matches?("chef", Gem::Version.new(Chef::VERSION), *chef_versions)
|
702
|
+
raise Exceptions::CookbookChefVersionMismatch.new(Chef::VERSION, name, version, *chef_versions)
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
615
706
|
private
|
616
707
|
|
708
|
+
# Helper to match a gem style version (ohai_version/chef_version) against a set of
|
709
|
+
# Gem::Dependency version constraints. If none are present, it always matches. if
|
710
|
+
# multiple are present, one must match. Returns false if none matches.
|
711
|
+
#
|
712
|
+
# @param what [String] the name of the constraint (e.g. 'chef' or 'ohai')
|
713
|
+
# @param version [String] the version to compare against the constraints
|
714
|
+
# @param deps [Array<Gem::Dependency>] Multiple Gem-style version constraints
|
715
|
+
# @return [Boolean] true if no constraints or a match, false if no match
|
716
|
+
def gem_dep_matches?(what, version, *deps)
|
717
|
+
# always match if we have no chef_version at all
|
718
|
+
return true unless deps.length > 0
|
719
|
+
# match if we match any of the chef_version lines
|
720
|
+
deps.any? { |dep| dep.match?(what, version) }
|
721
|
+
end
|
722
|
+
|
617
723
|
def run_validation
|
618
724
|
if name.nil?
|
619
725
|
@errors = ["The `name' attribute is required in cookbook metadata"]
|