chef 0.9.8 → 0.9.10.rc.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/README.rdoc +1 -1
  2. data/distro/common/man/man8/knife.8 +89 -79
  3. data/distro/common/markdown/knife.mkd +7 -0
  4. data/distro/debian/etc/default/chef-server +3 -0
  5. data/distro/debian/etc/default/chef-server-webui +3 -0
  6. data/distro/debian/etc/default/chef-solr +3 -0
  7. data/distro/debian/etc/default/chef-solr-indexer +3 -0
  8. data/distro/debian/etc/init.d/chef-server +3 -1
  9. data/distro/debian/etc/init.d/chef-server-webui +3 -1
  10. data/distro/redhat/etc/init.d/chef-client +1 -1
  11. data/lib/chef/application.rb +2 -0
  12. data/lib/chef/application/client.rb +5 -3
  13. data/lib/chef/application/knife.rb +16 -5
  14. data/lib/chef/application/solo.rb +0 -1
  15. data/lib/chef/checksum.rb +65 -1
  16. data/lib/chef/checksum_cache.rb +173 -0
  17. data/lib/chef/client.rb +84 -121
  18. data/lib/chef/cookbook/remote_file_vendor.rb +10 -3
  19. data/lib/chef/cookbook/syntax_check.rb +2 -2
  20. data/lib/chef/cookbook_loader.rb +2 -0
  21. data/lib/chef/cookbook_site_streaming_uploader.rb +29 -0
  22. data/lib/chef/cookbook_uploader.rb +8 -7
  23. data/lib/chef/cookbook_version.rb +155 -114
  24. data/lib/chef/exceptions.rb +5 -0
  25. data/lib/chef/handler.rb +43 -0
  26. data/lib/chef/index_queue/consumer.rb +1 -1
  27. data/lib/chef/index_queue/indexable.rb +1 -1
  28. data/lib/chef/knife.rb +18 -5
  29. data/lib/chef/knife/bootstrap.rb +2 -2
  30. data/lib/chef/knife/bootstrap/archlinux-gems.erb +44 -0
  31. data/lib/chef/knife/bootstrap/client-install.vbs +80 -0
  32. data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
  33. data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +6 -7
  34. data/lib/chef/knife/bootstrap/windows-gems.erb +34 -0
  35. data/lib/chef/knife/configure_client.rb +4 -2
  36. data/lib/chef/knife/cookbook_metadata.rb +1 -1
  37. data/lib/chef/knife/cookbook_site_share.rb +2 -1
  38. data/lib/chef/knife/cookbook_site_vendor.rb +6 -0
  39. data/lib/chef/knife/cookbook_test.rb +1 -1
  40. data/lib/chef/knife/ec2_server_create.rb +51 -26
  41. data/lib/chef/knife/exec.rb +52 -0
  42. data/lib/chef/knife/ssh.rb +27 -15
  43. data/lib/chef/knife/status.rb +27 -10
  44. data/lib/chef/knife/windows_bootstrap.rb +154 -0
  45. data/lib/chef/mixin/checksum.rb +2 -2
  46. data/lib/chef/mixin/xml_escape.rb +75 -49
  47. data/lib/chef/node.rb +54 -58
  48. data/lib/chef/node/attribute.rb +61 -53
  49. data/lib/chef/platform.rb +19 -2
  50. data/lib/chef/provider/breakpoint.rb +1 -1
  51. data/lib/chef/provider/cookbook_file.rb +3 -3
  52. data/lib/chef/provider/cron.rb +3 -3
  53. data/lib/chef/provider/cron/solaris.rb +195 -0
  54. data/lib/chef/provider/deploy.rb +3 -3
  55. data/lib/chef/provider/directory.rb +2 -2
  56. data/lib/chef/provider/env.rb +5 -5
  57. data/lib/chef/provider/execute.rb +1 -1
  58. data/lib/chef/provider/file.rb +10 -9
  59. data/lib/chef/provider/git.rb +12 -4
  60. data/lib/chef/provider/group.rb +5 -5
  61. data/lib/chef/provider/http_request.rb +25 -9
  62. data/lib/chef/provider/ifconfig.rb +2 -2
  63. data/lib/chef/provider/link.rb +11 -6
  64. data/lib/chef/provider/log.rb +1 -0
  65. data/lib/chef/provider/mdadm.rb +3 -3
  66. data/lib/chef/provider/mount.rb +5 -5
  67. data/lib/chef/provider/mount/mount.rb +1 -1
  68. data/lib/chef/provider/ohai.rb +41 -0
  69. data/lib/chef/provider/package.rb +5 -5
  70. data/lib/chef/provider/package/yum-dump.py +5 -2
  71. data/lib/chef/provider/remote_directory.rb +11 -5
  72. data/lib/chef/provider/remote_file.rb +2 -2
  73. data/lib/chef/provider/route.rb +154 -133
  74. data/lib/chef/provider/ruby_block.rb +1 -1
  75. data/lib/chef/provider/service.rb +6 -6
  76. data/lib/chef/provider/subversion.rb +12 -9
  77. data/lib/chef/provider/template.rb +2 -2
  78. data/lib/chef/provider/user.rb +7 -7
  79. data/lib/chef/provider/user/useradd.rb +15 -1
  80. data/lib/chef/providers.rb +2 -0
  81. data/lib/chef/resource.rb +164 -58
  82. data/lib/chef/resource/http_request.rb +9 -0
  83. data/lib/chef/resource/ohai.rb +40 -0
  84. data/lib/chef/resource/remote_directory.rb +10 -1
  85. data/lib/chef/resource/rpm_package.rb +34 -0
  86. data/lib/chef/resource_collection.rb +3 -2
  87. data/lib/chef/resources.rb +2 -0
  88. data/lib/chef/rest.rb +13 -7
  89. data/lib/chef/rest/auth_credentials.rb +1 -1
  90. data/lib/chef/rest/rest_request.rb +3 -1
  91. data/lib/chef/runner.rb +31 -55
  92. data/lib/chef/shef/shef_session.rb +1 -1
  93. data/lib/chef/util/windows/net_use.rb +1 -1
  94. data/lib/chef/version.rb +1 -1
  95. data/lib/chef/webui_user.rb +0 -1
  96. metadata +38 -19
  97. data/lib/chef/cache.rb +0 -61
  98. data/lib/chef/cache/checksum.rb +0 -91
@@ -115,6 +115,13 @@ __ssh QUERY COMMAND__ _(options)_
115
115
 
116
116
  The _ssh_ sub-command opens an ssh session to each of the nodes in the search results of the _QUERY_. This sub-command requires that the net-ssh-multi and highline Ruby libraries are installed. On Debian systems, these are the libnet-ssh-multi-ruby and libhighline-ruby packages. They can also be installed as RubyGems (net-ssh-multi and highline, respectively).
117
117
 
118
+ __status__ _(options)_
119
+
120
+ * `-r`, `--run-list RUN_LIST`:
121
+ Show the run list
122
+
123
+ The _status_ sub-command searches the Chef Server for all nodes and displays information about the last time the node checked into the server and executed a `node.save`. The fields displayed are the relative checkin time, the node name, it's operating system platform and version, the fully-qualified domain name and the default IP address. If the `-r` option is given, the node's run list will also be displayed. Note that depending on the configuration of the nodes, the FQDN and IP displayed may not be publicly reachable.
124
+
118
125
  ## BOOTSTRAP SUB-COMMANDS
119
126
 
120
127
  __bootstrap FQDN__ _(options)_
@@ -4,3 +4,6 @@ ADAPTER=thin
4
4
  PORT=4000
5
5
  USER=chef
6
6
  GROUP=chef
7
+ # Sleep to give daemon enough time to fully start or stop.
8
+ STARTTIME=10
9
+ DIETIME=5
@@ -4,3 +4,6 @@ ADAPTER=thin
4
4
  PORT=4040
5
5
  USER=chef
6
6
  GROUP=chef
7
+ # Sleep to give daemon enough time to fully start or stop.
8
+ STARTTIME=10
9
+ DIETIME=5
@@ -2,3 +2,6 @@ LOGFILE=/var/log/chef/solr.log
2
2
  CONFIG=/etc/chef/solr.rb
3
3
  USER=chef
4
4
  GROUP=chef
5
+ # Sleep to give daemon enough time to fully start or stop.
6
+ DIETIME=5
7
+ STARTTIME=5
@@ -2,3 +2,6 @@ LOGFILE=/var/log/chef/solr-indexer.log
2
2
  CONFIG=/etc/chef/solr.rb
3
3
  USER=chef
4
4
  GROUP=chef
5
+ # Sleep to give daemon enough time to fully start or stop.
6
+ DIETIME=5
7
+ STARTTIME=5
@@ -57,7 +57,9 @@ stop_server() {
57
57
 
58
58
  reload_server() {
59
59
  stop_server
60
+ [ -n "$DIETIME" ] && sleep $DIETIME
60
61
  start_server
62
+ [ -n "$STARTTIME" ] && sleep $STARTTIME
61
63
  }
62
64
 
63
65
  case "$1" in
@@ -69,7 +71,7 @@ case "$1" in
69
71
  exit 0
70
72
  fi
71
73
  if start_server ; then
72
- sleep 1
74
+ [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time
73
75
  if running ; then
74
76
  log_end_msg 0
75
77
  else
@@ -58,7 +58,9 @@ stop_server() {
58
58
 
59
59
  reload_server() {
60
60
  stop_server
61
+ [ -n "$DIETIME" ] && sleep $DIETIME
61
62
  start_server
63
+ [ -n "$STARTTIME" ] && sleep $STARTTIME
62
64
  }
63
65
 
64
66
  case "$1" in
@@ -70,7 +72,7 @@ case "$1" in
70
72
  exit 0
71
73
  fi
72
74
  if start_server ; then
73
- sleep 1
75
+ [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time
74
76
  if running ; then
75
77
  log_end_msg 0
76
78
  else
@@ -35,7 +35,7 @@ start() {
35
35
  [ -x $exec ] || exit 5
36
36
  [ -f $config ] || exit 6
37
37
  echo -n $"Starting $prog: "
38
- daemon chef-client -d -c "$config" -L "$logfile" -i "$interval" -s "$splay" "$options"
38
+ daemon chef-client -d -c "$config" -L "$logfile" -p "$pidfile" -i "$interval" -s "$splay" "$options"
39
39
  retval=$?
40
40
  echo
41
41
  [ $retval -eq 0 ] && touch $lockfile
@@ -80,6 +80,8 @@ class Chef::Application
80
80
  Chef::Log.warn("Can not find config file: #{config[:config_file]}, using defaults.")
81
81
  Chef::Log.warn("#{error.message}")
82
82
  Chef::Log.warn("*****************************************")
83
+
84
+ Chef::Config.merge!(config)
83
85
  end
84
86
 
85
87
  end
@@ -149,6 +149,9 @@ class Chef::Application::Client < Chef::Application
149
149
 
150
150
  if Chef::Config[:daemonize]
151
151
  Chef::Config[:interval] ||= 1800
152
+ else
153
+ Chef::Config[:interval] = nil
154
+ Chef::Config[:splay] = nil
152
155
  end
153
156
 
154
157
  if Chef::Config[:json_attribs]
@@ -221,9 +224,8 @@ class Chef::Application::Client < Chef::Application
221
224
  raise
222
225
  rescue Exception => e
223
226
  if Chef::Config[:interval]
224
- Chef::Log.error("#{e.class}")
225
- Chef::Log.fatal("#{e}\n#{e.backtrace.join("\n")}")
226
- Chef::Log.fatal("Sleeping for #{Chef::Config[:interval]} seconds before trying again")
227
+ Chef::Log.error("#{e.class}:#{e}\n#{e.backtrace.join("\n")}")
228
+ Chef::Log.error("Sleeping for #{Chef::Config[:interval]} seconds before trying again")
227
229
  sleep Chef::Config[:interval]
228
230
  retry
229
231
  else
@@ -31,6 +31,8 @@ require 'uri'
31
31
 
32
32
  class Chef::Application::Knife < Chef::Application
33
33
 
34
+ NO_COMMAND_GIVEN = "You need to pass a sub-command (e.g., knife SUB-COMMAND)\n"
35
+
34
36
  banner "Usage: #{$0} sub-command (options)"
35
37
 
36
38
  option :config_file,
@@ -114,6 +116,7 @@ class Chef::Application::Knife < Chef::Application
114
116
 
115
117
  # Run knife
116
118
  def run
119
+ Mixlib::Log::Formatter.show_time = false
117
120
  validate_and_parse_options
118
121
  Chef::Knife.run(ARGV, options)
119
122
  exit 0
@@ -124,11 +127,15 @@ class Chef::Application::Knife < Chef::Application
124
127
  def validate_and_parse_options
125
128
  # Checking ARGV validity *before* parse_options because parse_options
126
129
  # mangles ARGV in some situations
127
- if no_subcommand_given?
128
- print_help_and_exit if want_help?
129
- print_help_and_exit(2, "Sorry, you need to pass a sub-command first!")
130
+ if no_command_given?
131
+ print_help_and_exit(1, NO_COMMAND_GIVEN)
132
+ elsif no_subcommand_given?
133
+ if (want_help? || want_version?)
134
+ print_help_and_exit
135
+ else
136
+ print_help_and_exit(2, NO_COMMAND_GIVEN)
137
+ end
130
138
  end
131
- print_help_and_exit if no_command_given?
132
139
  end
133
140
 
134
141
  def no_subcommand_given?
@@ -142,9 +149,13 @@ class Chef::Application::Knife < Chef::Application
142
149
  def want_help?
143
150
  ARGV[0] =~ /^(--help|-h)$/
144
151
  end
152
+
153
+ def want_version?
154
+ ARGV[0] =~ /^(--version|-v)$/
155
+ end
145
156
 
146
157
  def print_help_and_exit(exitcode=1, fatal_message=nil)
147
- Chef::Log.fatal(fatal_message) if fatal_message
158
+ Chef::Log.error(fatal_message) if fatal_message
148
159
 
149
160
  begin
150
161
  self.parse_options
@@ -187,7 +187,6 @@ class Chef::Application::Solo < Chef::Application
187
187
  end
188
188
 
189
189
  @chef_solo = Chef::Client.new(@chef_solo_json)
190
- @chef_solo_json = nil
191
190
  @chef_solo.run
192
191
  @chef_solo = nil
193
192
  if Chef::Config[:interval]
@@ -25,7 +25,13 @@ class Chef
25
25
  class Checksum
26
26
  attr_accessor :checksum, :create_time
27
27
  attr_accessor :couchdb_id, :couchdb_rev
28
-
28
+
29
+ # When a Checksum commits a sandboxed file to its final home in the checksum
30
+ # repo, this attribute will have the original on-disk path where the file
31
+ # was stored; it will be used if the commit is reverted to restore the sandbox
32
+ # to the pre-commit state.
33
+ attr_reader :original_committed_file_location
34
+
29
35
  DESIGN_DOCUMENT = {
30
36
  "version" => 1,
31
37
  "language" => "javascript",
@@ -52,6 +58,7 @@ class Chef
52
58
  def initialize(checksum=nil, couchdb=nil)
53
59
  @create_time = Time.now.iso8601
54
60
  @checksum = checksum
61
+ @original_committed_file_location = nil
55
62
  end
56
63
 
57
64
  def to_json(*a)
@@ -82,6 +89,51 @@ class Chef
82
89
  checksum
83
90
  end
84
91
 
92
+
93
+ ##
94
+ # On-Disk Checksum File Repo (Chef Server API)
95
+ ##
96
+
97
+ def file_location
98
+ File.join(checksum_repo_directory, checksum)
99
+ end
100
+
101
+ def checksum_repo_directory
102
+ File.join(Chef::Config.checksum_path, checksum[0..1])
103
+ end
104
+
105
+ # Moves the given +sandbox_file+ into the checksum repo using the path
106
+ # given by +file_location+ and saves the Checksum to the database
107
+ def commit_sandbox_file(sandbox_file)
108
+ @original_committed_file_location = sandbox_file
109
+ Chef::Log.info("commiting sandbox file: move #{sandbox_file} to #{file_location}")
110
+ FileUtils.mkdir_p(checksum_repo_directory)
111
+ File.rename(sandbox_file, file_location)
112
+ cdb_save
113
+ end
114
+
115
+ # Moves the checksum file back to its pre-commit location and deletes
116
+ # the checksum object from the database, effectively undoing +commit_sandbox_file+.
117
+ # Raises Chef::Exceptions::IllegalChecksumRevert if the original file location
118
+ # is unknown, which is will be the case if commit_sandbox_file was not
119
+ # previously called
120
+ def revert_sandbox_file_commit
121
+ unless original_committed_file_location
122
+ raise Chef::Exceptions::IllegalChecksumRevert, "Checksum #{self.inspect} cannot be reverted because the original sandbox file location is not known"
123
+ end
124
+
125
+ Chef::Log.warn("reverting sandbox file commit: moving #{file_location} back to #{original_committed_file_location}")
126
+ File.rename(file_location, original_committed_file_location)
127
+ cdb_destroy
128
+ end
129
+
130
+ # Removes the on-disk file backing this checksum object, then removes it
131
+ # from the database
132
+ def purge
133
+ purge_file
134
+ cdb_destroy
135
+ end
136
+
85
137
  ##
86
138
  # Couchdb
87
139
  ##
@@ -114,5 +166,17 @@ class Chef
114
166
  @couchdb_rev = (couchdb || Chef::CouchDB.new).store("checksum", checksum, self)["rev"]
115
167
  end
116
168
 
169
+
170
+ private
171
+
172
+ # Deletes the file backing this checksum from the on-disk repo.
173
+ # Purging the checksums is how users can get back to a valid state if
174
+ # they've deleted files, so we silently swallow Errno::ENOENT here.
175
+ def purge_file
176
+ FileUtils.rm(file_location)
177
+ rescue Errno::ENOENT
178
+ true
179
+ end
180
+
117
181
  end
118
182
  end
@@ -0,0 +1,173 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Daniel DeLeo (<dan@kallistec.com>)
4
+ # Copyright:: Copyright (c) 2009 Opscode, Inc.
5
+ # Copyright:: Copyright (c) 2009 Daniel DeLeo
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+
21
+ require 'set'
22
+ require 'fileutils'
23
+ require 'chef/log'
24
+ require 'chef/config'
25
+ require 'chef/client'
26
+ require 'chef/mixin/convert_to_class_name'
27
+ require 'singleton'
28
+ require 'moneta'
29
+
30
+ class Chef
31
+ class ChecksumCache
32
+ include Chef::Mixin::ConvertToClassName
33
+ include ::Singleton
34
+
35
+ attr_reader :moneta
36
+
37
+ def initialize(*args)
38
+ self.reset!(*args)
39
+ end
40
+
41
+ def reset!(backend=nil, options=nil)
42
+ backend ||= Chef::Config[:cache_type]
43
+ options ||= Chef::Config[:cache_options]
44
+
45
+ begin
46
+ require "moneta/#{convert_to_snake_case(backend, 'Moneta')}"
47
+ rescue LoadError => e
48
+ Chef::Log.fatal("Could not load Moneta back end #{backend.inspect}")
49
+ raise e
50
+ end
51
+
52
+ @moneta = Moneta.const_get(backend).new(options)
53
+ end
54
+
55
+ def self.reset_cache_validity
56
+ @valid_cached_checksums = nil
57
+ end
58
+
59
+ Chef::Client.when_run_starts do |run_status|
60
+ reset_cache_validity
61
+ end
62
+
63
+ def self.valid_cached_checksums
64
+ @valid_cached_checksums ||= Set.new
65
+ end
66
+
67
+ def self.validate_checksum(checksum_key)
68
+ valid_cached_checksums << checksum_key
69
+ end
70
+
71
+ def self.all_cached_checksums
72
+ all_checksums_with_filenames = {}
73
+
74
+ Dir[File.join(Chef::Config[:cache_options][:path], '*')].each do |cksum_file|
75
+ all_checksums_with_filenames[File.basename(cksum_file)] = cksum_file
76
+ end
77
+ all_checksums_with_filenames
78
+ end
79
+
80
+ def self.cleanup_checksum_cache
81
+ Chef::Log.info("cleaning the checksum cache")
82
+ if (Chef::Config[:cache_type].to_s == "BasicFile")
83
+ all_cached_checksums.each do |cache_key, cksum_cache_file|
84
+ unless valid_cached_checksums.include?(cache_key)
85
+ remove_unused_checksum(cksum_cache_file)
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ Chef::Client.when_run_completes_successfully do |run_status|
92
+ cleanup_checksum_cache
93
+ end
94
+
95
+ def self.remove_unused_checksum(checksum_file)
96
+ Chef::Log.debug("removing unused checksum cache file #{checksum_file}")
97
+ FileUtils.rm(checksum_file)
98
+ end
99
+
100
+ def self.checksum_for_file(*args)
101
+ instance.checksum_for_file(*args)
102
+ end
103
+
104
+ def validate_checksum(*args)
105
+ self.class.validate_checksum(*args)
106
+ end
107
+
108
+ def checksum_for_file(file, key=nil)
109
+ key ||= generate_key(file)
110
+ fstat = File.stat(file)
111
+ lookup_checksum(key, fstat) || generate_checksum(key, file, fstat)
112
+ end
113
+
114
+ def lookup_checksum(key, fstat)
115
+ cached = @moneta.fetch(key)
116
+ if cached && file_unchanged?(cached, fstat)
117
+ validate_checksum(key)
118
+ cached["checksum"]
119
+ else
120
+ nil
121
+ end
122
+ end
123
+
124
+ def generate_checksum(key, file, fstat)
125
+ checksum = checksum_file(file, Digest::SHA256.new)
126
+ moneta.store(key, {"mtime" => fstat.mtime.to_f, "checksum" => checksum})
127
+ validate_checksum(key)
128
+ checksum
129
+ end
130
+
131
+ def generate_key(file, group="chef")
132
+ "#{group}-file-#{file.gsub(/(#{File::SEPARATOR}|\.)/, '-')}"
133
+ end
134
+
135
+ def self.generate_md5_checksum_for_file(*args)
136
+ instance.generate_md5_checksum_for_file(*args)
137
+ end
138
+
139
+ def generate_md5_checksum_for_file(file)
140
+ checksum_file(file, Digest::MD5.new)
141
+ end
142
+
143
+ def generate_md5_checksum(io)
144
+ checksum_io(io, Digest::MD5.new)
145
+ end
146
+
147
+ private
148
+
149
+ def file_unchanged?(cached, fstat)
150
+ cached["mtime"].to_f == fstat.mtime.to_f
151
+ end
152
+
153
+ def checksum_file(file, digest)
154
+ File.open(file) { |f| checksum_io(f, digest) }
155
+ end
156
+
157
+ def checksum_io(io, digest)
158
+ while chunk = io.read(1024 * 8)
159
+ digest.update(chunk)
160
+ end
161
+ digest.hexdigest
162
+ end
163
+
164
+ end
165
+ end
166
+
167
+ module Moneta
168
+ module Defaults
169
+ def default
170
+ nil
171
+ end
172
+ end
173
+ end