knife-essentials 0.1.1 → 0.2
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/list.rb +1 -1
- data/lib/chef/knife/show.rb +1 -1
- data/lib/chef_fs/command_line.rb +11 -2
- data/lib/chef_fs/diff.rb +1 -1
- data/lib/chef_fs/file_system/base_fs_dir.rb +4 -0
- data/lib/chef_fs/file_system/base_fs_object.rb +11 -0
- data/lib/chef_fs/file_system/chef_repository_file_system_entry.rb +46 -0
- data/lib/chef_fs/file_system/chef_repository_file_system_root_dir.rb +11 -0
- data/lib/chef_fs/file_system/chef_server_root_dir.rb +5 -1
- data/lib/chef_fs/file_system/cookbook_dir.rb +63 -7
- data/lib/chef_fs/file_system/cookbook_file.rb +2 -2
- data/lib/chef_fs/file_system/cookbook_subdir.rb +12 -1
- data/lib/chef_fs/file_system/cookbooks_dir.rb +4 -0
- data/lib/chef_fs/file_system/data_bag_dir.rb +2 -1
- data/lib/chef_fs/file_system/data_bags_dir.rb +4 -0
- data/lib/chef_fs/file_system/file_system_entry.rb +4 -3
- data/lib/chef_fs/file_system/nonexistent_fs_object.rb +2 -5
- data/lib/chef_fs/file_system/not_found_error.rb +11 -0
- data/lib/chef_fs/file_system/rest_list_dir.rb +6 -1
- data/lib/chef_fs/file_system/rest_list_entry.rb +3 -3
- data/lib/chef_fs/knife.rb +2 -2
- data/lib/chef_fs/version.rb +1 -1
- data/spec/chef_fs/diff_spec.rb +14 -2
- data/spec/chef_fs/file_system/chef_server_root_dir_spec.rb +212 -0
- data/spec/chef_fs/file_system/cookbooks_dir_spec.rb +549 -0
- data/spec/chef_fs/file_system/data_bags_dir_spec.rb +202 -0
- data/spec/support/file_system_support.rb +9 -3
- metadata +8 -3
- data/lib/chef_fs/file_system/not_found_exception.rb +0 -12
data/lib/chef/knife/list.rb
CHANGED
@@ -52,7 +52,7 @@ class Chef
|
|
52
52
|
def add_dir_result(result)
|
53
53
|
begin
|
54
54
|
children = result.children.sort_by { |child| child.name }
|
55
|
-
rescue ChefFS::FileSystem::
|
55
|
+
rescue ChefFS::FileSystem::NotFoundError
|
56
56
|
STDERR.puts "#{format_path(result.path)}: No such file or directory"
|
57
57
|
return []
|
58
58
|
end
|
data/lib/chef/knife/show.rb
CHANGED
@@ -17,7 +17,7 @@ class Chef
|
|
17
17
|
value = result.read
|
18
18
|
puts "#{format_path(result.path)}:"
|
19
19
|
output(format_for_display(result.read))
|
20
|
-
rescue ChefFS::FileSystem::
|
20
|
+
rescue ChefFS::FileSystem::NotFoundError
|
21
21
|
STDERR.puts "#{format_path(result.path)}: No such file or directory" if pattern.exact_path
|
22
22
|
end
|
23
23
|
end
|
data/lib/chef_fs/command_line.rb
CHANGED
@@ -27,7 +27,7 @@ module ChefFS
|
|
27
27
|
result << "Common subdirectories: #{old_file.path}\n"
|
28
28
|
elsif new_file.exists?
|
29
29
|
result << "File #{new_file.path_for_printing} is a directory while file #{new_file.path_for_printing} is a regular file\n"
|
30
|
-
|
30
|
+
elsif new_file.parent.can_have_child?(old_file.name, old_file.dir?)
|
31
31
|
result << "Only in #{old_file.parent.path_for_printing}: #{old_file.name}\n"
|
32
32
|
end
|
33
33
|
|
@@ -36,7 +36,7 @@ module ChefFS
|
|
36
36
|
elsif new_file.dir?
|
37
37
|
if old_file.exists?
|
38
38
|
result << "File #{old_file.path_for_printing} is a regular file while file #{old_file.path_for_printing} is a directory\n"
|
39
|
-
|
39
|
+
elsif old_file.parent.can_have_child?(new_file.name, new_file.dir?)
|
40
40
|
result << "Only in #{new_file.parent.path_for_printing}: #{new_file.name}\n"
|
41
41
|
end
|
42
42
|
|
@@ -44,6 +44,15 @@ module ChefFS
|
|
44
44
|
# Neither is a directory, so they are diffable with file diff
|
45
45
|
different, old_value, new_value = ChefFS::Diff::diff_files(old_file, new_file)
|
46
46
|
if different
|
47
|
+
# If one of the files doesn't exist, we only want to print the diff if the
|
48
|
+
# other file *could be synced*.
|
49
|
+
if !old_value && !old_file.parent.can_have_child?(new_file.name, new_file.dir?)
|
50
|
+
return result
|
51
|
+
end
|
52
|
+
if !new_value && !new_file.parent.can_have_child?(old_file.name, old_file.dir?)
|
53
|
+
return result
|
54
|
+
end
|
55
|
+
|
47
56
|
old_path = old_file.path_for_printing
|
48
57
|
new_path = new_file.path_for_printing
|
49
58
|
result << "diff --knife #{old_path} #{new_path}\n"
|
data/lib/chef_fs/diff.rb
CHANGED
@@ -44,6 +44,17 @@ module ChefFS
|
|
44
44
|
:text
|
45
45
|
end
|
46
46
|
|
47
|
+
def child(name)
|
48
|
+
NonexistentFSObject.new(name, self)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Override can_have_child? to report whether a given file *could* be added
|
52
|
+
# to this directory. (Some directories can't have subdirs, some can only have .json
|
53
|
+
# files, etc.)
|
54
|
+
def can_have_child?(name, is_dir)
|
55
|
+
false
|
56
|
+
end
|
57
|
+
|
47
58
|
# Important directory attributes: name, parent, path, root
|
48
59
|
# Overridable attributes: dir?, child(name), path_for_printing
|
49
60
|
# Abstract: read, write, delete, children
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'chef_fs/file_system/file_system_entry'
|
2
|
+
require 'chef/cookbook/chefignore'
|
3
|
+
|
4
|
+
module ChefFS
|
5
|
+
module FileSystem
|
6
|
+
# ChefRepositoryFileSystemEntry works just like FileSystemEntry,
|
7
|
+
# except it pretends files in /cookbooks/chefignore don't exist
|
8
|
+
class ChefRepositoryFileSystemEntry < FileSystemEntry
|
9
|
+
def initialize(name, parent, file_path = nil)
|
10
|
+
super(name, parent, file_path)
|
11
|
+
# Load /cookbooks/chefignore
|
12
|
+
if name == "cookbooks" && path == "/cookbooks" # We check name first because it's a faster fail than path
|
13
|
+
@chefignore = Chef::Cookbook::Chefignore.new(self.file_path)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def children
|
18
|
+
@children ||= Dir.entries(file_path).select { |entry| entry != '.' && entry != '..' && !ignored?(entry) }
|
19
|
+
.map { |entry| ChefRepositoryFileSystemEntry.new(entry, self) }
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :chefignore
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def ignored?(child_name)
|
27
|
+
ignorer = self
|
28
|
+
begin
|
29
|
+
if ignorer.chefignore
|
30
|
+
# Grab the path from entry to child
|
31
|
+
path_to_child = child_name
|
32
|
+
child = self
|
33
|
+
while child != ignorer
|
34
|
+
path_to_child = PathUtils.join(child.name, path_to_child)
|
35
|
+
child = child.parent
|
36
|
+
end
|
37
|
+
# Check whether that relative path is ignored
|
38
|
+
return ignorer.chefignore.ignored?(path_to_child)
|
39
|
+
end
|
40
|
+
ignorer = ignorer.parent
|
41
|
+
end while ignorer
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'chef_fs/file_system/rest_list_dir'
|
2
2
|
require 'chef_fs/file_system/cookbook_subdir'
|
3
3
|
require 'chef_fs/file_system/cookbook_file'
|
4
|
+
require 'chef_fs/file_system/not_found_error'
|
4
5
|
require 'chef/cookbook_version'
|
5
6
|
|
6
7
|
module ChefFS
|
@@ -13,6 +14,18 @@ module ChefFS
|
|
13
14
|
|
14
15
|
attr_reader :versions
|
15
16
|
|
17
|
+
COOKBOOK_SEGMENT_INFO = {
|
18
|
+
:attributes => { :ruby_only => true },
|
19
|
+
:definitions => { :ruby_only => true },
|
20
|
+
:recipes => { :ruby_only => true },
|
21
|
+
:libraries => { :ruby_only => true },
|
22
|
+
:templates => { :recursive => true },
|
23
|
+
:files => { :recursive => true },
|
24
|
+
:resources => { :ruby_only => true, :recursive => true },
|
25
|
+
:providers => { :ruby_only => true, :recursive => true },
|
26
|
+
:root_files => { }
|
27
|
+
}
|
28
|
+
|
16
29
|
def add_child(child)
|
17
30
|
@children << child
|
18
31
|
end
|
@@ -22,23 +35,42 @@ module ChefFS
|
|
22
35
|
end
|
23
36
|
|
24
37
|
def child(name)
|
25
|
-
|
38
|
+
# Since we're ignoring the rules and doing a network request here,
|
39
|
+
# we need to make sure we don't rethrow the exception. (child(name)
|
40
|
+
# is not supposed to fail.)
|
41
|
+
begin
|
42
|
+
result = children.select { |child| child.name == name }.first
|
43
|
+
return result if result
|
44
|
+
rescue ChefFS::FileSystem::NotFoundError
|
45
|
+
end
|
46
|
+
return NonexistentFSObject.new(name, self)
|
47
|
+
end
|
48
|
+
|
49
|
+
def can_have_child?(name, is_dir)
|
50
|
+
# A cookbook's root may not have directories unless they are segment directories
|
51
|
+
if is_dir
|
52
|
+
return name != 'root_files' && COOKBOOK_SEGMENT_INFO.keys.any? { |segment| segment.to_s == name }
|
53
|
+
end
|
54
|
+
true
|
26
55
|
end
|
27
56
|
|
28
57
|
def children
|
29
58
|
if @children.nil?
|
30
59
|
@children = []
|
31
|
-
|
60
|
+
COOKBOOK_SEGMENT_INFO.each do |segment, segment_info|
|
32
61
|
next unless manifest.has_key?(segment)
|
62
|
+
|
63
|
+
# Go through each file in the manifest for the segment, and
|
64
|
+
# add cookbook subdirs and files for it.
|
33
65
|
manifest[segment].each do |segment_file|
|
34
|
-
parts = segment_file[
|
66
|
+
parts = segment_file[:path].split('/')
|
35
67
|
# Get or create the path to the file
|
36
68
|
container = self
|
37
69
|
parts[0,parts.length-1].each do |part|
|
38
70
|
old_container = container
|
39
71
|
container = old_container.children.select { |child| part == child.name }.first
|
40
72
|
if !container
|
41
|
-
container = CookbookSubdir.new(part, old_container)
|
73
|
+
container = CookbookSubdir.new(part, old_container, segment_info[:ruby_only], segment_info[:recursive])
|
42
74
|
old_container.add_child(container)
|
43
75
|
end
|
44
76
|
end
|
@@ -56,7 +88,7 @@ module ChefFS
|
|
56
88
|
|
57
89
|
def read
|
58
90
|
# This will only be called if dir? is false, which means exists? is false.
|
59
|
-
raise ChefFS::FileSystem::
|
91
|
+
raise ChefFS::FileSystem::NotFoundError, path_for_printing
|
60
92
|
end
|
61
93
|
|
62
94
|
def exists?
|
@@ -74,11 +106,35 @@ module ChefFS
|
|
74
106
|
private
|
75
107
|
|
76
108
|
def manifest
|
109
|
+
# The negative (not found) response is cached
|
110
|
+
if @could_not_get_manifest
|
111
|
+
raise ChefFS::FileSystem::NotFoundError.new(@could_not_get_manifest), "#{path_for_printing} not found"
|
112
|
+
end
|
113
|
+
|
77
114
|
begin
|
78
|
-
|
115
|
+
# We want to fail fast, for now, because of the 500 issue :/
|
116
|
+
# This will make things worse for parallelism, a little.
|
117
|
+
old_retry_count = Chef::Config[:http_retry_count]
|
118
|
+
begin
|
119
|
+
Chef::Config[:http_retry_count] = 0
|
120
|
+
@manifest ||= rest.get_rest(api_path).manifest
|
121
|
+
ensure
|
122
|
+
Chef::Config[:http_retry_count] = old_retry_count
|
123
|
+
end
|
79
124
|
rescue Net::HTTPServerException
|
80
125
|
if $!.response.code == "404"
|
81
|
-
|
126
|
+
@could_not_get_manifest = $!
|
127
|
+
raise ChefFS::FileSystem::NotFoundError.new(@could_not_get_manifest), "#{path_for_printing} not found"
|
128
|
+
else
|
129
|
+
raise
|
130
|
+
end
|
131
|
+
|
132
|
+
# Chef bug http://tickets.opscode.com/browse/CHEF-3066 ... instead of 404 we get 500 right now.
|
133
|
+
# Remove this when that bug is fixed.
|
134
|
+
rescue Net::HTTPFatalError
|
135
|
+
if $!.response.code == "500"
|
136
|
+
@could_not_get_manifest = $!
|
137
|
+
raise ChefFS::FileSystem::NotFoundError.new(@could_not_get_manifest), "#{path_for_printing} not found"
|
82
138
|
else
|
83
139
|
raise
|
84
140
|
end
|
@@ -18,9 +18,9 @@ module ChefFS
|
|
18
18
|
old_sign_on_redirect = rest.sign_on_redirect
|
19
19
|
rest.sign_on_redirect = false
|
20
20
|
begin
|
21
|
-
rest.get_rest(file[
|
21
|
+
rest.get_rest(file[:url])
|
22
22
|
ensure
|
23
|
-
rest.sign_on_redirect =
|
23
|
+
rest.sign_on_redirect = old_sign_on_redirect
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -5,9 +5,11 @@ require 'chef_fs/file_system/base_fs_dir'
|
|
5
5
|
module ChefFS
|
6
6
|
module FileSystem
|
7
7
|
class CookbookSubdir < BaseFSDir
|
8
|
-
def initialize(name, parent)
|
8
|
+
def initialize(name, parent, ruby_only, recursive)
|
9
9
|
super(name, parent)
|
10
10
|
@children = []
|
11
|
+
@ruby_only = ruby_only
|
12
|
+
@recursive = recursive
|
11
13
|
end
|
12
14
|
|
13
15
|
attr_reader :versions
|
@@ -17,6 +19,15 @@ module ChefFS
|
|
17
19
|
@children << child
|
18
20
|
end
|
19
21
|
|
22
|
+
def can_have_child?(name, is_dir)
|
23
|
+
if is_dir
|
24
|
+
return false if !@recursive
|
25
|
+
else
|
26
|
+
return false if @ruby_only && name !~ /\.rb$/
|
27
|
+
end
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
20
31
|
def rest
|
21
32
|
parent.rest
|
22
33
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'chef_fs/file_system/base_fs_dir'
|
2
2
|
require 'chef_fs/file_system/rest_list_entry'
|
3
|
+
require 'chef_fs/file_system/not_found_error'
|
3
4
|
|
4
5
|
# TODO: take environment into account
|
5
6
|
|
@@ -17,7 +18,7 @@ module ChefFS
|
|
17
18
|
|
18
19
|
def read
|
19
20
|
# This will only be called if dir? is false, which means exists? is false.
|
20
|
-
raise ChefFS::FileSystem::
|
21
|
+
raise ChefFS::FileSystem::NotFoundError, "#{path_for_printing} not found"
|
21
22
|
end
|
22
23
|
|
23
24
|
def exists?
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'chef_fs/file_system/base_fs_dir'
|
2
2
|
require 'chef_fs/file_system/rest_list_dir'
|
3
|
+
require 'chef_fs/file_system/not_found_error'
|
3
4
|
require 'chef_fs/path_utils'
|
4
5
|
|
5
6
|
module ChefFS
|
@@ -17,7 +18,7 @@ module ChefFS
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def children
|
20
|
-
@children ||= Dir.entries(file_path).select { |entry| entry
|
21
|
+
@children ||= Dir.entries(file_path).select { |entry| entry != '.' && entry != '..' }.map { |entry| FileSystemEntry.new(entry, self) }
|
21
22
|
end
|
22
23
|
|
23
24
|
def dir?
|
@@ -27,8 +28,8 @@ module ChefFS
|
|
27
28
|
def read
|
28
29
|
begin
|
29
30
|
IO.read(file_path)
|
30
|
-
rescue
|
31
|
-
raise
|
31
|
+
rescue IONotFoundError # TODO real exception
|
32
|
+
raise ChefFS::FileSystem::NotFoundError.new($!), "#{path_for_printing} not found"
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'chef_fs/file_system/base_fs_object'
|
2
|
+
require 'chef_fs/file_system/not_found_error'
|
2
3
|
|
3
4
|
module ChefFS
|
4
5
|
module FileSystem
|
@@ -11,12 +12,8 @@ module ChefFS
|
|
11
12
|
false
|
12
13
|
end
|
13
14
|
|
14
|
-
def child(name)
|
15
|
-
NonexistentFSObject.new(name, self)
|
16
|
-
end
|
17
|
-
|
18
15
|
def read
|
19
|
-
raise ChefFS::FileSystem::
|
16
|
+
raise ChefFS::FileSystem::NotFoundError, "Nonexistent #{path_for_printing}"
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'chef_fs/file_system/base_fs_dir'
|
2
2
|
require 'chef_fs/file_system/rest_list_entry'
|
3
|
+
require 'chef_fs/file_system/not_found_error'
|
3
4
|
|
4
5
|
# TODO: take environment into account
|
5
6
|
|
@@ -18,12 +19,16 @@ module ChefFS
|
|
18
19
|
result || RestListEntry.new(name, self)
|
19
20
|
end
|
20
21
|
|
22
|
+
def can_have_child?(name, is_dir)
|
23
|
+
name =~ /\.json$/ && !is_dir
|
24
|
+
end
|
25
|
+
|
21
26
|
def children
|
22
27
|
begin
|
23
28
|
@children ||= rest.get_rest(api_path).keys.map { |key| RestListEntry.new("#{key}.json", self, true) }
|
24
29
|
rescue Net::HTTPServerException
|
25
30
|
if $!.response.code == "404"
|
26
|
-
raise ChefFS::FileSystem::
|
31
|
+
raise ChefFS::FileSystem::NotFoundError.new($!), "#{path_for_printing} not found"
|
27
32
|
else
|
28
33
|
raise
|
29
34
|
end
|