chef 0.10.0.beta.5 → 0.10.0.beta.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/lib/chef/application.rb +13 -1
  2. data/lib/chef/application/client.rb +4 -2
  3. data/lib/chef/application/knife.rb +26 -2
  4. data/lib/chef/application/solo.rb +4 -3
  5. data/lib/chef/client.rb +2 -1
  6. data/lib/chef/cookbook_version.rb +2 -1
  7. data/lib/chef/knife.rb +129 -37
  8. data/lib/chef/knife/cookbook_metadata.rb +8 -3
  9. data/lib/chef/knife/cookbook_site_install.rb +3 -127
  10. data/lib/chef/knife/cookbook_site_vendor.rb +46 -0
  11. data/lib/chef/knife/cookbook_test.rb +13 -2
  12. data/lib/chef/knife/core/cookbook_scm_repo.rb +149 -0
  13. data/lib/chef/knife/core/generic_presenter.rb +184 -0
  14. data/lib/chef/knife/core/node_editor.rb +127 -0
  15. data/lib/chef/knife/core/node_presenter.rb +103 -0
  16. data/lib/chef/knife/core/object_loader.rb +75 -0
  17. data/lib/chef/knife/{subcommand_loader.rb → core/subcommand_loader.rb} +1 -1
  18. data/lib/chef/knife/core/text_formatter.rb +100 -0
  19. data/lib/chef/knife/{ui.rb → core/ui.rb} +53 -73
  20. data/lib/chef/knife/data_bag_from_file.rb +8 -2
  21. data/lib/chef/knife/environment_from_file.rb +14 -3
  22. data/lib/chef/knife/node_edit.rb +14 -105
  23. data/lib/chef/knife/node_from_file.rb +6 -1
  24. data/lib/chef/knife/node_show.rb +6 -0
  25. data/lib/chef/knife/role_from_file.rb +6 -1
  26. data/lib/chef/knife/search.rb +34 -19
  27. data/lib/chef/knife/status.rb +15 -1
  28. data/lib/chef/mixin/recipe_definition_dsl_core.rb +1 -4
  29. data/lib/chef/mixin/shell_out.rb +1 -0
  30. data/lib/chef/node.rb +17 -5
  31. data/lib/chef/resource.rb +42 -19
  32. data/lib/chef/rest.rb +14 -6
  33. data/lib/chef/rest/auth_credentials.rb +1 -1
  34. data/lib/chef/rest/rest_request.rb +26 -1
  35. data/lib/chef/runner.rb +2 -9
  36. data/lib/chef/version.rb +1 -1
  37. metadata +11 -7
  38. data/lib/chef/knife/bootstrap/client-install.vbs +0 -80
  39. data/lib/chef/knife/bootstrap/windows-gems.erb +0 -34
  40. data/lib/chef/knife/windows_bootstrap.rb +0 -157
@@ -26,6 +26,7 @@ class Chef
26
26
  deps do
27
27
  require 'chef/data_bag'
28
28
  require 'chef/data_bag_item'
29
+ require 'chef/knife/core/object_loader'
29
30
  require 'chef/json_compat'
30
31
  require 'chef/encrypted_data_bag_item'
31
32
  end
@@ -58,12 +59,17 @@ class Chef
58
59
  config[:secret] || config[:secret_file]
59
60
  end
60
61
 
62
+ def loader
63
+ @loader ||= Knife::Core::ObjectLoader.new(DataBagItem, ui)
64
+ end
65
+
61
66
  def run
62
67
  if @name_args.size != 2
63
68
  stdout.puts opt_parser
64
69
  exit(1)
65
70
  end
66
- item = load_from_file(Chef::DataBagItem, @name_args[1], @name_args[0])
71
+ @data_bag, @item_path = @name_args[0], @name_args[1]
72
+ item = loader.load_from("data_bags", @data_bag, @item_path)
67
73
  item = if use_encryption
68
74
  secret = read_secret
69
75
  Chef::EncryptedDataBagItem.encrypt_data_bag_item(item, secret)
@@ -74,7 +80,7 @@ class Chef
74
80
  dbag.data_bag(@name_args[0])
75
81
  dbag.raw_data = item
76
82
  dbag.save
77
- ui.info("Updated data_bag_item[#{@name_args[1]}]")
83
+ ui.info("Updated data_bag_item[#{dbag.data_bag}::#{dbag.id}]")
78
84
  end
79
85
  end
80
86
  end
@@ -20,8 +20,18 @@ class Chef
20
20
  class Knife
21
21
  class EnvironmentFromFile < Knife
22
22
 
23
+ deps do
24
+ require 'chef/environment'
25
+ require 'chef/knife/core/object_loader'
26
+ end
27
+
23
28
  banner "knife environment from file FILE (options)"
24
29
 
30
+ def loader
31
+ @loader ||= Knife::Core::ObjectLoader.new(Chef::Environment, ui)
32
+ end
33
+
34
+
25
35
  def run
26
36
  if @name_args[0].nil?
27
37
  show_usage
@@ -29,11 +39,12 @@ class Chef
29
39
  exit 1
30
40
  end
31
41
 
32
- updated = load_from_file(Chef::Environment, @name_args[0])
42
+
43
+ updated = loader.load_from("environments", @name_args[0])
33
44
  updated.save
34
45
  output(format_for_display(updated)) if config[:print_after]
35
- ui.warn("Updated Environment #{updated.name}!")
46
+ ui.info("Updated Environment #{updated.name}")
36
47
  end
37
48
  end
38
49
  end
39
- end
50
+ end
@@ -21,110 +21,14 @@ require 'chef/knife'
21
21
  class Chef
22
22
  class Knife
23
23
 
24
- module NodeEditController
25
- def edit_node
26
- abort "You specified the --no-editor option, nothing to edit" if config[:no_editor]
27
- assert_editor_set!
28
-
29
- updated_node_data = edit_data(view)
30
- apply_updates(updated_node_data)
31
- @updated_node
32
- end
33
-
34
- def view
35
- result = {}
36
- result["name"] = node.name
37
- result["chef_environment"] = node.chef_environment
38
- result["normal"] = node.normal_attrs
39
- result["run_list"] = node.run_list
40
-
41
- if config[:all_attributes]
42
- result["default"] = node.default_attrs
43
- result["override"] = node.override_attrs
44
- result["automatic"] = node.automatic_attrs
45
- end
46
- Chef::JSONCompat.to_json_pretty(result)
47
- end
48
-
49
- def edit_data(text)
50
- edited_data = tempfile_for(text) {|filename| system("#{config[:editor]} #{filename}")}
51
- Chef::JSONCompat.from_json(edited_data)
52
- end
53
-
54
- def apply_updates(updated_data)
55
- # TODO: should warn/error/ask for confirmation when changing the
56
- # name, since this results in a new node, not an edited node.
57
- @updated_node = Node.new.tap do |n|
58
- n.name( updated_data["name"] )
59
- n.chef_environment( updated_data["chef_environment"] )
60
- n.run_list( updated_data["run_list"])
61
- n.normal_attrs = updated_data["normal"]
62
-
63
- if config[:all_attributes]
64
- n.default_attrs = updated_data["default"]
65
- n.override_attrs = updated_data["override"]
66
- n.automatic_attrs = updated_data["automatic"]
67
- else
68
- n.default_attrs = node.default_attrs
69
- n.override_attrs = node.override_attrs
70
- n.automatic_attrs = node.automatic_attrs
71
- end
72
- end
73
- end
74
-
75
- def updated?
76
- pristine_copy = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(node), :create_additions => false)
77
- updated_copy = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(@updated_node), :create_additions => false)
78
- unless pristine_copy == updated_copy
79
- updated_properties = %w{name normal chef_environment run_list default override automatic}.reject do |key|
80
- pristine_copy[key] == updated_copy[key]
81
- end
82
- end
83
- ( pristine_copy != updated_copy ) && updated_properties
84
- end
85
-
86
- private
87
-
88
- def abort(message)
89
- STDERR.puts("ERROR: #{message}")
90
- exit 1
91
- end
92
-
93
- def assert_editor_set!
94
- unless config[:editor]
95
- abort "You must set your EDITOR environment variable or configure your editor via knife.rb"
96
- end
97
- end
98
-
99
- def tempfile_for(data)
100
- # TODO: include useful info like the node name in the temp file
101
- # name
102
- basename = "knife-edit-" << rand(1_000_000_000_000_000).to_s.rjust(15, '0') << '.js'
103
- filename = File.join(Dir.tmpdir, basename)
104
- File.open(filename, "w+") do |f|
105
- f.sync = true
106
- f.puts data
107
- end
108
-
109
- yield filename
110
-
111
- IO.read(filename)
112
- ensure
113
- File.unlink(filename)
114
- end
115
- end
116
-
117
24
  class NodeEdit < Knife
118
- include NodeEditController
119
25
 
120
26
  deps do
121
27
  require 'chef/node'
122
28
  require 'chef/json_compat'
29
+ require 'chef/knife/core/node_editor'
123
30
  end
124
31
 
125
- attr_reader :node_name
126
- attr_reader :node
127
-
128
32
  banner "knife node edit NODE (options)"
129
33
 
130
34
  option :all_attributes,
@@ -134,17 +38,14 @@ class Chef
134
38
  :description => "Display all attributes when editing"
135
39
 
136
40
  def run
137
- node_name = @name_args[0]
138
-
139
41
  if node_name.nil?
140
42
  show_usage
141
43
  ui.fatal("You must specify a node name")
142
44
  exit 1
143
45
  end
144
46
 
145
- load_node(node_name)
146
- updated_node = edit_node
147
- if updated_values = updated?
47
+ updated_node = node_editor.edit_node
48
+ if updated_values = node_editor.updated?
148
49
  ui.info "Saving updated #{updated_values.join(', ')} on node #{node.name}"
149
50
  updated_node.save
150
51
  else
@@ -152,10 +53,18 @@ class Chef
152
53
  end
153
54
  end
154
55
 
155
- def load_node(node_name)
156
- @node = Chef::Node.load(node_name)
157
- # TODO: rescue errors with a helpful message
56
+ def node_name
57
+ @node_name ||= @name_args[0]
58
+ end
59
+
60
+ def node_editor
61
+ @node_editor ||= Knife::NodeEditor.new(node, ui, config)
62
+ end
63
+
64
+ def node
65
+ @node ||= Chef::Node.load(node_name)
158
66
  end
67
+
159
68
  end
160
69
  end
161
70
  end
@@ -25,12 +25,17 @@ class Chef
25
25
  deps do
26
26
  require 'chef/node'
27
27
  require 'chef/json_compat'
28
+ require 'chef/knife/core/object_loader'
28
29
  end
29
30
 
30
31
  banner "knife node from file FILE (options)"
31
32
 
33
+ def loader
34
+ @loader ||= Knife::Core::ObjectLoader.new(Chef::Node, ui)
35
+ end
36
+
32
37
  def run
33
- updated = load_from_file(Chef::Node, @name_args[0])
38
+ updated = loader.load_from('nodes', @name_args[0])
34
39
 
35
40
  updated.save
36
41
 
@@ -17,11 +17,14 @@
17
17
  #
18
18
 
19
19
  require 'chef/knife'
20
+ require 'chef/knife/core/node_presenter'
20
21
 
21
22
  class Chef
22
23
  class Knife
23
24
  class NodeShow < Knife
24
25
 
26
+ include Knife::Core::NodeFormattingOptions
27
+
25
28
  deps do
26
29
  require 'chef/node'
27
30
  require 'chef/json_compat'
@@ -29,9 +32,11 @@ class Chef
29
32
 
30
33
  banner "knife node show NODE (options)"
31
34
 
35
+ attrs_to_show = []
32
36
  option :attribute,
33
37
  :short => "-a [ATTR]",
34
38
  :long => "--attribute [ATTR]",
39
+ :proc => lambda {|val| attrs_to_show << val},
35
40
  :description => "Show only one attribute"
36
41
 
37
42
  option :run_list,
@@ -45,6 +50,7 @@ class Chef
45
50
  :description => "Show only the Chef environment"
46
51
 
47
52
  def run
53
+ ui.use_presenter Knife::Core::NodePresenter
48
54
  @node_name = @name_args[0]
49
55
 
50
56
  if @node_name.nil?
@@ -24,13 +24,18 @@ class Chef
24
24
 
25
25
  deps do
26
26
  require 'chef/role'
27
+ require 'chef/knife/core/object_loader'
27
28
  require 'chef/json_compat'
28
29
  end
29
30
 
30
31
  banner "knife role from file FILE (options)"
31
32
 
33
+ def loader
34
+ @loader ||= Knife::Core::ObjectLoader.new(Chef::Role, ui)
35
+ end
36
+
32
37
  def run
33
- updated = load_from_file(Chef::Role, @name_args[0])
38
+ updated = loader.load_from("roles", @name_args[0])
34
39
 
35
40
  updated.save
36
41
 
@@ -24,8 +24,11 @@ class Chef
24
24
 
25
25
  deps do
26
26
  require 'chef/search/query'
27
+ require 'chef/knife/core/node_presenter'
27
28
  end
28
29
 
30
+ include Knife::Core::NodeFormattingOptions
31
+
29
32
  banner "knife search INDEX QUERY (options)"
30
33
 
31
34
  option :sort,
@@ -70,48 +73,60 @@ class Chef
70
73
 
71
74
  def run
72
75
  if config[:query] && @name_args[1]
73
- puts "please specify query as an argument or an option via -q, not both"
74
- puts opt_parser
76
+ ui.error "please specify query as an argument or an option via -q, not both"
77
+ ui.msg opt_parser
75
78
  exit 1
76
79
  end
77
80
  raw_query = config[:query] || @name_args[1]
78
81
  if !raw_query || raw_query.empty?
79
- puts "no query specified"
80
- puts opt_parser
82
+ ui.error "no query specified"
83
+ ui.msg opt_parser
84
+ exit 1
85
+ end
86
+
87
+ if name_args[0].nil?
88
+ ui.error "you must specify an item type to search for"
81
89
  exit 1
82
90
  end
83
91
 
92
+ if name_args[0] == 'node'
93
+ ui.use_presenter Knife::Core::NodePresenter
94
+ end
95
+
96
+
84
97
  q = Chef::Search::Query.new
85
- display = { :total => 0, :start => config[:start] ? config[:start] : 0, :rows => [ ] }
86
98
  query = URI.escape(raw_query,
87
99
  Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
88
- rows = config[:rows] ? config[:rows] : 20
89
- start = config[:start] ? config[:start] : 0
100
+
101
+ result_items = []
102
+ result_count = 0
103
+
104
+ rows = config[:rows]
105
+ start = config[:start]
90
106
  begin
91
107
  q.search(@name_args[0], query, config[:sort], start, rows) do |item|
92
108
  formatted_item = format_for_display(item)
93
109
  if formatted_item.respond_to?(:has_key?) && !formatted_item.has_key?('id')
94
110
  formatted_item['id'] = item.has_key?('id') ? item['id'] : item.name
95
111
  end
96
- display[:rows] << formatted_item
97
- display[:total] += 1
112
+ result_items << formatted_item
113
+ result_count += 1
98
114
  end
99
115
  rescue Net::HTTPServerException => e
100
116
  msg = Chef::JSONCompat.from_json(e.response.body)["error"].first
101
- ui.msg("knife search failed: #{msg}")
117
+ ui.error("knife search failed: #{msg}")
102
118
  exit 1
103
119
  end
104
120
 
105
- if config[:id_only]
106
- if config[:attribute]
107
- display[:rows].each do |row|
108
- puts row[config[:attribute]] if row.has_key?(config[:attribute]) && !row[config[:attribute]].nil?
109
- end
110
- else
111
- puts display[:rows].join("\n")
112
- end
121
+ if ui.interchange?
122
+ output({:results => result_count, :rows => result_items})
113
123
  else
114
- output(display)
124
+ ui.msg "#{result_count} items found"
125
+ ui.msg("\n")
126
+ result_items.each do |item|
127
+ output(item)
128
+ ui.msg("\n")
129
+ end
115
130
  end
116
131
  end
117
132
  end
@@ -68,7 +68,21 @@ class Chef
68
68
  text = minutes_text
69
69
  end
70
70
 
71
- highline.say("<%= color('#{text}', #{color}) %> ago, #{node.name}, #{node['platform']} #{node['platform_version']}, #{fqdn}, #{ipaddress}#{run_list}")
71
+ line_parts = Array.new
72
+ line_parts << "<%= color('#{text}', #{color}) %> ago" << node.name
73
+ line_parts << fqdn if fqdn
74
+ line_parts << ipaddress if ipaddress
75
+ line_parts << run_list if run_list
76
+
77
+ if node['platform']
78
+ platform = node['platform']
79
+ if node['platform_version']
80
+ platform << " #{node['platform_version']}"
81
+ end
82
+ line_parts << platform
83
+ end
84
+
85
+ highline.say(line_parts.join(', ') + '.')
72
86
  end
73
87
 
74
88
  end
@@ -61,10 +61,7 @@ class Chef
61
61
  resource = Chef::Resource.const_get(rname).new(*args)
62
62
  resource.load_prior_resource
63
63
  resource.cookbook_name = cookbook_name
64
- # TODO: 5/21/2010 cw/dan: do we need recipe_name for
65
- # anything? it's not even possible that this ivar is set on
66
- # Chef::Provider.
67
- # resource.recipe_name = @recipe_name
64
+ resource.recipe_name = @recipe_name
68
65
  resource.params = @params
69
66
  resource.source_line = caller[0]
70
67
  # Determine whether this resource is being created in the context of an enclosing Provider
@@ -16,6 +16,7 @@
16
16
  # limitations under the License.
17
17
 
18
18
  require 'chef/shell_out'
19
+ require 'chef/config'
19
20
 
20
21
  class Chef
21
22
  module Mixin
@@ -19,6 +19,7 @@
19
19
  # limitations under the License.
20
20
  #
21
21
 
22
+ require 'forwardable'
22
23
  require 'chef/config'
23
24
  require 'chef/cookbook/cookbook_collection'
24
25
  require 'chef/nil_argument'
@@ -39,6 +40,10 @@ require 'chef/json_compat'
39
40
  class Chef
40
41
  class Node
41
42
 
43
+ extend Forwardable
44
+
45
+ def_delegators :construct_attributes, :keys, :each_key, :each_value, :key?, :has_key?
46
+
42
47
  attr_accessor :recipe_list, :couchdb, :couchdb_rev, :run_state, :run_list
43
48
  attr_accessor :override_attrs, :default_attrs, :normal_attrs, :automatic_attrs
44
49
  attr_reader :couchdb_id
@@ -363,11 +368,6 @@ class Chef
363
368
  args.length > 0 ? @run_list.reset!(args) : @run_list
364
369
  end
365
370
 
366
- def recipes(*args)
367
- Chef::Log.warn "Chef::Node#recipes method is deprecated. Please use Chef::Node#run_list"
368
- run_list(*args)
369
- end
370
-
371
371
  # Returns true if this Node expects a given role, false if not.
372
372
  def run_list?(item)
373
373
  run_list.detect { |r| r == item } ? true : false
@@ -468,6 +468,18 @@ class Chef
468
468
  index_hash
469
469
  end
470
470
 
471
+ def display_hash
472
+ display = {}
473
+ display["name"] = name
474
+ display["chef_environment"] = chef_environment
475
+ display["automatic"] = automatic_attrs
476
+ display["normal"] = normal_attrs
477
+ display["default"] = default_attrs
478
+ display["override"] = override_attrs
479
+ display["run_list"] = run_list.run_list
480
+ display
481
+ end
482
+
471
483
  # Serialize this object as a hash
472
484
  def to_json(*a)
473
485
  result = {