chef 10.30.0.rc.1 → 10.30.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/distro/common/html/chef-client.8.html +4 -4
  2. data/distro/common/html/chef-expander.8.html +4 -4
  3. data/distro/common/html/chef-expanderctl.8.html +4 -4
  4. data/distro/common/html/chef-server-webui.8.html +4 -4
  5. data/distro/common/html/chef-server.8.html +4 -4
  6. data/distro/common/html/chef-solo.8.html +4 -4
  7. data/distro/common/html/chef-solr.8.html +4 -4
  8. data/distro/common/html/knife-bootstrap.1.html +4 -4
  9. data/distro/common/html/knife-client.1.html +4 -4
  10. data/distro/common/html/knife-configure.1.html +4 -4
  11. data/distro/common/html/knife-cookbook-site.1.html +4 -4
  12. data/distro/common/html/knife-cookbook.1.html +4 -4
  13. data/distro/common/html/knife-data-bag.1.html +4 -4
  14. data/distro/common/html/knife-environment.1.html +4 -4
  15. data/distro/common/html/knife-exec.1.html +4 -4
  16. data/distro/common/html/knife-index.1.html +4 -4
  17. data/distro/common/html/knife-node.1.html +4 -4
  18. data/distro/common/html/knife-role.1.html +4 -4
  19. data/distro/common/html/knife-search.1.html +4 -4
  20. data/distro/common/html/knife-ssh.1.html +4 -4
  21. data/distro/common/html/knife-status.1.html +4 -4
  22. data/distro/common/html/knife-tag.1.html +4 -4
  23. data/distro/common/html/knife.1.html +4 -4
  24. data/distro/common/html/shef.1.html +4 -4
  25. data/distro/common/man/man1/knife-bootstrap.1 +1 -1
  26. data/distro/common/man/man1/knife-client.1 +1 -1
  27. data/distro/common/man/man1/knife-configure.1 +1 -1
  28. data/distro/common/man/man1/knife-cookbook-site.1 +1 -1
  29. data/distro/common/man/man1/knife-cookbook.1 +1 -1
  30. data/distro/common/man/man1/knife-data-bag.1 +1 -1
  31. data/distro/common/man/man1/knife-environment.1 +1 -1
  32. data/distro/common/man/man1/knife-exec.1 +1 -1
  33. data/distro/common/man/man1/knife-index.1 +1 -1
  34. data/distro/common/man/man1/knife-node.1 +1 -1
  35. data/distro/common/man/man1/knife-role.1 +1 -1
  36. data/distro/common/man/man1/knife-search.1 +1 -1
  37. data/distro/common/man/man1/knife-ssh.1 +1 -1
  38. data/distro/common/man/man1/knife-status.1 +1 -1
  39. data/distro/common/man/man1/knife-tag.1 +1 -1
  40. data/distro/common/man/man1/knife.1 +1 -1
  41. data/distro/common/man/man1/shef.1 +1 -1
  42. data/distro/common/man/man8/chef-client.8 +1 -1
  43. data/distro/common/man/man8/chef-expander.8 +1 -1
  44. data/distro/common/man/man8/chef-expanderctl.8 +1 -1
  45. data/distro/common/man/man8/chef-server-webui.8 +1 -1
  46. data/distro/common/man/man8/chef-server.8 +1 -1
  47. data/distro/common/man/man8/chef-solo.8 +1 -1
  48. data/distro/common/man/man8/chef-solr.8 +1 -1
  49. data/lib/chef/knife/core/node_editor.rb +16 -36
  50. data/lib/chef/knife/core/ui.rb +9 -13
  51. data/lib/chef/mixin/deep_merge.rb +6 -1
  52. data/lib/chef/version.rb +1 -1
  53. data/spec/unit/knife/core/ui_spec.rb +118 -0
  54. data/spec/unit/knife/node_edit_spec.rb +33 -6
  55. metadata +2 -2
@@ -21,6 +21,7 @@
21
21
  require 'forwardable'
22
22
  require 'chef/platform'
23
23
  require 'chef/knife/core/generic_presenter'
24
+ require 'tempfile'
24
25
 
25
26
  class Chef
26
27
  class Knife
@@ -148,19 +149,14 @@ class Chef
148
149
  output = Chef::JSONCompat.to_json_pretty(data)
149
150
 
150
151
  if (!config[:disable_editing])
151
- filename = "knife-edit-"
152
- 0.upto(20) { filename += rand(9).to_s }
153
- filename << ".js"
154
- filename = File.join(Dir.tmpdir, filename)
155
- tf = File.open(filename, "w")
156
- tf.sync = true
157
- tf.puts output
158
- tf.close
159
- raise "Please set EDITOR environment variable" unless system("#{config[:editor]} #{tf.path}")
160
- tf = File.open(filename, "r")
161
- output = tf.gets(nil)
162
- tf.close
163
- File.unlink(filename)
152
+ Tempfile.open([ 'knife-edit-', '.json' ]) do |tf|
153
+ tf.sync = true
154
+ tf.puts output
155
+ tf.close
156
+ raise "Please set EDITOR environment variable" unless system("#{config[:editor]} #{tf.path}")
157
+
158
+ output = IO.read(tf.path)
159
+ end
164
160
  end
165
161
 
166
162
  parse_output ? Chef::JSONCompat.from_json(output) : output
@@ -146,7 +146,12 @@ class Chef
146
146
  # is not applicable anymore because it results in
147
147
  # duplicates when merging two array values with
148
148
  # :horizontal_precedence = true.
149
- dest[src_key] = deep_merge!(src_value, { }, options.merge(:debug_indent => di + ' '))
149
+ if src_value.nil?
150
+ # Nothing to compute with an extra deep_merge!
151
+ dest[src_key] = src_value
152
+ else
153
+ dest[src_key] = deep_merge!(src_value, { }, options.merge(:debug_indent => di + ' '))
154
+ end
150
155
  end
151
156
  else # dest isn't a hash, so we overwrite it completely (if permitted)
152
157
  if overwrite_unmergeable
@@ -17,7 +17,7 @@
17
17
 
18
18
  class Chef
19
19
  CHEF_ROOT = File.dirname(File.expand_path(File.dirname(__FILE__)))
20
- VERSION = '10.30.0.rc.1'
20
+ VERSION = '10.30.0.rc.2'
21
21
  end
22
22
 
23
23
  # NOTE: the Chef::Version class is defined in version_class.rb
@@ -27,6 +27,124 @@ describe Chef::Knife::UI do
27
27
  @ui = Chef::Knife::UI.new(@out, @err, @in, @config)
28
28
  end
29
29
 
30
+ describe "edit" do
31
+ ruby_for_json = { 'foo' => 'bar' }
32
+ json_from_ruby = "{\n \"foo\": \"bar\"\n}"
33
+ json_from_editor = "{\n \"bar\": \"foo\"\n}"
34
+ ruby_from_editor = { 'bar' => 'foo' }
35
+ my_editor = "veeeye"
36
+ temp_path = "/tmp/bar/baz"
37
+
38
+ let(:subject) { @ui.edit_data(ruby_for_json, parse_output) }
39
+ let(:parse_output) { false }
40
+
41
+ context "when editing is disabled" do
42
+ before do
43
+ @ui.config[:disable_editing] = true
44
+ stub_const("Tempfile", double) # Tempfiles should never be invoked
45
+ end
46
+ context "when parse_output is false" do
47
+ it "returns pretty json string" do
48
+ expect(subject).to eql(json_from_ruby)
49
+ end
50
+ end
51
+ context "when parse_output is true" do
52
+ let(:parse_output) { true }
53
+ it "returns a ruby object" do
54
+ expect(subject).to eql(ruby_for_json)
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ context "when editing is enabled" do
61
+ before do
62
+ @ui.config[:disable_editing] = false
63
+ @ui.config[:editor] = my_editor
64
+ @mock = mock('Tempfile')
65
+ @mock.should_receive(:sync=).with(true)
66
+ @mock.should_receive(:puts).with(json_from_ruby)
67
+ @mock.should_receive(:close)
68
+ @mock.should_receive(:path).at_least(:once).and_return(temp_path)
69
+ Tempfile.should_receive(:open).with([ 'knife-edit-', '.json' ]).and_yield(@mock)
70
+ end
71
+ context "and the editor works" do
72
+ before do
73
+ @ui.should_receive(:system).with("#{my_editor} #{temp_path}").and_return(true)
74
+ IO.should_receive(:read).with(temp_path).and_return(json_from_editor)
75
+ end
76
+
77
+ context "when parse_output is false" do
78
+ it "returns an edited pretty json string" do
79
+ expect(subject).to eql(json_from_editor)
80
+ end
81
+ end
82
+ context "when parse_output is true" do
83
+ let(:parse_output) { true }
84
+ it "returns an edited ruby object" do
85
+ expect(subject).to eql(ruby_from_editor)
86
+ end
87
+ end
88
+ end
89
+ context "when running the editor fails with nil" do
90
+ before do
91
+ @ui.should_receive(:system).with("#{my_editor} #{temp_path}").and_return(nil)
92
+ IO.should_not_receive(:read)
93
+ end
94
+ it "throws an exception" do
95
+ expect{ subject }.to raise_error(RuntimeError)
96
+ end
97
+ end
98
+ context "when running the editor fails with false" do
99
+ before do
100
+ @ui.should_receive(:system).with("#{my_editor} #{temp_path}").and_return(false)
101
+ IO.should_not_receive(:read)
102
+ end
103
+ it "throws an exception" do
104
+ expect{ subject }.to raise_error(RuntimeError)
105
+ end
106
+ end
107
+ end
108
+ context "when editing and not stubbing Tempfile (semi-functional test)" do
109
+ before do
110
+ @ui.config[:disable_editing] = false
111
+ @ui.config[:editor] = my_editor
112
+ @tempfile = Tempfile.new([ 'knife-edit-', '.json' ])
113
+ Tempfile.should_receive(:open).with([ 'knife-edit-', '.json' ]).and_yield(@tempfile)
114
+ end
115
+
116
+ context "and the editor works" do
117
+ before do
118
+ @ui.should_receive(:system).with("#{my_editor} #{@tempfile.path}").and_return(true)
119
+ IO.should_receive(:read).with(@tempfile.path).and_return(json_from_editor)
120
+ end
121
+
122
+ context "when parse_output is false" do
123
+ it "returns an edited pretty json string" do
124
+ expect(subject).to eql(json_from_editor)
125
+ end
126
+ it "the tempfile should have mode 0600" do
127
+ # XXX: this looks odd because we're really testing Tempfile.new here
128
+ expect(File.stat(@tempfile.path).mode & 0777).to eql(0600)
129
+ expect(subject).to eql(json_from_editor)
130
+ end
131
+ end
132
+
133
+ context "when parse_output is true" do
134
+ let(:parse_output) { true }
135
+ it "returns an edited ruby object" do
136
+ expect(subject).to eql(ruby_from_editor)
137
+ end
138
+ it "the tempfile should have mode 0600" do
139
+ # XXX: this looks odd because we're really testing Tempfile.new here
140
+ expect(File.stat(@tempfile.path).mode & 0777).to eql(0600)
141
+ expect(subject).to eql(ruby_from_editor)
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+
30
148
  describe "format_list_for_display" do
31
149
  it "should print the full hash if --with-uri is true" do
32
150
  @ui.config[:with_uri] = true
@@ -20,6 +20,12 @@ require 'spec_helper'
20
20
  Chef::Knife::NodeEdit.load_deps
21
21
 
22
22
  describe Chef::Knife::NodeEdit do
23
+
24
+ # helper to convert the view from Chef objects into Ruby objects representing JSON
25
+ def deserialized_json_view
26
+ actual = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json_pretty(@knife.node_editor.send(:view)))
27
+ end
28
+
23
29
  before(:each) do
24
30
  Chef::Config[:node_name] = "webmonkey.example.com"
25
31
  @knife = Chef::Knife::NodeEdit.new
@@ -49,7 +55,7 @@ describe Chef::Knife::NodeEdit do
49
55
  end
50
56
 
51
57
  it "creates a view of the node without attributes from roles or ohai" do
52
- actual = Chef::JSONCompat.from_json(@knife.node_editor.view)
58
+ actual = deserialized_json_view
53
59
  actual.should_not have_key("automatic")
54
60
  actual.should_not have_key("override")
55
61
  actual.should_not have_key("default")
@@ -61,7 +67,7 @@ describe Chef::Knife::NodeEdit do
61
67
  it "shows the extra attributes when given the --all option" do
62
68
  @knife.config[:all_attributes] = true
63
69
 
64
- actual = Chef::JSONCompat.from_json(@knife.node_editor.view)
70
+ actual = deserialized_json_view
65
71
  actual["automatic"].should == {"go" => "away"}
66
72
  actual["override"].should == {"dont" => "show"}
67
73
  actual["default"].should == {"hide" => "me"}
@@ -71,18 +77,39 @@ describe Chef::Knife::NodeEdit do
71
77
  end
72
78
 
73
79
  it "does not consider unedited data updated" do
74
- view = Chef::JSONCompat.from_json( @knife.node_editor.view )
75
- @knife.node_editor.apply_updates(view)
80
+ view = deserialized_json_view
81
+ @knife.node_editor.send(:apply_updates, view)
76
82
  @knife.node_editor.should_not be_updated
77
83
  end
78
84
 
79
85
  it "considers edited data updated" do
80
- view = Chef::JSONCompat.from_json( @knife.node_editor.view )
86
+ view = deserialized_json_view
81
87
  view["run_list"] << "role[fuuu]"
82
- @knife.node_editor.apply_updates(view)
88
+ @knife.node_editor.send(:apply_updates, view)
83
89
  @knife.node_editor.should be_updated
84
90
  end
85
91
 
86
92
  end
93
+
94
+ describe "edit_node" do
95
+
96
+ before do
97
+ @knife.stub!(:node).and_return(@node)
98
+ end
99
+
100
+ let(:subject) { @knife.node_editor.edit_node }
101
+
102
+ it "raises an exception when editing is disabled" do
103
+ @knife.config[:disable_editing] = true
104
+ expect{ subject }.to raise_error(SystemExit)
105
+ end
106
+
107
+ it "raises an exception when the editor is not set" do
108
+ @knife.config[:editor] = nil
109
+ expect{ subject }.to raise_error(SystemExit)
110
+ end
111
+
112
+ end
113
+
87
114
  end
88
115
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef
3
3
  version: !ruby/object:Gem::Version
4
- version: 10.30.0.rc.1
4
+ version: 10.30.0.rc.2
5
5
  prerelease: 8
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-26 00:00:00.000000000 Z
12
+ date: 2013-12-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mixlib-config