knife-essentials 0.3.1 → 0.4

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.
@@ -12,12 +12,30 @@ class Chef
12
12
  :default => true,
13
13
  :description => "List directories recursively."
14
14
 
15
+ option :name_only,
16
+ :long => '--name-only',
17
+ :boolean => true,
18
+ :description => "Only show names of modified files."
19
+
20
+ option :name_status,
21
+ :long => '--name-status',
22
+ :boolean => true,
23
+ :description => "Only show names and statuses of modified files: Added, Deleted, Modified, and Type Changed."
24
+
25
+ common_options
26
+
15
27
  def run
28
+ if config[:name_only]
29
+ output_mode = :name_only
30
+ end
31
+ if config[:name_status]
32
+ output_mode = :name_status
33
+ end
16
34
  patterns = pattern_args_from(name_args.length > 0 ? name_args : [ "" ])
17
35
 
18
36
  # Get the matches (recursively)
19
37
  patterns.each do |pattern|
20
- ChefFS::CommandLine.diff(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1) do |diff|
38
+ ChefFS::CommandLine.diff(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1, output_mode) do |diff|
21
39
  puts diff
22
40
  end
23
41
  end
@@ -2,11 +2,11 @@ require 'chef_fs/diff'
2
2
 
3
3
  module ChefFS
4
4
  module CommandLine
5
- def self.diff(pattern, a_root, b_root, recurse_depth)
5
+ def self.diff(pattern, a_root, b_root, recurse_depth, output_mode)
6
6
  found_result = false
7
7
  ChefFS::Diff::diffable_leaves_from_pattern(pattern, a_root, b_root, recurse_depth) do |a_leaf, b_leaf|
8
8
  found_result = true
9
- diff = diff_leaves(a_leaf, b_leaf)
9
+ diff = diff_leaves(a_leaf, b_leaf, output_mode)
10
10
  yield diff if diff != ''
11
11
  end
12
12
  if !found_result && pattern.exact_path
@@ -17,27 +17,53 @@ module ChefFS
17
17
  private
18
18
 
19
19
  # Diff two known leaves (could be files or dirs)
20
- def self.diff_leaves(old_file, new_file)
20
+ def self.diff_leaves(old_file, new_file, output_mode)
21
21
  result = ''
22
22
  # If both are directories
23
23
  # If old is a directory and new is a file
24
24
  # If old is a directory and new does not exist
25
25
  if old_file.dir?
26
26
  if new_file.dir?
27
- result << "Common subdirectories: #{old_file.path}\n"
27
+ if output_mode != :name_only && output_mode != :name_status
28
+ result << "Common subdirectories: #{old_file.path}\n"
29
+ end
28
30
  elsif new_file.exists?
29
- result << "File #{new_file.path_for_printing} is a directory while file #{new_file.path_for_printing} is a regular file\n"
31
+ if output_mode == :name_only
32
+ result << "#{new_file.path_for_printing}\n"
33
+ elsif output_mode == :name_status
34
+ result << "T\t#{new_file.path_for_printing}\n"
35
+ else
36
+ result << "File #{new_file.path_for_printing} is a directory while file #{new_file.path_for_printing} is a regular file\n"
37
+ end
30
38
  elsif new_file.parent.can_have_child?(old_file.name, old_file.dir?)
31
- result << "Only in #{old_file.parent.path_for_printing}: #{old_file.name}\n"
39
+ if output_mode == :name_only
40
+ result << "#{new_file.path_for_printing}\n"
41
+ elsif output_mode == :name_status
42
+ result << "D\t#{new_file.path_for_printing}\n"
43
+ else
44
+ result << "Only in #{old_file.parent.path_for_printing}: #{old_file.name}\n"
45
+ end
32
46
  end
33
47
 
34
48
  # If new is a directory and old does not exist
35
49
  # If new is a directory and old is a file
36
50
  elsif new_file.dir?
37
51
  if old_file.exists?
38
- result << "File #{old_file.path_for_printing} is a regular file while file #{old_file.path_for_printing} is a directory\n"
52
+ if output_mode == :name_only
53
+ result << "#{new_file.path_for_printing}\n"
54
+ elsif output_mode == :name_status
55
+ result << "T\t#{new_file.path_for_printing}\n"
56
+ else
57
+ result << "File #{old_file.path_for_printing} is a regular file while file #{old_file.path_for_printing} is a directory\n"
58
+ end
39
59
  elsif old_file.parent.can_have_child?(new_file.name, new_file.dir?)
40
- result << "Only in #{new_file.parent.path_for_printing}: #{new_file.name}\n"
60
+ if output_mode == :name_only
61
+ result << "#{new_file.path_for_printing}\n"
62
+ elsif output_mode == :name_status
63
+ result << "A\t#{new_file.path_for_printing}\n"
64
+ else
65
+ result << "Only in #{new_file.parent.path_for_printing}: #{new_file.name}\n"
66
+ end
41
67
  end
42
68
 
43
69
  else
@@ -45,7 +71,7 @@ module ChefFS
45
71
  different, old_value, new_value = ChefFS::Diff::diff_files(old_file, new_file)
46
72
  if different
47
73
  # If one of the files doesn't exist, we only want to print the diff if the
48
- # other file *could be synced*.
74
+ # other file *could be uploaded/downloaded*.
49
75
  if !old_value && !old_file.parent.can_have_child?(new_file.name, new_file.dir?)
50
76
  return result
51
77
  end
@@ -53,20 +79,32 @@ module ChefFS
53
79
  return result
54
80
  end
55
81
 
56
- old_path = old_file.path_for_printing
57
- new_path = new_file.path_for_printing
58
- result << "diff --knife #{old_path} #{new_path}\n"
59
- if !old_value
60
- result << "new file\n"
61
- old_path = "/dev/null"
62
- old_value = ''
63
- end
64
- if !new_value
65
- result << "deleted file\n"
66
- new_path = "/dev/null"
67
- new_value = ''
82
+ if output_mode == :name_only
83
+ result << "#{new_file.path_for_printing}\n"
84
+ elsif output_mode == :name_status
85
+ if !old_value
86
+ result << "A\t#{new_file.path_for_printing}\n"
87
+ elsif !new_value
88
+ result << "D\t#{new_file.path_for_printing}\n"
89
+ else
90
+ result << "M\t#{new_file.path_for_printing}\n"
91
+ end
92
+ else
93
+ old_path = old_file.path_for_printing
94
+ new_path = new_file.path_for_printing
95
+ result << "diff --knife #{old_path} #{new_path}\n"
96
+ if !old_value
97
+ result << "new file\n"
98
+ old_path = "/dev/null"
99
+ old_value = ''
100
+ end
101
+ if !new_value
102
+ result << "deleted file\n"
103
+ new_path = "/dev/null"
104
+ new_value = ''
105
+ end
106
+ result << diff_text(old_path, new_path, old_value, new_value)
68
107
  end
69
- result << diff_text(old_path, new_path, old_value, new_value)
70
108
  end
71
109
  end
72
110
  return result
@@ -61,20 +61,20 @@ module ChefFS
61
61
  new_value = read_file_value(new_file) if new_value == :not_retrieved
62
62
 
63
63
  return false if old_value == new_value
64
- return false if old_value && new_value && !context_aware_diff(old_file, new_file, old_value, new_value)
64
+ return false if old_value && new_value && context_aware_diff(old_file, new_file, old_value, new_value) == false
65
65
  return [ true, old_value, new_value ]
66
66
  end
67
67
 
68
68
  def self.context_aware_diff(old_file, new_file, old_value, new_value)
69
- # TODO handle errors in reading JSON
70
69
  if old_file.content_type == :json || new_file.content_type == :json
71
- new_value = Chef::JSONCompat.from_json(new_value).to_hash
72
- old_value = Chef::JSONCompat.from_json(old_value).to_hash
73
-
74
- old_value != new_value
75
- else
76
- true
70
+ begin
71
+ new_value = Chef::JSONCompat.from_json(new_value).to_hash
72
+ old_value = Chef::JSONCompat.from_json(old_value).to_hash
73
+ return old_value != new_value
74
+ rescue JSON::ParserError
75
+ end
77
76
  end
77
+ return nil
78
78
  end
79
79
 
80
80
  # Gets all common leaves, recursively, starting from the results of
@@ -7,12 +7,13 @@ require 'chef_fs/file_system/nodes_dir'
7
7
  module ChefFS
8
8
  module FileSystem
9
9
  class ChefServerRootDir < BaseFSDir
10
- def initialize(root_name, config)
10
+ def initialize(root_name, chef_config, repo_mode)
11
11
  super("", nil)
12
- @chef_server_url = config[:chef_server_url]
13
- @chef_username = config[:node_name]
14
- @chef_private_key = config[:client_key]
15
- @environment = config[:environment]
12
+ @chef_server_url = chef_config[:chef_server_url]
13
+ @chef_username = chef_config[:node_name]
14
+ @chef_private_key = chef_config[:client_key]
15
+ @environment = chef_config[:environment]
16
+ @repo_mode = repo_mode
16
17
  @root_name = root_name
17
18
  end
18
19
 
@@ -20,6 +21,7 @@ module ChefFS
20
21
  attr_reader :chef_username
21
22
  attr_reader :chef_private_key
22
23
  attr_reader :environment
24
+ attr_reader :repo_mode
23
25
 
24
26
  def rest
25
27
  Chef::REST.new(chef_server_url, chef_username, chef_private_key)
@@ -38,15 +40,21 @@ module ChefFS
38
40
  end
39
41
 
40
42
  def children
41
- @children ||= [
42
- RestListDir.new("clients", self),
43
- CookbooksDir.new(self),
44
- DataBagsDir.new(self),
45
- RestListDir.new("environments", self),
46
- NodesDir.new(self),
47
- RestListDir.new("roles", self),
48
- # RestListDir.new("sandboxes", self)
49
- ]
43
+ @children ||= begin
44
+ result = [
45
+ CookbooksDir.new(self),
46
+ DataBagsDir.new(self),
47
+ RestListDir.new("environments", self),
48
+ RestListDir.new("roles", self)
49
+ ]
50
+ if repo_mode == 'everything'
51
+ result += [
52
+ RestListDir.new("clients", self),
53
+ NodesDir.new(self)
54
+ ]
55
+ end
56
+ result.sort_by { |child| child.name }
57
+ end
50
58
  end
51
59
  end
52
60
  end
@@ -1,7 +1,5 @@
1
1
  require 'chef_fs/file_system/base_fs_dir'
2
2
 
3
- # TODO: take environment into account
4
-
5
3
  module ChefFS
6
4
  module FileSystem
7
5
  class CookbookSubdir < BaseFSDir
@@ -6,12 +6,19 @@ require 'chef/config'
6
6
 
7
7
  module ChefFS
8
8
  class Knife < Chef::Knife
9
+ def self.common_options
10
+ option :repo_mode,
11
+ :long => '--repo-mode MODE',
12
+ :default => "default",
13
+ :description => "Specifies the local repository layout. Values: default or full"
14
+ end
15
+
9
16
  def base_path
10
17
  @base_path ||= "/" + ChefFS::PathUtils::relative_to(File.absolute_path(Dir.pwd), chef_repo)
11
18
  end
12
19
 
13
20
  def chef_fs
14
- @chef_fs ||= ChefFS::FileSystem::ChefServerRootDir.new("remote", Chef::Config)
21
+ @chef_fs ||= ChefFS::FileSystem::ChefServerRootDir.new("remote", Chef::Config, config[:repo_mode])
15
22
  end
16
23
 
17
24
  def chef_repo
@@ -1,4 +1,4 @@
1
1
  module ChefFS
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4"
3
3
  end
4
4
 
@@ -136,7 +136,7 @@ describe ChefFS::Diff do
136
136
  end
137
137
  it 'ChefFS::CommandLine.diff(/)' do
138
138
  results = []
139
- ChefFS::CommandLine.diff(pattern('/'), a, b, nil) do |diff|
139
+ ChefFS::CommandLine.diff(pattern('/'), a, b, nil, nil) do |diff|
140
140
  results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
141
141
  end
142
142
  results.should =~ [
@@ -212,7 +212,7 @@ new file
212
212
  end
213
213
  it 'ChefFS::CommandLine.diff(/both_dirs)' do
214
214
  results = []
215
- ChefFS::CommandLine.diff(pattern('/both_dirs'), a, b, nil) do |diff|
215
+ ChefFS::CommandLine.diff(pattern('/both_dirs'), a, b, nil, nil) do |diff|
216
216
  results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
217
217
  end
218
218
  results.should =~ [
@@ -254,7 +254,7 @@ new file
254
254
  end
255
255
  it 'ChefFS::CommandLine.diff(/) with depth 1' do
256
256
  results = []
257
- ChefFS::CommandLine.diff(pattern('/'), a, b, 1) do |diff|
257
+ ChefFS::CommandLine.diff(pattern('/'), a, b, 1, nil) do |diff|
258
258
  results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
259
259
  end
260
260
  results.should =~ [
@@ -288,7 +288,7 @@ new file
288
288
  end
289
289
  it 'ChefFS::CommandLine.diff(/*_*) with depth 0' do
290
290
  results = []
291
- ChefFS::CommandLine.diff(pattern('/*_*'), a, b, 0) do |diff|
291
+ ChefFS::CommandLine.diff(pattern('/*_*'), a, b, 0, nil) do |diff|
292
292
  results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
293
293
  end
294
294
  results.should =~ [
@@ -320,5 +320,57 @@ new file
320
320
  +b_only_file
321
321
  ' ]
322
322
  end
323
+ it 'ChefFS::CommandLine.diff(/) in name-only mode' do
324
+ results = []
325
+ ChefFS::CommandLine.diff(pattern('/'), a, b, nil, :name_only) do |diff|
326
+ results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
327
+ end
328
+ results.should =~ [
329
+ "b/both_dirs/sub_both_files_different\n",
330
+ "b/both_dirs/sub_dirs_empty_in_b_filled_in_a/subsub\n",
331
+ "b/both_dirs/sub_dirs_empty_in_a_filled_in_b/subsub\n",
332
+ "b/both_dirs/sub_a_only_dir\n",
333
+ "b/both_dirs/sub_a_only_file\n",
334
+ "b/both_dirs/sub_b_only_dir\n",
335
+ "b/both_dirs/sub_b_only_file\n",
336
+ "b/both_dirs/sub_dir_in_a_file_in_b\n",
337
+ "b/both_dirs/sub_file_in_a_dir_in_b\n",
338
+ "b/both_files_different\n",
339
+ "b/dirs_empty_in_b_filled_in_a/subsub\n",
340
+ "b/dirs_empty_in_a_filled_in_b/subsub\n",
341
+ "b/a_only_dir\n",
342
+ "b/a_only_file\n",
343
+ "b/b_only_dir\n",
344
+ "b/b_only_file\n",
345
+ "b/dir_in_a_file_in_b\n",
346
+ "b/file_in_a_dir_in_b\n"
347
+ ]
348
+ end
349
+ it 'ChefFS::CommandLine.diff(/) in name-status mode' do
350
+ results = []
351
+ ChefFS::CommandLine.diff(pattern('/'), a, b, nil, :name_status) do |diff|
352
+ results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
353
+ end
354
+ results.should =~ [
355
+ "M\tb/both_dirs/sub_both_files_different\n",
356
+ "D\tb/both_dirs/sub_dirs_empty_in_b_filled_in_a/subsub\n",
357
+ "A\tb/both_dirs/sub_dirs_empty_in_a_filled_in_b/subsub\n",
358
+ "D\tb/both_dirs/sub_a_only_dir\n",
359
+ "D\tb/both_dirs/sub_a_only_file\n",
360
+ "A\tb/both_dirs/sub_b_only_dir\n",
361
+ "A\tb/both_dirs/sub_b_only_file\n",
362
+ "T\tb/both_dirs/sub_dir_in_a_file_in_b\n",
363
+ "T\tb/both_dirs/sub_file_in_a_dir_in_b\n",
364
+ "M\tb/both_files_different\n",
365
+ "D\tb/dirs_empty_in_b_filled_in_a/subsub\n",
366
+ "A\tb/dirs_empty_in_a_filled_in_b/subsub\n",
367
+ "D\tb/a_only_dir\n",
368
+ "D\tb/a_only_file\n",
369
+ "A\tb/b_only_dir\n",
370
+ "A\tb/b_only_file\n",
371
+ "T\tb/dir_in_a_file_in_b\n",
372
+ "T\tb/file_in_a_dir_in_b\n"
373
+ ]
374
+ end
323
375
  end
324
376
  end
@@ -22,7 +22,7 @@ describe ChefFS::FileSystem::ChefServerRootDir do
22
22
  endpoint_leaf.exists?.should be_true
23
23
  end
24
24
  it 'read returns content' do
25
- @rest.should_receive(:get_rest).with("#{endpoint_name}/#{endpoint_leaf_name}/environments/env").once.and_return(
25
+ @rest.should_receive(:get_rest).with("#{endpoint_name}/#{endpoint_leaf_name}").once.and_return(
26
26
  {
27
27
  'a' => 'b'
28
28
  })
@@ -101,7 +101,7 @@ describe ChefFS::FileSystem::ChefServerRootDir do
101
101
  nonexistent_child.dir?.should be_false
102
102
  end
103
103
  it 'read returns NotFoundError' do
104
- @rest.should_receive(:get_rest).with("#{endpoint_name}/blah/environments/env").once.and_raise(Net::HTTPServerException.new(nil,Net::HTTPResponse.new(nil,'404',nil)))
104
+ @rest.should_receive(:get_rest).with("#{endpoint_name}/blah").once.and_raise(Net::HTTPServerException.new(nil,Net::HTTPResponse.new(nil,'404',nil)))
105
105
  expect { nonexistent_child.read }.to raise_error(ChefFS::FileSystem::NotFoundError)
106
106
  end
107
107
  end
@@ -112,9 +112,8 @@ describe ChefFS::FileSystem::ChefServerRootDir do
112
112
  {
113
113
  :chef_server_url => 'url',
114
114
  :node_name => 'username',
115
- :client_key => 'key',
116
- :environment => 'env'
117
- })
115
+ :client_key => 'key'
116
+ }, 'everything')
118
117
  }
119
118
  before(:each) do
120
119
  @rest = double("rest")
@@ -7,9 +7,9 @@ describe ChefFS::FileSystem::CookbooksDir do
7
7
  {
8
8
  :chef_server_url => 'url',
9
9
  :node_name => 'username',
10
- :client_key => 'key',
11
- :environment => 'env'
12
- })
10
+ :client_key => 'key'
11
+ },
12
+ 'everything')
13
13
  }
14
14
  let(:cookbooks_dir) { root_dir.child('cookbooks') }
15
15
  let(:should_list_cookbooks) do
@@ -6,9 +6,8 @@ describe ChefFS::FileSystem::DataBagsDir do
6
6
  {
7
7
  :chef_server_url => 'url',
8
8
  :node_name => 'username',
9
- :client_key => 'key',
10
- :environment => 'env'
11
- })
9
+ :client_key => 'key'
10
+ }, 'everything')
12
11
  }
13
12
  let(:data_bags_dir) { root_dir.child('data_bags') }
14
13
  let(:should_list_data_bags) do
@@ -73,7 +72,7 @@ describe ChefFS::FileSystem::DataBagsDir do
73
72
  data_bag_item.path_for_printing.should == "remote/data_bags/#{data_bag_dir_name}/#{data_bag_item_name}"
74
73
  end
75
74
  it 'reads correctly' do
76
- @rest.should_receive(:get_rest).with("data/#{data_bag_dir_name}/#{data_bag_item_short_name}/environments/env").once.and_return({
75
+ @rest.should_receive(:get_rest).with("data/#{data_bag_dir_name}/#{data_bag_item_short_name}").once.and_return({
77
76
  'a' => 'b'
78
77
  })
79
78
  data_bag_item.read.should == '{
@@ -155,7 +154,7 @@ describe ChefFS::FileSystem::DataBagsDir do
155
154
  nonexistent_child.dir?.should be_false
156
155
  end
157
156
  it 'read returns NotFoundError' do
158
- @rest.should_receive(:get_rest).with("data/#{data_bag_dir_name}/blah/environments/env").once.and_raise(Net::HTTPServerException.new(nil,Net::HTTPResponse.new(nil,'404',nil)))
157
+ @rest.should_receive(:get_rest).with("data/#{data_bag_dir_name}/blah").once.and_raise(Net::HTTPServerException.new(nil,Net::HTTPResponse.new(nil,'404',nil)))
159
158
  expect { nonexistent_child.read }.to raise_error(ChefFS::FileSystem::NotFoundError)
160
159
  end
161
160
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-essentials
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: '0.4'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: