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.
- data/lib/chef/application.rb +13 -1
- data/lib/chef/application/client.rb +4 -2
- data/lib/chef/application/knife.rb +26 -2
- data/lib/chef/application/solo.rb +4 -3
- data/lib/chef/client.rb +2 -1
- data/lib/chef/cookbook_version.rb +2 -1
- data/lib/chef/knife.rb +129 -37
- data/lib/chef/knife/cookbook_metadata.rb +8 -3
- data/lib/chef/knife/cookbook_site_install.rb +3 -127
- data/lib/chef/knife/cookbook_site_vendor.rb +46 -0
- data/lib/chef/knife/cookbook_test.rb +13 -2
- data/lib/chef/knife/core/cookbook_scm_repo.rb +149 -0
- data/lib/chef/knife/core/generic_presenter.rb +184 -0
- data/lib/chef/knife/core/node_editor.rb +127 -0
- data/lib/chef/knife/core/node_presenter.rb +103 -0
- data/lib/chef/knife/core/object_loader.rb +75 -0
- data/lib/chef/knife/{subcommand_loader.rb → core/subcommand_loader.rb} +1 -1
- data/lib/chef/knife/core/text_formatter.rb +100 -0
- data/lib/chef/knife/{ui.rb → core/ui.rb} +53 -73
- data/lib/chef/knife/data_bag_from_file.rb +8 -2
- data/lib/chef/knife/environment_from_file.rb +14 -3
- data/lib/chef/knife/node_edit.rb +14 -105
- data/lib/chef/knife/node_from_file.rb +6 -1
- data/lib/chef/knife/node_show.rb +6 -0
- data/lib/chef/knife/role_from_file.rb +6 -1
- data/lib/chef/knife/search.rb +34 -19
- data/lib/chef/knife/status.rb +15 -1
- data/lib/chef/mixin/recipe_definition_dsl_core.rb +1 -4
- data/lib/chef/mixin/shell_out.rb +1 -0
- data/lib/chef/node.rb +17 -5
- data/lib/chef/resource.rb +42 -19
- data/lib/chef/rest.rb +14 -6
- data/lib/chef/rest/auth_credentials.rb +1 -1
- data/lib/chef/rest/rest_request.rb +26 -1
- data/lib/chef/runner.rb +2 -9
- data/lib/chef/version.rb +1 -1
- metadata +11 -7
- data/lib/chef/knife/bootstrap/client-install.vbs +0 -80
- data/lib/chef/knife/bootstrap/windows-gems.erb +0 -34
- 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
|
-
|
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[#{
|
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
|
-
|
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.
|
46
|
+
ui.info("Updated Environment #{updated.name}")
|
36
47
|
end
|
37
48
|
end
|
38
49
|
end
|
39
|
-
end
|
50
|
+
end
|
data/lib/chef/knife/node_edit.rb
CHANGED
@@ -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
|
-
|
146
|
-
|
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
|
156
|
-
@
|
157
|
-
|
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 =
|
38
|
+
updated = loader.load_from('nodes', @name_args[0])
|
34
39
|
|
35
40
|
updated.save
|
36
41
|
|
data/lib/chef/knife/node_show.rb
CHANGED
@@ -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 =
|
38
|
+
updated = loader.load_from("roles", @name_args[0])
|
34
39
|
|
35
40
|
updated.save
|
36
41
|
|
data/lib/chef/knife/search.rb
CHANGED
@@ -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
|
-
|
74
|
-
|
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
|
-
|
80
|
-
|
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
|
-
|
89
|
-
|
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
|
-
|
97
|
-
|
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.
|
117
|
+
ui.error("knife search failed: #{msg}")
|
102
118
|
exit 1
|
103
119
|
end
|
104
120
|
|
105
|
-
if
|
106
|
-
|
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
|
-
|
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
|
data/lib/chef/knife/status.rb
CHANGED
@@ -68,7 +68,21 @@ class Chef
|
|
68
68
|
text = minutes_text
|
69
69
|
end
|
70
70
|
|
71
|
-
|
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
|
-
|
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
|
data/lib/chef/mixin/shell_out.rb
CHANGED
data/lib/chef/node.rb
CHANGED
@@ -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 = {
|