knife-essentials 0.9.4 → 0.9.5
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/lib/chef/knife/diff_essentials.rb +2 -5
- data/lib/chef/knife/raw_essentials.rb +2 -2
- data/lib/chef_fs/command_line.rb +98 -79
- data/lib/chef_fs/data_handler/acl_data_handler.rb +22 -0
- data/lib/chef_fs/data_handler/container_data_handler.rb +20 -0
- data/lib/chef_fs/data_handler/group_data_handler.rb +33 -0
- data/lib/chef_fs/data_handler/user_data_handler.rb +6 -1
- data/lib/chef_fs/file_system/acl_dir.rb +62 -0
- data/lib/chef_fs/file_system/acl_entry.rb +54 -0
- data/lib/chef_fs/file_system/acls_dir.rb +66 -0
- data/lib/chef_fs/file_system/base_fs_object.rb +0 -74
- data/lib/chef_fs/file_system/chef_repository_file_system_root_dir.rb +9 -0
- data/lib/chef_fs/file_system/chef_server_root_dir.rb +21 -2
- data/lib/chef_fs/file_system/cookbook_dir.rb +1 -1
- data/lib/chef_fs/file_system/cookbooks_acl_dir.rb +39 -0
- data/lib/chef_fs/file_system/cookbooks_dir.rb +3 -2
- data/lib/chef_fs/file_system/data_bags_dir.rb +1 -5
- data/lib/chef_fs/file_system/nodes_dir.rb +13 -3
- data/lib/chef_fs/file_system/rest_list_dir.rb +5 -7
- data/lib/chef_fs/file_system/rest_list_entry.rb +18 -18
- data/lib/chef_fs/knife.rb +7 -4
- data/lib/chef_fs/raw_request.rb +73 -0
- data/lib/chef_fs/version.rb +1 -1
- data/spec/support/integration_helper.rb +12 -1
- metadata +10 -6
- data/spec/chef_fs/file_system/chef_server_root_dir_spec.rb +0 -252
- data/spec/chef_fs/file_system/cookbook_dir_spec.rb +0 -582
- data/spec/chef_fs/file_system/cookbooks_dir_spec.rb +0 -165
- data/spec/chef_fs/file_system/data_bags_dir_spec.rb +0 -235
@@ -44,13 +44,10 @@ class Chef
|
|
44
44
|
error = false
|
45
45
|
begin
|
46
46
|
patterns.each do |pattern|
|
47
|
-
|
47
|
+
found_error = ChefFS::CommandLine.diff_print(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1, output_mode, proc { |entry| format_path(entry) }, config[:diff_filter], ui ) do |diff|
|
48
48
|
stdout.print diff
|
49
49
|
end
|
50
|
-
if
|
51
|
-
ui.error "#{pattern}: No such file or directory on remote or local"
|
52
|
-
error = true
|
53
|
-
end
|
50
|
+
error = true if found_error
|
54
51
|
end
|
55
52
|
rescue ChefFS::FileSystem::OperationFailedError => e
|
56
53
|
ui.error "Failed on #{format_path(e.entry)} in #{e.operation}: #{e.message}"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'chef_fs/data_handler/data_handler_base'
|
3
|
-
require 'chef_fs/
|
3
|
+
require 'chef_fs/raw_request'
|
4
4
|
|
5
5
|
class Chef
|
6
6
|
class Knife
|
@@ -44,7 +44,7 @@ class Chef
|
|
44
44
|
end
|
45
45
|
chef_rest = Chef::REST.new(Chef::Config[:chef_server_url])
|
46
46
|
begin
|
47
|
-
output
|
47
|
+
output ChefFS::RawRequest.api_request(chef_rest, config[:method].to_sym, chef_rest.create_url(name_args[0]), {}, data)
|
48
48
|
rescue Net::HTTPServerException => e
|
49
49
|
ui.error "Server responded with error #{e.response.code} \"#{e.response.message}\""
|
50
50
|
ui.error "Error Body: #{e.response.body}" if e.response.body && e.response.body != ''
|
data/lib/chef_fs/command_line.rb
CHANGED
@@ -17,18 +17,20 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require 'chef_fs/file_system'
|
20
|
+
require 'chef_fs/file_system/operation_failed_error'
|
21
|
+
require 'chef_fs/file_system/operation_not_allowed_error'
|
20
22
|
|
21
23
|
module ChefFS
|
22
24
|
module CommandLine
|
23
25
|
|
24
|
-
def self.diff_print(pattern, a_root, b_root, recurse_depth, output_mode, format_path = nil, diff_filter = nil)
|
26
|
+
def self.diff_print(pattern, a_root, b_root, recurse_depth, output_mode, format_path = nil, diff_filter = nil, ui = nil)
|
25
27
|
if format_path.nil?
|
26
28
|
format_path = proc { |entry| entry.path_for_printing }
|
27
29
|
end
|
28
30
|
|
29
31
|
get_content = (output_mode != :name_only && output_mode != :name_status)
|
30
32
|
found_match = false
|
31
|
-
diff(pattern, a_root, b_root, recurse_depth, get_content) do |type, old_entry, new_entry, old_value, new_value|
|
33
|
+
diff(pattern, a_root, b_root, recurse_depth, get_content) do |type, old_entry, new_entry, old_value, new_value, error|
|
32
34
|
found_match = true unless type == :both_nonexistent
|
33
35
|
old_path = format_path.call(old_entry)
|
34
36
|
new_path = format_path.call(new_entry)
|
@@ -104,9 +106,22 @@ module ChefFS
|
|
104
106
|
when :deleted_cannot_download
|
105
107
|
when :same
|
106
108
|
# Skip these silently
|
109
|
+
when :error
|
110
|
+
if error.is_a?(ChefFS::FileSystem::OperationFailedError)
|
111
|
+
ui.error "#{format_path.call(error.entry)} failed to #{error.operation}: #{error.message}" if ui
|
112
|
+
error = true
|
113
|
+
elsif error.is_a?(ChefFS::FileSystem::OperationNotAllowedError)
|
114
|
+
ui.error "#{format_path.call(error.entry)} #{error.reason}." if ui
|
115
|
+
else
|
116
|
+
raise error
|
117
|
+
end
|
107
118
|
end
|
108
119
|
end
|
109
|
-
found_match
|
120
|
+
if !found_match
|
121
|
+
ui.error "#{pattern}: No such file or directory on remote or local" if ui
|
122
|
+
error = true
|
123
|
+
end
|
124
|
+
error
|
110
125
|
end
|
111
126
|
|
112
127
|
def self.diff(pattern, a_root, b_root, recurse_depth, get_content)
|
@@ -119,98 +134,102 @@ module ChefFS
|
|
119
134
|
|
120
135
|
# Diff two known entries (could be files or dirs)
|
121
136
|
def self.diff_entries(old_entry, new_entry, recurse_depth, get_content)
|
122
|
-
|
123
|
-
|
124
|
-
if
|
125
|
-
if
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
137
|
+
begin
|
138
|
+
# If both are directories
|
139
|
+
if old_entry.dir?
|
140
|
+
if new_entry.dir?
|
141
|
+
if recurse_depth == 0
|
142
|
+
yield [ :common_subdirectories, old_entry, new_entry ]
|
143
|
+
else
|
144
|
+
ChefFS::FileSystem.child_pairs(old_entry, new_entry).each do |old_child,new_child|
|
145
|
+
diff_entries(old_child, new_child,
|
146
|
+
recurse_depth ? recurse_depth - 1 : nil, get_content) do |diff|
|
147
|
+
yield diff
|
148
|
+
end
|
132
149
|
end
|
133
150
|
end
|
134
|
-
end
|
135
151
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
# If old is a directory and new does not exist
|
141
|
-
elsif new_entry.parent.can_have_child?(old_entry.name, old_entry.dir?)
|
142
|
-
yield [ :deleted, old_entry, new_entry ]
|
143
|
-
end
|
152
|
+
# If old is a directory and new is a file
|
153
|
+
elsif new_entry.exists?
|
154
|
+
yield [ :directory_to_file, old_entry, new_entry ]
|
144
155
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
156
|
+
# If old is a directory and new does not exist
|
157
|
+
elsif new_entry.parent.can_have_child?(old_entry.name, old_entry.dir?)
|
158
|
+
yield [ :deleted, old_entry, new_entry ]
|
159
|
+
end
|
149
160
|
|
150
|
-
|
151
|
-
elsif
|
152
|
-
|
153
|
-
|
161
|
+
# If new is a directory and old is a file
|
162
|
+
elsif new_entry.dir?
|
163
|
+
if old_entry.exists?
|
164
|
+
yield [ :file_to_directory, old_entry, new_entry ]
|
154
165
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
if are_same
|
159
|
-
if old_value == :none
|
160
|
-
yield [ :both_nonexistent, old_entry, new_entry ]
|
161
|
-
else
|
162
|
-
yield [ :same, old_entry, new_entry ]
|
163
|
-
end
|
164
|
-
else
|
165
|
-
if old_value == :none
|
166
|
-
old_exists = false
|
167
|
-
elsif old_value.nil?
|
168
|
-
old_exists = old_entry.exists?
|
169
|
-
else
|
170
|
-
old_exists = true
|
166
|
+
# If new is a directory and old does not exist
|
167
|
+
elsif old_entry.parent.can_have_child?(new_entry.name, new_entry.dir?)
|
168
|
+
yield [ :added, old_entry, new_entry ]
|
171
169
|
end
|
172
170
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
171
|
+
# Neither is a directory, so they are diffable with file diff
|
172
|
+
else
|
173
|
+
are_same, old_value, new_value = ChefFS::FileSystem.compare(old_entry, new_entry)
|
174
|
+
if are_same
|
175
|
+
if old_value == :none
|
176
|
+
yield [ :both_nonexistent, old_entry, new_entry ]
|
177
|
+
else
|
178
|
+
yield [ :same, old_entry, new_entry ]
|
179
|
+
end
|
177
180
|
else
|
178
|
-
|
179
|
-
|
181
|
+
if old_value == :none
|
182
|
+
old_exists = false
|
183
|
+
elsif old_value.nil?
|
184
|
+
old_exists = old_entry.exists?
|
185
|
+
else
|
186
|
+
old_exists = true
|
187
|
+
end
|
180
188
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
yield [ :new_cannot_upload, old_entry, new_entry ]
|
189
|
-
return
|
190
|
-
end
|
189
|
+
if new_value == :none
|
190
|
+
new_exists = false
|
191
|
+
elsif new_value.nil?
|
192
|
+
new_exists = new_entry.exists?
|
193
|
+
else
|
194
|
+
new_exists = true
|
195
|
+
end
|
191
196
|
|
192
|
-
|
193
|
-
#
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
old_value = :none
|
197
|
+
# If one of the files doesn't exist, we only want to print the diff if the
|
198
|
+
# other file *could be uploaded/downloaded*.
|
199
|
+
if !old_exists && !old_entry.parent.can_have_child?(new_entry.name, new_entry.dir?)
|
200
|
+
yield [ :old_cannot_upload, old_entry, new_entry ]
|
201
|
+
return
|
198
202
|
end
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
new_value = :none
|
203
|
+
if !new_exists && !new_entry.parent.can_have_child?(old_entry.name, old_entry.dir?)
|
204
|
+
yield [ :new_cannot_upload, old_entry, new_entry ]
|
205
|
+
return
|
203
206
|
end
|
204
|
-
end
|
205
207
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
208
|
+
if get_content
|
209
|
+
# If we haven't read the values yet, get them now so that they can be diffed
|
210
|
+
begin
|
211
|
+
old_value = old_entry.read if old_value.nil?
|
212
|
+
rescue ChefFS::FileSystem::NotFoundError
|
213
|
+
old_value = :none
|
214
|
+
end
|
215
|
+
begin
|
216
|
+
new_value = new_entry.read if new_value.nil?
|
217
|
+
rescue ChefFS::FileSystem::NotFoundError
|
218
|
+
new_value = :none
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
if old_value == :none || (old_value == nil && !old_entry.exists?)
|
223
|
+
yield [ :added, old_entry, new_entry, old_value, new_value ]
|
224
|
+
elsif new_value == :none
|
225
|
+
yield [ :deleted, old_entry, new_entry, old_value, new_value ]
|
226
|
+
else
|
227
|
+
yield [ :modified, old_entry, new_entry, old_value, new_value ]
|
228
|
+
end
|
212
229
|
end
|
213
230
|
end
|
231
|
+
rescue ChefFS::FileSystem::FileSystemError => e
|
232
|
+
yield [ :error, old_entry, new_entry, nil, nil, e ]
|
214
233
|
end
|
215
234
|
end
|
216
235
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'chef_fs/data_handler/data_handler_base'
|
2
|
+
|
3
|
+
module ChefFS
|
4
|
+
module DataHandler
|
5
|
+
class AclDataHandler < DataHandlerBase
|
6
|
+
def normalize(node, entry)
|
7
|
+
# Normalize the order of the keys for easier reading
|
8
|
+
result = super(node, {
|
9
|
+
'create' => {},
|
10
|
+
'read' => {},
|
11
|
+
'update' => {},
|
12
|
+
'delete' => {},
|
13
|
+
'grant' => {}
|
14
|
+
})
|
15
|
+
result.keys.each do |key|
|
16
|
+
result[key] = super(result[key], { 'actors' => [], 'groups' => [] })
|
17
|
+
end
|
18
|
+
result
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'chef_fs/data_handler/data_handler_base'
|
2
|
+
|
3
|
+
module ChefFS
|
4
|
+
module DataHandler
|
5
|
+
class ContainerDataHandler < DataHandlerBase
|
6
|
+
def normalize(user, entry)
|
7
|
+
super(user, {
|
8
|
+
'containername' => remove_dot_json(entry.name),
|
9
|
+
'containerpath' => remove_dot_json(entry.name)
|
10
|
+
})
|
11
|
+
end
|
12
|
+
|
13
|
+
def preserve_key(key)
|
14
|
+
return key == 'containername'
|
15
|
+
end
|
16
|
+
|
17
|
+
# There is no chef_class for users, nor does to_ruby work.
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'chef_fs/data_handler/data_handler_base'
|
2
|
+
require 'chef/api_client'
|
3
|
+
|
4
|
+
module ChefFS
|
5
|
+
module DataHandler
|
6
|
+
class GroupDataHandler < DataHandlerBase
|
7
|
+
def normalize(group, entry)
|
8
|
+
defaults = {
|
9
|
+
'name' => remove_dot_json(entry.name),
|
10
|
+
'groupname' => remove_dot_json(entry.name),
|
11
|
+
'users' => [],
|
12
|
+
'actors' => [],
|
13
|
+
'clients' => [],
|
14
|
+
'groups' => [],
|
15
|
+
}
|
16
|
+
if entry.org
|
17
|
+
defaults['orgname'] = entry.org
|
18
|
+
end
|
19
|
+
super(group, defaults)
|
20
|
+
end
|
21
|
+
|
22
|
+
def preserve_key(key)
|
23
|
+
return key == 'name'
|
24
|
+
end
|
25
|
+
|
26
|
+
def chef_class
|
27
|
+
Chef::ApiClient
|
28
|
+
end
|
29
|
+
|
30
|
+
# There is no Ruby API for Chef::ApiClient
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -6,7 +6,12 @@ module ChefFS
|
|
6
6
|
def normalize(user, entry)
|
7
7
|
super(user, {
|
8
8
|
'name' => remove_dot_json(entry.name),
|
9
|
-
'admin' => false
|
9
|
+
'admin' => false,
|
10
|
+
'json_class' => 'Chef::WebUIUser',
|
11
|
+
'chef_type' => 'webui_user',
|
12
|
+
'salt' => nil,
|
13
|
+
'password' => nil,
|
14
|
+
'openid' => nil
|
10
15
|
})
|
11
16
|
end
|
12
17
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#
|
2
|
+
# Author:: John Keiser (<jkeiser@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 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
|
+
require 'chef_fs/file_system/base_fs_dir'
|
20
|
+
require 'chef_fs/file_system/acl_entry'
|
21
|
+
require 'chef_fs/file_system/operation_not_allowed_error'
|
22
|
+
|
23
|
+
module ChefFS
|
24
|
+
module FileSystem
|
25
|
+
class AclDir < BaseFSDir
|
26
|
+
def api_path
|
27
|
+
parent.parent.child(name).api_path
|
28
|
+
end
|
29
|
+
|
30
|
+
def child(name)
|
31
|
+
result = @children.select { |child| child.name == name }.first if @children
|
32
|
+
result ||= can_have_child?(name, false) ?
|
33
|
+
AclEntry.new(name, self) : NonexistentFSObject.new(name, self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def can_have_child?(name, is_dir)
|
37
|
+
name =~ /\.json$/ && !is_dir
|
38
|
+
end
|
39
|
+
|
40
|
+
def children
|
41
|
+
if @children.nil?
|
42
|
+
# Grab the ACTUAL children (/nodes, /containers, etc.) and get their names
|
43
|
+
names = parent.parent.child(name).children.map { |child| child.dir? ? "#{child.name}.json" : child.name }
|
44
|
+
@children = names.map { |name| AclEntry.new(name, self, true) }
|
45
|
+
end
|
46
|
+
@children
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_child(name, file_contents)
|
50
|
+
raise OperationNotAllowedError.new(:create_child, self)
|
51
|
+
end
|
52
|
+
|
53
|
+
def data_handler
|
54
|
+
parent.data_handler
|
55
|
+
end
|
56
|
+
|
57
|
+
def rest
|
58
|
+
parent.rest
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#
|
2
|
+
# Author:: John Keiser (<jkeiser@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 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
|
+
require 'chef_fs/file_system/rest_list_entry'
|
20
|
+
require 'chef_fs/file_system/not_found_error'
|
21
|
+
require 'chef_fs/file_system/operation_not_allowed_error'
|
22
|
+
require 'chef_fs/file_system/operation_failed_error'
|
23
|
+
|
24
|
+
module ChefFS
|
25
|
+
module FileSystem
|
26
|
+
class AclEntry < RestListEntry
|
27
|
+
PERMISSIONS = %w(create read update delete grant)
|
28
|
+
|
29
|
+
def api_path
|
30
|
+
"#{super}/_acl"
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete(recurse)
|
34
|
+
raise ChefFS::FileSystem::OperationNotAllowedError.new(:delete, self, e), "ACLs cannot be deleted."
|
35
|
+
end
|
36
|
+
|
37
|
+
def write(file_contents)
|
38
|
+
# ACL writes are fun.
|
39
|
+
acls = data_handler.normalize(JSON.parse(file_contents, :create_additions => false), self)
|
40
|
+
PERMISSIONS.each do |permission|
|
41
|
+
begin
|
42
|
+
rest.put_rest("#{api_path}/#{permission}", { permission => acls[permission] })
|
43
|
+
rescue Net::HTTPServerException => e
|
44
|
+
if e.response.code == "404"
|
45
|
+
raise ChefFS::FileSystem::NotFoundError.new(self, e)
|
46
|
+
else
|
47
|
+
raise ChefFS::FileSystem::OperationFailedError.new(:write, self, e), "HTTP error writing: #{e}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|