summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Campbell <hikeit@gmail.com>2013-03-01 12:25:01 -0500
committerJesse Campbell <hikeit@gmail.com>2013-03-01 12:25:01 -0500
commita2faf73b16726fef02dd644437105d05c7700bf1 (patch)
tree3eff391b63dd9e9c496d34fff5f7be88ce630b49
parent2139a6888756fdcedce559c9e38a8ea76a5f7b54 (diff)
parent77f911b99e68bf1ae068ce79f70f670f52943b2e (diff)
downloadchef-a2faf73b16726fef02dd644437105d05c7700bf1.tar.gz
Merge branch 'master' into rest_client
Conflicts: lib/chef/provider/remote_file.rb lib/chef/provider/remote_file/ftp.rb lib/chef/providers.rb lib/chef/resource/remote_file.rb spec/unit/provider/remote_file/ftp_spec.rb spec/unit/provider/remote_file_spec.rb spec/unit/resource/remote_file_spec.rb
-rw-r--r--Gemfile5
-rw-r--r--README.md2
-rwxr-xr-xbin/chef-service-manager31
-rw-r--r--chef.gemspec14
-rw-r--r--ci/jenkins_run_tests.bat2
-rwxr-xr-xci/jenkins_run_tests.sh2
-rw-r--r--distro/common/html/chef-client.8.html6
-rw-r--r--distro/common/html/chef-expander.8.html6
-rw-r--r--distro/common/html/chef-expanderctl.8.html6
-rw-r--r--distro/common/html/chef-server-webui.8.html6
-rw-r--r--distro/common/html/chef-server.8.html6
-rw-r--r--distro/common/html/chef-shell.1.html6
-rw-r--r--distro/common/html/chef-solo.8.html6
-rw-r--r--distro/common/html/chef-solr.8.html6
-rw-r--r--distro/common/html/knife-bootstrap.1.html6
-rw-r--r--distro/common/html/knife-client.1.html8
-rw-r--r--distro/common/html/knife-configure.1.html6
-rw-r--r--distro/common/html/knife-cookbook-site.1.html12
-rw-r--r--distro/common/html/knife-cookbook.1.html6
-rw-r--r--distro/common/html/knife-data-bag.1.html6
-rw-r--r--distro/common/html/knife-environment.1.html12
-rw-r--r--distro/common/html/knife-exec.1.html6
-rw-r--r--distro/common/html/knife-index.1.html8
-rw-r--r--distro/common/html/knife-node.1.html6
-rw-r--r--distro/common/html/knife-role.1.html6
-rw-r--r--distro/common/html/knife-search.1.html6
-rw-r--r--distro/common/html/knife-ssh.1.html8
-rw-r--r--distro/common/html/knife-status.1.html6
-rw-r--r--distro/common/html/knife-tag.1.html6
-rw-r--r--distro/common/html/knife.1.html6
-rw-r--r--distro/common/man/man1/chef-shell.12
-rw-r--r--distro/common/man/man1/knife-bootstrap.12
-rw-r--r--distro/common/man/man1/knife-client.12
-rw-r--r--distro/common/man/man1/knife-configure.12
-rw-r--r--distro/common/man/man1/knife-cookbook-site.12
-rw-r--r--distro/common/man/man1/knife-cookbook.12
-rw-r--r--distro/common/man/man1/knife-data-bag.12
-rw-r--r--distro/common/man/man1/knife-environment.12
-rw-r--r--distro/common/man/man1/knife-exec.12
-rw-r--r--distro/common/man/man1/knife-index.12
-rw-r--r--distro/common/man/man1/knife-node.12
-rw-r--r--distro/common/man/man1/knife-role.12
-rw-r--r--distro/common/man/man1/knife-search.12
-rw-r--r--distro/common/man/man1/knife-ssh.12
-rw-r--r--distro/common/man/man1/knife-status.12
-rw-r--r--distro/common/man/man1/knife-tag.12
-rw-r--r--distro/common/man/man1/knife.12
-rw-r--r--distro/common/man/man8/chef-client.82
-rw-r--r--distro/common/man/man8/chef-expander.82
-rw-r--r--distro/common/man/man8/chef-expanderctl.82
-rw-r--r--distro/common/man/man8/chef-server-webui.82
-rw-r--r--distro/common/man/man8/chef-server.82
-rw-r--r--distro/common/man/man8/chef-solo.82
-rw-r--r--distro/common/man/man8/chef-solr.82
-rw-r--r--lib/chef/application.rb7
-rw-r--r--lib/chef/application/client.rb3
-rw-r--r--lib/chef/application/windows_service.rb168
-rw-r--r--lib/chef/application/windows_service_manager.rb165
-rw-r--r--lib/chef/cookbook_version.rb2
-rw-r--r--lib/chef/data_bag.rb2
-rw-r--r--lib/chef/exceptions.rb4
-rw-r--r--lib/chef/json_compat.rb99
-rw-r--r--lib/chef/knife/configure.rb29
-rw-r--r--lib/chef/knife/user_create.rb93
-rw-r--r--lib/chef/knife/user_delete.rb46
-rw-r--r--lib/chef/knife/user_edit.rb53
-rw-r--r--lib/chef/knife/user_list.rb42
-rw-r--r--lib/chef/knife/user_reregister.rb59
-rw-r--r--lib/chef/knife/user_show.rb52
-rw-r--r--lib/chef/log.rb4
-rw-r--r--lib/chef/mixin/windows_architecture_helper.rb91
-rw-r--r--lib/chef/monologger.rb93
-rw-r--r--lib/chef/platform.rb8
-rw-r--r--lib/chef/provider/batch.rb35
-rw-r--r--lib/chef/provider/package/rubygems.rb50
-rw-r--r--lib/chef/provider/powershell.rb35
-rw-r--r--lib/chef/provider/remote_file/ftp.rb2
-rw-r--r--lib/chef/provider/script.rb9
-rw-r--r--lib/chef/provider/windows_script.rb73
-rw-r--r--lib/chef/providers.rb2
-rw-r--r--lib/chef/resource.rb17
-rw-r--r--lib/chef/resource/batch.rb31
-rw-r--r--lib/chef/resource/powershell.rb31
-rw-r--r--lib/chef/resource/windows_script.rb62
-rw-r--r--lib/chef/resources.rb2
-rw-r--r--lib/chef/user.rb182
-rw-r--r--lib/chef/version.rb2
-rw-r--r--lib/chef/win32/api/process.rb1
-rw-r--r--lib/chef/win32/handle.rb9
-rw-r--r--spec/data/big_json.json3
-rw-r--r--spec/data/big_json_plus_one.json3
-rw-r--r--spec/functional/resource/batch_spec.rb70
-rw-r--r--spec/functional/resource/powershell_spec.rb40
-rw-r--r--spec/functional/run_lock_spec.rb194
-rw-r--r--spec/support/shared/unit/execute_resource.rb125
-rw-r--r--spec/support/shared/unit/script_resource.rb52
-rw-r--r--spec/support/shared/unit/windows_script_resource.rb48
-rw-r--r--spec/unit/application_spec.rb4
-rw-r--r--spec/unit/json_compat_spec.rb14
-rw-r--r--spec/unit/knife/configure_spec.rb49
-rw-r--r--spec/unit/knife/user_create_spec.rb86
-rw-r--r--spec/unit/knife/user_delete_spec.rb39
-rw-r--r--spec/unit/knife/user_edit_spec.rb42
-rw-r--r--spec/unit/knife/user_list_spec.rb32
-rw-r--r--spec/unit/knife/user_reregister_spec.rb53
-rw-r--r--spec/unit/knife/user_show_spec.rb41
-rw-r--r--spec/unit/mixin/windows_architecture_helper_spec.rb83
-rw-r--r--spec/unit/platform_spec.rb3
-rw-r--r--spec/unit/provider/package/rubygems_spec.rb12
-rw-r--r--spec/unit/provider/powershell_spec.rb38
-rw-r--r--spec/unit/provider/remote_file/ftp_spec.rb2
-rw-r--r--spec/unit/resource/batch_spec.rb48
-rw-r--r--spec/unit/resource/execute_spec.rb104
-rw-r--r--spec/unit/resource/powershell_spec.rb48
-rw-r--r--spec/unit/resource/script_spec.rb49
-rw-r--r--spec/unit/user_spec.rb255
116 files changed, 2952 insertions, 414 deletions
diff --git a/Gemfile b/Gemfile
index eff46bb579..dffdef67e8 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,7 +3,10 @@ source :rubygems
gemspec
gem "activesupport", :group => :compat_testing, :platform => "ruby"
-gem "ronn"
+
+group(:docgen) do
+ gem "ronn"
+end
group(:development, :test) do
gem 'rack', "~> 1.5.1"
diff --git a/README.md b/README.md
index a2431358f3..78328c4e1c 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Chef
-* Documentation: [http://wiki.opscode.com/display/chef/Home/](http://wiki.opscode.com/display/chef/Home/)
+* Documentation: [http://docs.opscode.com](http://docs.opscode.com)
* Source: [http://github.com/opscode/chef/tree/master](http://github.com/opscode/chef/tree/master)
* Tickets/Issues: [http://tickets.opscode.com](http://tickets.opscode.com)
* IRC: `#chef` and `#chef-hacking` on Freenode
diff --git a/bin/chef-service-manager b/bin/chef-service-manager
new file mode 100755
index 0000000000..c7f2fa43a9
--- /dev/null
+++ b/bin/chef-service-manager
@@ -0,0 +1,31 @@
+#!/usr/bin/env ruby
+#
+# ./chef-service-manager - Control chef-service on Windows platforms.
+#
+# Author:: Serdar Sutay (serdar@opscode.com)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'rubygems'
+$:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
+require 'chef'
+require 'chef/application/windows_service_manager'
+
+if Chef::Platform.windows?
+ Chef::Application::WindowsServiceManager.new.run
+else
+ puts "chef-service-manager is only available on Windows platforms."
+end
+
diff --git a/chef.gemspec b/chef.gemspec
index 9f97141aea..4e2f57af44 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -20,19 +20,25 @@ Gem::Specification.new do |s|
s.add_dependency "ohai", ">= 0.6.0"
s.add_dependency "rest-client", ">= 1.0.4", "< 1.7.0"
- s.add_dependency "json", ">= 1.4.4", "<= 1.6.1"
+
+ # The JSON gem reliably releases breaking changes as a patch release
+ s.add_dependency "json", ">= 1.4.4", "<= 1.7.7"
s.add_dependency "yajl-ruby", "~> 1.1"
- s.add_dependency "net-ssh", "~> 2.2.2"
+ s.add_dependency "net-ssh", "~> 2.6"
s.add_dependency "net-ssh-multi", "~> 1.1.0"
# CHEF-3027: The knife-cloud plugins require newer features from highline, core chef should not.
s.add_dependency "highline", ">= 1.6.9"
s.add_dependency "erubis"
- %w(rdoc sdoc ronn rake rack rspec_junit_formatter).each { |gem| s.add_development_dependency gem }
+ %w(rdoc sdoc rake rack rspec_junit_formatter).each { |gem| s.add_development_dependency gem }
%w(rspec-core rspec-expectations rspec-mocks).each { |gem| s.add_development_dependency gem, "~> 2.12.0" }
s.bindir = "bin"
- s.executables = %w( chef-client chef-solo knife chef-shell shef chef-apply )
+ # chef-service-manager is a windows only executable.
+ # However gemspec doesn't give us a way to have this executable only
+ # on windows. So we're including this in all platforms.
+ s.executables = %w( chef-client chef-solo knife chef-shell shef chef-apply chef-service-manager )
+
s.require_path = 'lib'
s.files = %w(Rakefile LICENSE README.md CONTRIBUTING.md) + Dir.glob("{distro,lib,tasks,spec}/**/*")
end
diff --git a/ci/jenkins_run_tests.bat b/ci/jenkins_run_tests.bat
index b5076949f3..4d1b1d1477 100644
--- a/ci/jenkins_run_tests.bat
+++ b/ci/jenkins_run_tests.bat
@@ -1,7 +1,7 @@
set PATH=C:\Ruby192\bin;%PATH%
ruby -v
-call bundle install --binstubs --path vendor/bundle || ( call rm Gemfile.lock && call bundle install --binstubs --path vendor/bundle )
+call bundle install --binstubs --without docgen --path vendor/bundle || ( call rm Gemfile.lock && call bundle install --binstubs --path vendor/bundle )
ruby bin\rspec -r rspec_junit_formatter -f RspecJunitFormatter -o test.xml -f documentation spec/functional spec/unit spec/stress
set RSPEC_ERRORLVL=%ERRORLEVEL%
diff --git a/ci/jenkins_run_tests.sh b/ci/jenkins_run_tests.sh
index 90a1fec0c8..9330d7cd07 100755
--- a/ci/jenkins_run_tests.sh
+++ b/ci/jenkins_run_tests.sh
@@ -5,7 +5,7 @@ export PATH=/usr/local/bin:$PATH
ruby -v;
# remove the Gemfile.lock and try again if bundler fails.
# This should take care of Gemfile changes that result in "bad" bundles without forcing us to rebundle every time
-bundle install --path vendor/bundle || ( rm Gemfile.lock && bundle install --path vendor/bundle )
+bundle install --without docgen --path vendor/bundle || ( rm Gemfile.lock && bundle install --path vendor/bundle )
bundle exec rspec -r rspec_junit_formatter -f RspecJunitFormatter -o test.xml -f documentation spec;
RSPEC_RETURNCODE=$?
diff --git a/distro/common/html/chef-client.8.html b/distro/common/html/chef-client.8.html
index 0f46109bb0..867e01fc2c 100644
--- a/distro/common/html/chef-client.8.html
+++ b/distro/common/html/chef-client.8.html
@@ -124,9 +124,9 @@ wiki, http://wiki.opscode.com/display/chef/Home.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p>Chef was written by Adam Jacob <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#x6f;&#58;&#x61;&#100;&#97;&#109;&#64;&#x6f;&#115;&#x70;&#99;&#x6f;&#x64;&#101;&#x2e;&#99;&#x6f;&#109;" data-bare-link="true">&#97;&#100;&#x61;&#x6d;&#x40;&#x6f;&#x73;&#x70;&#x63;&#x6f;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a> of Opscode
+<p>Chef was written by Adam Jacob <a data-bare-link="true" href="&#x6d;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#97;&#100;&#97;&#x6d;&#x40;&#x6f;&#x73;&#x70;&#x63;&#x6f;&#100;&#x65;&#x2e;&#99;&#x6f;&#109;">&#97;&#x64;&#x61;&#x6d;&#x40;&#111;&#x73;&#112;&#x63;&#111;&#100;&#x65;&#x2e;&#99;&#111;&#x6d;</a> of Opscode
(http://www.opscode.com), with contributions from the community. This
-manual page was written by Joshua Timberman <a href="&#x6d;&#97;&#x69;&#x6c;&#x74;&#x6f;&#58;&#106;&#x6f;&#x73;&#104;&#117;&#97;&#x40;&#111;&#112;&#x73;&#x63;&#x6f;&#x64;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#x6a;&#x6f;&#x73;&#x68;&#x75;&#97;&#64;&#x6f;&#112;&#x73;&#99;&#x6f;&#100;&#101;&#46;&#x63;&#111;&#x6d;</a> with
+manual page was written by Joshua Timberman <a data-bare-link="true" href="&#109;&#97;&#x69;&#x6c;&#x74;&#111;&#x3a;&#106;&#x6f;&#x73;&#x68;&#117;&#x61;&#64;&#x6f;&#112;&#x73;&#99;&#x6f;&#x64;&#x65;&#46;&#x63;&#111;&#x6d;">&#x6a;&#x6f;&#115;&#x68;&#x75;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#x6f;&#100;&#101;&#x2e;&#x63;&#x6f;&#x6d;</a> with
help2man. Permission is granted to copy, distribute and / or modify
this document under the terms of the Apache 2.0 License.</p>
@@ -135,7 +135,7 @@ found in /usr/share/common-licenses/Apache-2.0.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>chef-client(8)</li>
</ol>
diff --git a/distro/common/html/chef-expander.8.html b/distro/common/html/chef-expander.8.html
index d8afd7fe7a..1668b3fc73 100644
--- a/distro/common/html/chef-expander.8.html
+++ b/distro/common/html/chef-expander.8.html
@@ -143,9 +143,9 @@ wiki, http://wiki.opscode.com/display/chef/Home.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p>Chef was written by Adam Jacob <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#x6f;&#58;&#x61;&#100;&#97;&#109;&#64;&#x6f;&#115;&#x70;&#99;&#x6f;&#x64;&#101;&#x2e;&#99;&#x6f;&#109;" data-bare-link="true">&#97;&#100;&#x61;&#x6d;&#x40;&#x6f;&#x73;&#x70;&#x63;&#x6f;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a> of Opscode
+<p>Chef was written by Adam Jacob <a data-bare-link="true" href="&#x6d;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#97;&#100;&#97;&#x6d;&#x40;&#x6f;&#x73;&#x70;&#x63;&#x6f;&#100;&#x65;&#x2e;&#99;&#x6f;&#109;">&#97;&#x64;&#x61;&#x6d;&#x40;&#111;&#x73;&#112;&#x63;&#111;&#100;&#x65;&#x2e;&#99;&#111;&#x6d;</a> of Opscode
(http://www.opscode.com), with contributions from the community. This
-manual page was created by Nuo Yan <a href="&#x6d;&#97;&#x69;&#x6c;&#x74;&#x6f;&#58;&#110;&#x75;&#x6f;&#64;&#111;&#112;&#x73;&#99;&#111;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#110;&#117;&#x6f;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#100;&#x65;&#46;&#x63;&#111;&#x6d;</a>. Permission is
+manual page was created by Nuo Yan <a data-bare-link="true" href="&#109;&#97;&#x69;&#x6c;&#x74;&#111;&#x3a;&#110;&#x75;&#x6f;&#x40;&#111;&#x70;&#115;&#x63;&#111;&#x64;&#101;&#x2e;&#x63;&#x6f;&#109;">&#x6e;&#117;&#x6f;&#x40;&#x6f;&#112;&#x73;&#x63;&#111;&#x64;&#x65;&#x2e;&#x63;&#111;&#x6d;</a>. Permission is
granted to copy, distribute and / or modify this document under the
terms of the Apache 2.0 License.</p>
@@ -154,7 +154,7 @@ found in /usr/share/common-licenses/Apache-2.0.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>chef-expander(8)</li>
</ol>
diff --git a/distro/common/html/chef-expanderctl.8.html b/distro/common/html/chef-expanderctl.8.html
index c944dabf1a..cfe63ea536 100644
--- a/distro/common/html/chef-expanderctl.8.html
+++ b/distro/common/html/chef-expanderctl.8.html
@@ -125,9 +125,9 @@ wiki, http://wiki.opscode.com/display/chef/Home.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p>Chef was written by Adam Jacob <a href="&#109;&#97;&#x69;&#x6c;&#116;&#111;&#x3a;&#x61;&#100;&#x61;&#x6d;&#x40;&#x6f;&#115;&#112;&#x63;&#x6f;&#100;&#101;&#46;&#x63;&#111;&#x6d;" data-bare-link="true">&#97;&#100;&#97;&#x6d;&#x40;&#111;&#115;&#112;&#99;&#111;&#x64;&#101;&#x2e;&#x63;&#x6f;&#109;</a> of Opscode
+<p>Chef was written by Adam Jacob <a data-bare-link="true" href="&#x6d;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#97;&#100;&#97;&#x6d;&#x40;&#x6f;&#x73;&#x70;&#x63;&#x6f;&#100;&#x65;&#x2e;&#99;&#x6f;&#109;">&#97;&#x64;&#x61;&#x6d;&#x40;&#111;&#x73;&#112;&#x63;&#111;&#100;&#x65;&#x2e;&#99;&#111;&#x6d;</a> of Opscode
(http://www.opscode.com), with contributions from the community. This
-manual page was created by Nuo Yan <a href="&#109;&#97;&#x69;&#x6c;&#x74;&#111;&#x3a;&#x6e;&#x75;&#x6f;&#x40;&#111;&#112;&#x73;&#x63;&#x6f;&#100;&#x65;&#46;&#x63;&#x6f;&#109;" data-bare-link="true">&#x6e;&#117;&#x6f;&#64;&#111;&#112;&#115;&#x63;&#111;&#100;&#101;&#46;&#x63;&#x6f;&#109;</a>. Permission is
+manual page was created by Nuo Yan <a data-bare-link="true" href="&#109;&#97;&#x69;&#x6c;&#x74;&#111;&#x3a;&#110;&#x75;&#x6f;&#x40;&#111;&#x70;&#115;&#x63;&#111;&#x64;&#101;&#x2e;&#x63;&#x6f;&#109;">&#x6e;&#117;&#x6f;&#x40;&#x6f;&#112;&#x73;&#x63;&#111;&#x64;&#x65;&#x2e;&#x63;&#111;&#x6d;</a>. Permission is
granted to copy, distribute and / or modify this document under the
terms of the Apache 2.0 License.</p>
@@ -136,7 +136,7 @@ found in /usr/share/common-licenses/Apache-2.0.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>chef-expanderctl(8)</li>
</ol>
diff --git a/distro/common/html/chef-server-webui.8.html b/distro/common/html/chef-server-webui.8.html
index fa766a9cdf..8cd11313ac 100644
--- a/distro/common/html/chef-server-webui.8.html
+++ b/distro/common/html/chef-server-webui.8.html
@@ -163,9 +163,9 @@ is located on the Chef wiki, http://wiki.opscode.com/display/chef/Home.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p>Chef was written by Adam Jacob <a href="&#109;&#97;&#x69;&#x6c;&#116;&#111;&#x3a;&#x61;&#100;&#x61;&#x6d;&#x40;&#x6f;&#115;&#112;&#x63;&#x6f;&#100;&#101;&#46;&#x63;&#111;&#x6d;" data-bare-link="true">&#97;&#100;&#97;&#x6d;&#x40;&#111;&#115;&#112;&#99;&#111;&#x64;&#101;&#x2e;&#x63;&#x6f;&#109;</a> of Opscode
+<p>Chef was written by Adam Jacob <a data-bare-link="true" href="&#x6d;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#97;&#100;&#97;&#x6d;&#x40;&#x6f;&#x73;&#x70;&#x63;&#x6f;&#100;&#x65;&#x2e;&#99;&#x6f;&#109;">&#97;&#x64;&#x61;&#x6d;&#x40;&#111;&#x73;&#112;&#x63;&#111;&#100;&#x65;&#x2e;&#99;&#111;&#x6d;</a> of Opscode
(http://www.opscode.com), with contributions from the community. This
-manual page was written by Joshua Timberman <a href="&#109;&#97;&#x69;&#x6c;&#x74;&#111;&#x3a;&#x6a;&#x6f;&#x73;&#x68;&#117;&#97;&#x40;&#x6f;&#x70;&#115;&#x63;&#111;&#x64;&#x65;&#46;&#x63;&#111;&#x6d;" data-bare-link="true">&#106;&#111;&#115;&#104;&#x75;&#97;&#64;&#111;&#112;&#x73;&#x63;&#111;&#100;&#101;&#x2e;&#99;&#x6f;&#x6d;</a> with
+manual page was written by Joshua Timberman <a data-bare-link="true" href="&#109;&#97;&#x69;&#x6c;&#x74;&#111;&#x3a;&#106;&#x6f;&#x73;&#x68;&#117;&#x61;&#64;&#x6f;&#112;&#x73;&#99;&#x6f;&#x64;&#x65;&#46;&#x63;&#111;&#x6d;">&#x6a;&#x6f;&#115;&#x68;&#x75;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#x6f;&#100;&#101;&#x2e;&#x63;&#x6f;&#x6d;</a> with
help2man for the Debian project (but may be used by others). Permission
is granted to copy, distribute and / or modify this document under the
terms of the Apache 2.0 License.</p>
@@ -175,7 +175,7 @@ found in /usr/share/common-licenses/Apache-2.0.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>chef-server-webui(8)</li>
</ol>
diff --git a/distro/common/html/chef-server.8.html b/distro/common/html/chef-server.8.html
index 67a619a0bf..c4d5577e6d 100644
--- a/distro/common/html/chef-server.8.html
+++ b/distro/common/html/chef-server.8.html
@@ -161,9 +161,9 @@ wiki, http://wiki.opscode.com/display/chef/Home.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p>Chef was written by Adam Jacob <a href="&#109;&#97;&#x69;&#x6c;&#116;&#111;&#x3a;&#x61;&#100;&#x61;&#x6d;&#x40;&#x6f;&#115;&#112;&#x63;&#x6f;&#100;&#101;&#46;&#x63;&#111;&#x6d;" data-bare-link="true">&#97;&#100;&#97;&#x6d;&#x40;&#111;&#115;&#112;&#99;&#111;&#x64;&#101;&#x2e;&#x63;&#x6f;&#109;</a> of Opscode
+<p>Chef was written by Adam Jacob <a data-bare-link="true" href="&#x6d;&#x61;&#105;&#x6c;&#x74;&#x6f;&#x3a;&#x61;&#x64;&#97;&#x6d;&#64;&#111;&#x73;&#x70;&#99;&#111;&#100;&#x65;&#x2e;&#x63;&#x6f;&#109;">&#x61;&#x64;&#x61;&#x6d;&#x40;&#111;&#115;&#112;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#99;&#111;&#109;</a> of Opscode
(http://www.opscode.com), with contributions from the community. This
-manual page was written by Joshua Timberman <a href="&#109;&#97;&#x69;&#x6c;&#x74;&#111;&#x3a;&#x6a;&#x6f;&#x73;&#x68;&#117;&#97;&#x40;&#x6f;&#x70;&#115;&#x63;&#111;&#x64;&#x65;&#46;&#x63;&#111;&#x6d;" data-bare-link="true">&#106;&#111;&#115;&#104;&#x75;&#97;&#64;&#111;&#112;&#x73;&#x63;&#111;&#100;&#101;&#x2e;&#99;&#x6f;&#x6d;</a> with
+manual page was written by Joshua Timberman <a data-bare-link="true" href="&#x6d;&#97;&#x69;&#x6c;&#116;&#111;&#58;&#106;&#111;&#115;&#104;&#117;&#x61;&#x40;&#111;&#112;&#115;&#x63;&#x6f;&#x64;&#x65;&#46;&#x63;&#x6f;&#x6d;">&#106;&#111;&#115;&#104;&#117;&#x61;&#x40;&#x6f;&#112;&#115;&#x63;&#x6f;&#x64;&#101;&#x2e;&#x63;&#111;&#x6d;</a> with
help2man. Permission is granted to copy, distribute and / or modify
this document under the terms of the Apache 2.0 License.</p>
@@ -172,7 +172,7 @@ found in /usr/share/common-licenses/Apache-2.0.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>chef-server(8)</li>
</ol>
diff --git a/distro/common/html/chef-shell.1.html b/distro/common/html/chef-shell.1.html
index ab042518c0..220413ab87 100644
--- a/distro/common/html/chef-shell.1.html
+++ b/distro/common/html/chef-shell.1.html
@@ -260,13 +260,13 @@ libraries.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#x6d;&#97;&#105;&#108;&#116;&#x6f;&#x3a;&#97;&#x64;&#97;&#109;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#100;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#97;&#100;&#x61;&#109;&#64;&#111;&#112;&#115;&#x63;&#111;&#100;&#101;&#46;&#x63;&#x6f;&#109;</a> with many
+<p> Chef was written by Adam Jacob <a href="&#x6d;&#x61;&#x69;&#x6c;&#116;&#x6f;&#58;&#x61;&#100;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#101;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#97;&#x64;&#x61;&#109;&#64;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a> with many
contributions from the community. chef-shell was written by Daniel
DeLeo.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Daniel DeLeo <a href="&#109;&#x61;&#x69;&#x6c;&#116;&#111;&#58;&#x64;&#x61;&#110;&#64;&#x6f;&#112;&#x73;&#x63;&#x6f;&#x64;&#101;&#x2e;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#100;&#97;&#x6e;&#64;&#111;&#x70;&#115;&#99;&#111;&#100;&#x65;&#x2e;&#99;&#111;&#x6d;</a>.
+<p> This manual page was written by Daniel DeLeo <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#100;&#x61;&#110;&#x40;&#x6f;&#112;&#x73;&#x63;&#111;&#100;&#101;&#46;&#99;&#x6f;&#x6d;" data-bare-link="true">&#100;&#x61;&#110;&#x40;&#111;&#112;&#x73;&#x63;&#111;&#x64;&#101;&#46;&#99;&#x6f;&#109;</a>.
Permission is granted to copy, distribute and / or modify this
document under the terms of the Apache 2.0 License.</p>
@@ -276,7 +276,7 @@ libraries.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>chef-shell(1)</li>
</ol>
diff --git a/distro/common/html/chef-solo.8.html b/distro/common/html/chef-solo.8.html
index 7e9e7aac23..7c842cc67f 100644
--- a/distro/common/html/chef-solo.8.html
+++ b/distro/common/html/chef-solo.8.html
@@ -170,9 +170,9 @@ http://wiki.opscode.com/display/chef/Home.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p>Chef was written by Adam Jacob <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#x61;&#x64;&#x61;&#109;&#64;&#x6f;&#115;&#x70;&#99;&#x6f;&#100;&#101;&#46;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#x61;&#x64;&#x61;&#109;&#64;&#x6f;&#x73;&#x70;&#x63;&#x6f;&#100;&#101;&#46;&#99;&#x6f;&#109;</a> of Opscode
+<p>Chef was written by Adam Jacob <a href="&#x6d;&#x61;&#105;&#x6c;&#x74;&#x6f;&#x3a;&#x61;&#x64;&#97;&#x6d;&#64;&#111;&#x73;&#x70;&#99;&#111;&#100;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x61;&#x64;&#x61;&#x6d;&#x40;&#111;&#115;&#112;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#99;&#111;&#109;</a> of Opscode
(http://www.opscode.com), with contributions from the community. This
-manual page was written by Joshua Timberman <a href="&#x6d;&#97;&#105;&#x6c;&#116;&#111;&#x3a;&#106;&#111;&#x73;&#104;&#117;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#x2e;&#x63;&#111;&#109;" data-bare-link="true">&#x6a;&#111;&#x73;&#x68;&#117;&#x61;&#64;&#111;&#x70;&#115;&#99;&#111;&#x64;&#101;&#46;&#99;&#111;&#109;</a> with
+manual page was written by Joshua Timberman <a href="&#x6d;&#97;&#x69;&#x6c;&#116;&#111;&#58;&#106;&#111;&#115;&#104;&#117;&#x61;&#x40;&#111;&#112;&#115;&#x63;&#x6f;&#x64;&#x65;&#46;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#106;&#111;&#115;&#104;&#117;&#x61;&#x40;&#x6f;&#112;&#115;&#x63;&#x6f;&#x64;&#101;&#x2e;&#x63;&#111;&#x6d;</a> with
help2man. Permission is granted to copy, distribute and / or modify
this document under the terms of the Apache 2.0 License.</p>
@@ -181,7 +181,7 @@ found in /usr/share/common-licenses/Apache-2.0.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>chef-solo(8)</li>
</ol>
diff --git a/distro/common/html/chef-solr.8.html b/distro/common/html/chef-solr.8.html
index ffe7495dc3..45ed7c05dd 100644
--- a/distro/common/html/chef-solr.8.html
+++ b/distro/common/html/chef-solr.8.html
@@ -144,9 +144,9 @@ wiki, http://wiki.opscode.com/display/chef/Home.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p>Chef was written by Adam Jacob <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#x61;&#x64;&#x61;&#109;&#64;&#x6f;&#115;&#x70;&#99;&#x6f;&#100;&#101;&#46;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#x61;&#x64;&#x61;&#109;&#64;&#x6f;&#x73;&#x70;&#x63;&#x6f;&#100;&#101;&#46;&#99;&#x6f;&#109;</a> of Opscode
+<p>Chef was written by Adam Jacob <a href="&#x6d;&#x61;&#105;&#x6c;&#x74;&#x6f;&#x3a;&#x61;&#x64;&#97;&#x6d;&#64;&#111;&#x73;&#x70;&#99;&#111;&#100;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x61;&#x64;&#x61;&#x6d;&#x40;&#111;&#115;&#112;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#99;&#111;&#109;</a> of Opscode
(http://www.opscode.com), with contributions from the community. This
-manual page was written by Joshua Timberman <a href="&#x6d;&#97;&#105;&#x6c;&#116;&#111;&#x3a;&#106;&#111;&#x73;&#104;&#117;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#x2e;&#x63;&#111;&#109;" data-bare-link="true">&#x6a;&#111;&#x73;&#x68;&#117;&#x61;&#64;&#111;&#x70;&#115;&#99;&#111;&#x64;&#101;&#46;&#99;&#111;&#109;</a> with
+manual page was written by Joshua Timberman <a href="&#x6d;&#97;&#x69;&#x6c;&#116;&#111;&#58;&#106;&#111;&#115;&#104;&#117;&#x61;&#x40;&#111;&#112;&#115;&#x63;&#x6f;&#x64;&#x65;&#46;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#106;&#111;&#115;&#104;&#117;&#x61;&#x40;&#x6f;&#112;&#115;&#x63;&#x6f;&#x64;&#101;&#x2e;&#x63;&#111;&#x6d;</a> with
help2man. Permission is granted to copy, distribute and / or modify
this document under the terms of the Apache 2.0 License.</p>
@@ -155,7 +155,7 @@ found in /usr/share/common-licenses/Apache-2.0.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>chef-solr(8)</li>
</ol>
diff --git a/distro/common/html/knife-bootstrap.1.html b/distro/common/html/knife-bootstrap.1.html
index dfd44fa890..578fe57631 100644
--- a/distro/common/html/knife-bootstrap.1.html
+++ b/distro/common/html/knife-bootstrap.1.html
@@ -218,11 +218,11 @@ to other users via the process list using tools such as <span class="man-ref">ps
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#x6d;&#97;&#105;&#108;&#116;&#x6f;&#x3a;&#97;&#x64;&#97;&#109;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#100;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#97;&#100;&#x61;&#109;&#64;&#111;&#112;&#115;&#x63;&#111;&#100;&#101;&#46;&#x63;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a href="&#x6d;&#x61;&#x69;&#x6c;&#116;&#x6f;&#58;&#x61;&#100;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#101;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#97;&#x64;&#x61;&#109;&#64;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#x6c;&#116;&#111;&#58;&#x6a;&#x6f;&#115;&#104;&#x75;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#x6f;&#x64;&#x65;&#x2e;&#99;&#111;&#x6d;" data-bare-link="true">&#106;&#111;&#x73;&#104;&#117;&#97;&#64;&#x6f;&#x70;&#115;&#99;&#x6f;&#100;&#x65;&#46;&#x63;&#111;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#106;&#x6f;&#115;&#x68;&#x75;&#97;&#x40;&#x6f;&#112;&#115;&#99;&#111;&#100;&#x65;&#x2e;&#99;&#x6f;&#109;" data-bare-link="true">&#x6a;&#111;&#115;&#x68;&#x75;&#97;&#x40;&#111;&#112;&#115;&#x63;&#111;&#x64;&#x65;&#x2e;&#x63;&#111;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -231,7 +231,7 @@ to other users via the process list using tools such as <span class="man-ref">ps
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-bootstrap(1)</li>
</ol>
diff --git a/distro/common/html/knife-client.1.html b/distro/common/html/knife-client.1.html
index fdb72adf68..746646972b 100644
--- a/distro/common/html/knife-client.1.html
+++ b/distro/common/html/knife-client.1.html
@@ -196,20 +196,20 @@ setting up a host for management with Chef.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#x6d;&#97;&#105;&#108;&#116;&#x6f;&#x3a;&#97;&#x64;&#97;&#109;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#100;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#97;&#100;&#x61;&#109;&#64;&#111;&#112;&#115;&#x63;&#111;&#100;&#101;&#46;&#x63;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a data-bare-link="true" href="&#109;&#x61;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#115;&#x63;&#x6f;&#100;&#x65;&#46;&#x63;&#x6f;&#109;">&#97;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#x6c;&#116;&#111;&#58;&#x6a;&#x6f;&#115;&#104;&#x75;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#x6f;&#x64;&#x65;&#x2e;&#99;&#111;&#x6d;" data-bare-link="true">&#106;&#111;&#x73;&#104;&#117;&#97;&#64;&#x6f;&#x70;&#115;&#99;&#x6f;&#100;&#x65;&#46;&#x63;&#111;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a data-bare-link="true" href="&#x6d;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#x6a;&#x6f;&#x73;&#104;&#x75;&#x61;&#x40;&#x6f;&#x70;&#115;&#99;&#x6f;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;">&#x6a;&#x6f;&#x73;&#x68;&#117;&#97;&#64;&#x6f;&#112;&#x73;&#99;&#111;&#100;&#x65;&#46;&#x63;&#x6f;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
-<p> Knife is distributed with Chef. <a href="http://wiki.opscode.com/display/chef/Home" data-bare-link="true">http://wiki.opscode.com/display/chef/Home</a></p>
+<p> Knife is distributed with Chef. <a data-bare-link="true" href="http://wiki.opscode.com/display/chef/Home">http://wiki.opscode.com/display/chef/Home</a></p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-client(1)</li>
</ol>
diff --git a/distro/common/html/knife-configure.1.html b/distro/common/html/knife-configure.1.html
index 0174a9c524..6a6f58f816 100644
--- a/distro/common/html/knife-configure.1.html
+++ b/distro/common/html/knife-configure.1.html
@@ -147,11 +147,11 @@ may need to modify that setting after copying to a remote host.</p></li>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#x6d;&#97;&#105;&#108;&#116;&#x6f;&#x3a;&#97;&#x64;&#97;&#109;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#100;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#97;&#100;&#x61;&#109;&#64;&#111;&#112;&#115;&#x63;&#111;&#100;&#101;&#46;&#x63;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a href="&#109;&#x61;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#115;&#x63;&#x6f;&#100;&#x65;&#46;&#x63;&#x6f;&#109;" data-bare-link="true">&#97;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#x6c;&#116;&#111;&#58;&#x6a;&#x6f;&#115;&#104;&#x75;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#x6f;&#x64;&#x65;&#x2e;&#99;&#111;&#x6d;" data-bare-link="true">&#106;&#111;&#x73;&#104;&#117;&#97;&#64;&#x6f;&#x70;&#115;&#99;&#x6f;&#100;&#x65;&#46;&#x63;&#111;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a href="&#x6d;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#x6a;&#x6f;&#x73;&#104;&#x75;&#x61;&#x40;&#x6f;&#x70;&#115;&#99;&#x6f;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;" data-bare-link="true">&#x6a;&#x6f;&#x73;&#x68;&#117;&#97;&#64;&#x6f;&#112;&#x73;&#99;&#111;&#100;&#x65;&#46;&#x63;&#x6f;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -160,7 +160,7 @@ may need to modify that setting after copying to a remote host.</p></li>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-configure(1)</li>
</ol>
diff --git a/distro/common/html/knife-cookbook-site.1.html b/distro/common/html/knife-cookbook-site.1.html
index 65129b3eb9..b0e354687b 100644
--- a/distro/common/html/knife-cookbook-site.1.html
+++ b/distro/common/html/knife-cookbook-site.1.html
@@ -192,7 +192,7 @@ configuration file.</p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
-<p>The cookbook site, <a href="http://community.opscode.com/" data-bare-link="true">http://community.opscode.com/</a>, is a cookbook
+<p>The cookbook site, <a data-bare-link="true" href="http://community.opscode.com/">http://community.opscode.com/</a>, is a cookbook
distribution service operated by Opscode. This service provides users
with a central location to publish cookbooks for sharing with other
community members.</p>
@@ -214,24 +214,24 @@ configuration file.</p>
<h2 id="SEE-ALSO">SEE ALSO</h2>
<p> <strong><span class="man-ref">knife-cookbook<span class="s">(1)</span></span></strong>
- <a href="http://community.opscode.com/cookbooks" data-bare-link="true">http://community.opscode.com/cookbooks</a></p>
+ <a data-bare-link="true" href="http://community.opscode.com/cookbooks">http://community.opscode.com/cookbooks</a></p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x64;&#97;&#109;&#x40;&#111;&#x70;&#115;&#99;&#111;&#100;&#101;&#x2e;&#x63;&#111;&#x6d;" data-bare-link="true">&#x61;&#100;&#97;&#x6d;&#x40;&#111;&#x70;&#115;&#99;&#x6f;&#100;&#101;&#x2e;&#99;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a data-bare-link="true" href="&#109;&#x61;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#115;&#x63;&#x6f;&#100;&#x65;&#46;&#x63;&#x6f;&#109;">&#97;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#x6d;&#x61;&#105;&#x6c;&#116;&#111;&#x3a;&#106;&#111;&#x73;&#x68;&#x75;&#x61;&#x40;&#x6f;&#112;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x6a;&#111;&#x73;&#104;&#x75;&#x61;&#x40;&#x6f;&#112;&#115;&#x63;&#111;&#x64;&#x65;&#46;&#x63;&#111;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a data-bare-link="true" href="&#x6d;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#x6a;&#x6f;&#x73;&#104;&#x75;&#x61;&#x40;&#x6f;&#x70;&#115;&#99;&#x6f;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;">&#x6a;&#x6f;&#x73;&#x68;&#117;&#97;&#64;&#x6f;&#112;&#x73;&#99;&#111;&#100;&#x65;&#46;&#x63;&#x6f;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
-<p> Knife is distributed with Chef. <a href="http://wiki.opscode.com/display/chef/Home" data-bare-link="true">http://wiki.opscode.com/display/chef/Home</a></p>
+<p> Knife is distributed with Chef. <a data-bare-link="true" href="http://wiki.opscode.com/display/chef/Home">http://wiki.opscode.com/display/chef/Home</a></p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-cookbook-site(1)</li>
</ol>
diff --git a/distro/common/html/knife-cookbook.1.html b/distro/common/html/knife-cookbook.1.html
index 193754aa23..0557ccb638 100644
--- a/distro/common/html/knife-cookbook.1.html
+++ b/distro/common/html/knife-cookbook.1.html
@@ -361,11 +361,11 @@ cookbook.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x64;&#97;&#109;&#x40;&#111;&#x70;&#115;&#99;&#111;&#100;&#101;&#x2e;&#x63;&#111;&#x6d;" data-bare-link="true">&#x61;&#100;&#97;&#x6d;&#x40;&#111;&#x70;&#115;&#99;&#x6f;&#100;&#101;&#x2e;&#99;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a href="&#x6d;&#x61;&#x69;&#x6c;&#116;&#x6f;&#58;&#x61;&#100;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#101;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#97;&#x64;&#x61;&#109;&#64;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#x6d;&#x61;&#105;&#x6c;&#116;&#111;&#x3a;&#106;&#111;&#x73;&#x68;&#x75;&#x61;&#x40;&#x6f;&#112;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x6a;&#111;&#x73;&#104;&#x75;&#x61;&#x40;&#x6f;&#112;&#115;&#x63;&#111;&#x64;&#x65;&#46;&#x63;&#111;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#106;&#x6f;&#115;&#x68;&#x75;&#97;&#x40;&#x6f;&#112;&#115;&#99;&#111;&#100;&#x65;&#x2e;&#99;&#x6f;&#109;" data-bare-link="true">&#x6a;&#111;&#115;&#x68;&#x75;&#97;&#x40;&#111;&#112;&#115;&#x63;&#111;&#x64;&#x65;&#x2e;&#x63;&#111;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -374,7 +374,7 @@ cookbook.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-cookbook(1)</li>
</ol>
diff --git a/distro/common/html/knife-data-bag.1.html b/distro/common/html/knife-data-bag.1.html
index 0a4fff4621..23e05d795c 100644
--- a/distro/common/html/knife-data-bag.1.html
+++ b/distro/common/html/knife-data-bag.1.html
@@ -215,11 +215,11 @@ encryption keys.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x64;&#97;&#109;&#x40;&#111;&#x70;&#115;&#99;&#111;&#100;&#101;&#x2e;&#x63;&#111;&#x6d;" data-bare-link="true">&#x61;&#100;&#97;&#x6d;&#x40;&#111;&#x70;&#115;&#99;&#x6f;&#100;&#101;&#x2e;&#99;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a data-bare-link="true" href="&#109;&#x61;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#115;&#x63;&#x6f;&#100;&#x65;&#46;&#x63;&#x6f;&#109;">&#97;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#x6d;&#x61;&#105;&#x6c;&#116;&#111;&#x3a;&#106;&#111;&#x73;&#x68;&#x75;&#x61;&#x40;&#x6f;&#112;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x6a;&#111;&#x73;&#104;&#x75;&#x61;&#x40;&#x6f;&#112;&#115;&#x63;&#111;&#x64;&#x65;&#46;&#x63;&#111;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a data-bare-link="true" href="&#x6d;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#x6a;&#x6f;&#x73;&#104;&#x75;&#x61;&#x40;&#x6f;&#x70;&#115;&#99;&#x6f;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;">&#x6a;&#x6f;&#x73;&#x68;&#117;&#97;&#64;&#x6f;&#112;&#x73;&#99;&#111;&#100;&#x65;&#46;&#x63;&#x6f;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -228,7 +228,7 @@ encryption keys.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-data-bag(1)</li>
</ol>
diff --git a/distro/common/html/knife-environment.1.html b/distro/common/html/knife-environment.1.html
index 1e158de643..e1951f5c6d 100644
--- a/distro/common/html/knife-environment.1.html
+++ b/distro/common/html/knife-environment.1.html
@@ -239,25 +239,25 @@ override_attributes "aws_s3_bucket" =&gt; "production"
<h2 id="SEE-ALSO">SEE ALSO</h2>
<p> <strong><span class="man-ref">knife-node<span class="s">(1)</span></span></strong> <strong><span class="man-ref">knife-cookbook<span class="s">(1)</span></span></strong> <strong><span class="man-ref">knife-role<span class="s">(1)</span></span></strong>
- <a href="http://wiki.opscode.com/display/chef/Environments" data-bare-link="true">http://wiki.opscode.com/display/chef/Environments</a>
- <a href="http://wiki.opscode.com/display/chef/Version+Constraints" data-bare-link="true">http://wiki.opscode.com/display/chef/Version+Constraints</a></p>
+ <a data-bare-link="true" href="http://wiki.opscode.com/display/chef/Environments">http://wiki.opscode.com/display/chef/Environments</a>
+ <a data-bare-link="true" href="http://wiki.opscode.com/display/chef/Version+Constraints">http://wiki.opscode.com/display/chef/Version+Constraints</a></p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x64;&#97;&#109;&#x40;&#111;&#x70;&#115;&#99;&#111;&#100;&#101;&#x2e;&#x63;&#111;&#x6d;" data-bare-link="true">&#x61;&#100;&#97;&#x6d;&#x40;&#111;&#x70;&#115;&#99;&#x6f;&#100;&#101;&#x2e;&#99;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a data-bare-link="true" href="&#109;&#97;&#x69;&#108;&#116;&#x6f;&#58;&#97;&#x64;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;">&#x61;&#100;&#x61;&#109;&#x40;&#111;&#112;&#115;&#x63;&#111;&#100;&#x65;&#46;&#x63;&#111;&#109;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Daniel DeLeo <a href="&#x6d;&#x61;&#105;&#x6c;&#116;&#111;&#x3a;&#100;&#97;&#x6e;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#x64;&#x61;&#110;&#x40;&#111;&#x70;&#115;&#x63;&#x6f;&#x64;&#x65;&#46;&#99;&#x6f;&#109;</a>.
+<p> This manual page was written by Daniel DeLeo <a data-bare-link="true" href="&#109;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#100;&#x61;&#x6e;&#64;&#111;&#112;&#x73;&#x63;&#111;&#x64;&#101;&#46;&#x63;&#111;&#109;">&#x64;&#x61;&#x6e;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#x64;&#x65;&#x2e;&#x63;&#111;&#109;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
-<p> Knife is distributed with Chef. <a href="http://wiki.opscode.com/display/chef/Home" data-bare-link="true">http://wiki.opscode.com/display/chef/Home</a></p>
+<p> Knife is distributed with Chef. <a data-bare-link="true" href="http://wiki.opscode.com/display/chef/Home">http://wiki.opscode.com/display/chef/Home</a></p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-environment(1)</li>
</ol>
diff --git a/distro/common/html/knife-exec.1.html b/distro/common/html/knife-exec.1.html
index affde6c700..b0308c3c55 100644
--- a/distro/common/html/knife-exec.1.html
+++ b/distro/common/html/knife-exec.1.html
@@ -111,11 +111,11 @@ description of the commands available.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#x69;&#x6c;&#116;&#x6f;&#x3a;&#97;&#100;&#97;&#109;&#64;&#x6f;&#x70;&#x73;&#99;&#111;&#100;&#x65;&#46;&#99;&#x6f;&#109;" data-bare-link="true">&#x61;&#100;&#97;&#x6d;&#64;&#x6f;&#x70;&#115;&#99;&#111;&#x64;&#x65;&#46;&#99;&#111;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#x69;&#108;&#116;&#x6f;&#58;&#97;&#x64;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x61;&#100;&#x61;&#109;&#x40;&#111;&#112;&#115;&#x63;&#111;&#100;&#x65;&#46;&#x63;&#111;&#109;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#108;&#116;&#111;&#58;&#x6a;&#111;&#115;&#104;&#117;&#97;&#x40;&#x6f;&#112;&#x73;&#x63;&#x6f;&#x64;&#101;&#46;&#x63;&#111;&#109;" data-bare-link="true">&#106;&#111;&#115;&#x68;&#117;&#x61;&#x40;&#x6f;&#112;&#115;&#99;&#111;&#100;&#x65;&#46;&#99;&#x6f;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a href="&#109;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#106;&#x6f;&#x73;&#104;&#117;&#97;&#x40;&#x6f;&#112;&#x73;&#99;&#111;&#x64;&#101;&#46;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#x6a;&#x6f;&#x73;&#x68;&#x75;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#x2e;&#99;&#x6f;&#109;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -124,7 +124,7 @@ description of the commands available.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-exec(1)</li>
</ol>
diff --git a/distro/common/html/knife-index.1.html b/distro/common/html/knife-index.1.html
index 633098cbb1..e85c25d0db 100644
--- a/distro/common/html/knife-index.1.html
+++ b/distro/common/html/knife-index.1.html
@@ -102,20 +102,20 @@ time for all objects to be indexed and available for search.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#x69;&#x6c;&#116;&#x6f;&#x3a;&#97;&#100;&#97;&#109;&#64;&#x6f;&#x70;&#x73;&#99;&#111;&#100;&#x65;&#46;&#99;&#x6f;&#109;" data-bare-link="true">&#x61;&#100;&#97;&#x6d;&#64;&#x6f;&#x70;&#115;&#99;&#111;&#x64;&#x65;&#46;&#99;&#111;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a data-bare-link="true" href="&#109;&#97;&#x69;&#108;&#116;&#x6f;&#58;&#97;&#x64;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;">&#x61;&#100;&#x61;&#109;&#x40;&#111;&#112;&#115;&#x63;&#111;&#100;&#x65;&#46;&#x63;&#111;&#109;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#108;&#116;&#111;&#58;&#x6a;&#111;&#115;&#104;&#117;&#97;&#x40;&#x6f;&#112;&#x73;&#x63;&#x6f;&#x64;&#101;&#46;&#x63;&#111;&#109;" data-bare-link="true">&#106;&#111;&#115;&#x68;&#117;&#x61;&#x40;&#x6f;&#112;&#115;&#99;&#111;&#100;&#x65;&#46;&#99;&#x6f;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a data-bare-link="true" href="&#109;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#106;&#x6f;&#x73;&#104;&#117;&#97;&#x40;&#x6f;&#112;&#x73;&#99;&#111;&#x64;&#101;&#46;&#x63;&#x6f;&#x6d;">&#x6a;&#x6f;&#x73;&#x68;&#x75;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#x2e;&#99;&#x6f;&#109;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
-<p> Knife is distributed with Chef. <a href="http://wiki.opscode.com/display/chef/Home" data-bare-link="true">http://wiki.opscode.com/display/chef/Home</a></p>
+<p> Knife is distributed with Chef. <a data-bare-link="true" href="http://wiki.opscode.com/display/chef/Home">http://wiki.opscode.com/display/chef/Home</a></p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-index(1)</li>
</ol>
diff --git a/distro/common/html/knife-node.1.html b/distro/common/html/knife-node.1.html
index ba60474098..29c30c177e 100644
--- a/distro/common/html/knife-node.1.html
+++ b/distro/common/html/knife-node.1.html
@@ -227,11 +227,11 @@ run list, the correct syntax is "role[ROLE_NAME]"</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#x69;&#x6c;&#116;&#x6f;&#x3a;&#97;&#100;&#97;&#109;&#64;&#x6f;&#x70;&#x73;&#99;&#111;&#100;&#x65;&#46;&#99;&#x6f;&#109;" data-bare-link="true">&#x61;&#100;&#97;&#x6d;&#64;&#x6f;&#x70;&#115;&#99;&#111;&#x64;&#x65;&#46;&#99;&#111;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a href="&#x6d;&#x61;&#105;&#x6c;&#x74;&#x6f;&#x3a;&#x61;&#x64;&#97;&#x6d;&#64;&#111;&#x70;&#x73;&#99;&#111;&#100;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x61;&#x64;&#x61;&#x6d;&#x40;&#111;&#112;&#115;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#99;&#111;&#109;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#108;&#116;&#111;&#58;&#x6a;&#111;&#115;&#104;&#117;&#97;&#x40;&#x6f;&#112;&#x73;&#x63;&#x6f;&#x64;&#101;&#46;&#x63;&#111;&#109;" data-bare-link="true">&#106;&#111;&#115;&#x68;&#117;&#x61;&#x40;&#x6f;&#112;&#115;&#99;&#111;&#100;&#x65;&#46;&#99;&#x6f;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a href="&#x6d;&#97;&#x69;&#x6c;&#116;&#111;&#58;&#106;&#111;&#115;&#104;&#117;&#x61;&#x40;&#111;&#112;&#115;&#x63;&#x6f;&#x64;&#x65;&#46;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#106;&#111;&#115;&#104;&#117;&#x61;&#x40;&#x6f;&#112;&#115;&#x63;&#x6f;&#x64;&#101;&#x2e;&#x63;&#111;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -240,7 +240,7 @@ run list, the correct syntax is "role[ROLE_NAME]"</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-node(1)</li>
</ol>
diff --git a/distro/common/html/knife-role.1.html b/distro/common/html/knife-role.1.html
index 0c61868c70..d3a01b760c 100644
--- a/distro/common/html/knife-role.1.html
+++ b/distro/common/html/knife-role.1.html
@@ -177,11 +177,11 @@ run_list.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#105;&#108;&#116;&#x6f;&#x3a;&#x61;&#x64;&#97;&#x6d;&#64;&#111;&#x70;&#115;&#x63;&#x6f;&#100;&#101;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#97;&#100;&#97;&#x6d;&#x40;&#111;&#112;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#x69;&#108;&#116;&#x6f;&#58;&#97;&#x64;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x61;&#100;&#x61;&#109;&#x40;&#111;&#112;&#115;&#x63;&#111;&#100;&#x65;&#46;&#x63;&#111;&#109;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#108;&#x74;&#x6f;&#58;&#106;&#111;&#x73;&#104;&#117;&#97;&#x40;&#111;&#112;&#115;&#99;&#111;&#x64;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#106;&#x6f;&#115;&#x68;&#117;&#x61;&#x40;&#x6f;&#112;&#x73;&#99;&#x6f;&#x64;&#101;&#46;&#99;&#x6f;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a href="&#109;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#106;&#x6f;&#x73;&#104;&#117;&#97;&#x40;&#x6f;&#112;&#x73;&#99;&#111;&#x64;&#101;&#46;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#x6a;&#x6f;&#x73;&#x68;&#x75;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#x2e;&#99;&#x6f;&#109;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -190,7 +190,7 @@ run_list.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-role(1)</li>
</ol>
diff --git a/distro/common/html/knife-search.1.html b/distro/common/html/knife-search.1.html
index 08f0cc2695..a60d441b88 100644
--- a/distro/common/html/knife-search.1.html
+++ b/distro/common/html/knife-search.1.html
@@ -265,11 +265,11 @@ www.example.com:</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#105;&#108;&#116;&#x6f;&#x3a;&#x61;&#x64;&#97;&#x6d;&#64;&#111;&#x70;&#115;&#x63;&#x6f;&#100;&#101;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#97;&#100;&#97;&#x6d;&#x40;&#111;&#112;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a href="&#x6d;&#x61;&#x69;&#x6c;&#116;&#x6f;&#58;&#x61;&#100;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#101;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#97;&#x64;&#x61;&#109;&#64;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#108;&#x74;&#x6f;&#58;&#106;&#111;&#x73;&#104;&#117;&#97;&#x40;&#111;&#112;&#115;&#99;&#111;&#x64;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#106;&#x6f;&#115;&#x68;&#117;&#x61;&#x40;&#x6f;&#112;&#x73;&#99;&#x6f;&#x64;&#101;&#46;&#99;&#x6f;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#106;&#x6f;&#115;&#x68;&#x75;&#97;&#x40;&#x6f;&#112;&#115;&#99;&#111;&#100;&#x65;&#x2e;&#99;&#x6f;&#109;" data-bare-link="true">&#x6a;&#111;&#115;&#x68;&#x75;&#97;&#x40;&#111;&#112;&#115;&#x63;&#111;&#x64;&#x65;&#x2e;&#x63;&#111;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -278,7 +278,7 @@ www.example.com:</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-search(1)</li>
</ol>
diff --git a/distro/common/html/knife-ssh.1.html b/distro/common/html/knife-ssh.1.html
index 72d80369b7..f6a5f6d154 100644
--- a/distro/common/html/knife-ssh.1.html
+++ b/distro/common/html/knife-ssh.1.html
@@ -133,20 +133,20 @@ option.</dd>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#105;&#108;&#116;&#x6f;&#x3a;&#x61;&#x64;&#97;&#x6d;&#64;&#111;&#x70;&#115;&#x63;&#x6f;&#100;&#101;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#97;&#100;&#97;&#x6d;&#x40;&#111;&#112;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a data-bare-link="true" href="&#x6d;&#x61;&#x69;&#x6c;&#116;&#x6f;&#58;&#x61;&#100;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#101;&#46;&#99;&#111;&#x6d;">&#97;&#x64;&#x61;&#109;&#64;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#108;&#x74;&#x6f;&#58;&#106;&#111;&#x73;&#104;&#117;&#97;&#x40;&#111;&#112;&#115;&#99;&#111;&#x64;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#106;&#x6f;&#115;&#x68;&#117;&#x61;&#x40;&#x6f;&#112;&#x73;&#99;&#x6f;&#x64;&#101;&#46;&#99;&#x6f;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a data-bare-link="true" href="&#109;&#x61;&#105;&#x6c;&#x74;&#111;&#x3a;&#106;&#x6f;&#115;&#x68;&#x75;&#97;&#x40;&#x6f;&#112;&#115;&#99;&#111;&#100;&#x65;&#x2e;&#99;&#x6f;&#109;">&#x6a;&#111;&#115;&#x68;&#x75;&#97;&#x40;&#111;&#112;&#115;&#x63;&#111;&#x64;&#x65;&#x2e;&#x63;&#111;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
-<p> Knife is distributed with Chef. <a href="http://wiki.opscode.com/display/chef/Home" data-bare-link="true">http://wiki.opscode.com/display/chef/Home</a></p>
+<p> Knife is distributed with Chef. <a data-bare-link="true" href="http://wiki.opscode.com/display/chef/Home">http://wiki.opscode.com/display/chef/Home</a></p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-ssh(1)</li>
</ol>
diff --git a/distro/common/html/knife-status.1.html b/distro/common/html/knife-status.1.html
index 332dc8fd18..201c2a1bea 100644
--- a/distro/common/html/knife-status.1.html
+++ b/distro/common/html/knife-status.1.html
@@ -105,11 +105,11 @@ may not be publicly reachable.</p>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#105;&#108;&#116;&#x6f;&#x3a;&#x61;&#x64;&#97;&#x6d;&#64;&#111;&#x70;&#115;&#x63;&#x6f;&#100;&#101;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#97;&#100;&#97;&#x6d;&#x40;&#111;&#112;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a href="&#109;&#97;&#x69;&#108;&#116;&#x6f;&#58;&#97;&#x64;&#97;&#x6d;&#x40;&#111;&#x70;&#x73;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x61;&#100;&#x61;&#109;&#x40;&#111;&#112;&#115;&#x63;&#111;&#100;&#x65;&#46;&#x63;&#111;&#109;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#109;&#x61;&#x69;&#108;&#x74;&#x6f;&#58;&#106;&#111;&#x73;&#104;&#117;&#97;&#x40;&#111;&#112;&#115;&#99;&#111;&#x64;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#106;&#x6f;&#115;&#x68;&#117;&#x61;&#x40;&#x6f;&#112;&#x73;&#99;&#x6f;&#x64;&#101;&#46;&#99;&#x6f;&#109;</a>.
+<p> This manual page was written by Joshua Timberman <a href="&#109;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#106;&#x6f;&#x73;&#104;&#117;&#97;&#x40;&#x6f;&#112;&#x73;&#99;&#111;&#x64;&#101;&#46;&#x63;&#x6f;&#x6d;" data-bare-link="true">&#x6a;&#x6f;&#x73;&#x68;&#x75;&#97;&#x40;&#x6f;&#x70;&#x73;&#99;&#111;&#x64;&#x65;&#x2e;&#99;&#x6f;&#109;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -118,7 +118,7 @@ may not be publicly reachable.</p>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-status(1)</li>
</ol>
diff --git a/distro/common/html/knife-tag.1.html b/distro/common/html/knife-tag.1.html
index 47c91b7d4e..98fd8734bb 100644
--- a/distro/common/html/knife-tag.1.html
+++ b/distro/common/html/knife-tag.1.html
@@ -114,11 +114,11 @@
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#x6f;&#58;&#x61;&#100;&#97;&#109;&#64;&#x6f;&#112;&#x73;&#99;&#x6f;&#x64;&#101;&#x2e;&#99;&#x6f;&#109;" data-bare-link="true">&#97;&#100;&#x61;&#x6d;&#x40;&#x6f;&#x70;&#x73;&#x63;&#x6f;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a> with many contributions from the community.</p>
+<p> Chef was written by Adam Jacob <a href="&#x6d;&#x61;&#105;&#x6c;&#x74;&#x6f;&#x3a;&#x61;&#x64;&#97;&#x6d;&#64;&#111;&#x70;&#x73;&#99;&#111;&#100;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x61;&#x64;&#x61;&#x6d;&#x40;&#111;&#112;&#115;&#x63;&#x6f;&#x64;&#x65;&#x2e;&#99;&#111;&#109;</a> with many contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Daniel DeLeo <a href="&#x6d;&#97;&#x69;&#x6c;&#x74;&#x6f;&#58;&#100;&#x61;&#x6e;&#64;&#111;&#112;&#x73;&#99;&#111;&#x64;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#100;&#97;&#x6e;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#100;&#x65;&#46;&#x63;&#111;&#x6d;</a>.
+<p> This manual page was written by Daniel DeLeo <a href="&#x6d;&#97;&#x69;&#x6c;&#116;&#111;&#58;&#100;&#97;&#110;&#64;&#111;&#x70;&#x73;&#99;&#111;&#100;&#x65;&#x2e;&#x63;&#x6f;&#109;" data-bare-link="true">&#x64;&#x61;&#x6e;&#64;&#111;&#112;&#115;&#99;&#x6f;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a>.
Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p>
<h2 id="CHEF">CHEF</h2>
@@ -127,7 +127,7 @@
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife-tag(1)</li>
</ol>
diff --git a/distro/common/html/knife.1.html b/distro/common/html/knife.1.html
index 8b5343bd79..6d0b3076b0 100644
--- a/distro/common/html/knife.1.html
+++ b/distro/common/html/knife.1.html
@@ -286,12 +286,12 @@ data editing entirely.</dd>
<h2 id="AUTHOR">AUTHOR</h2>
-<p> Chef was written by Adam Jacob <a href="&#109;&#x61;&#105;&#x6c;&#x74;&#x6f;&#58;&#x61;&#100;&#97;&#109;&#64;&#x6f;&#112;&#x73;&#99;&#x6f;&#x64;&#101;&#x2e;&#99;&#x6f;&#109;" data-bare-link="true">&#97;&#100;&#x61;&#x6d;&#x40;&#x6f;&#x70;&#x73;&#x63;&#x6f;&#x64;&#x65;&#46;&#99;&#x6f;&#x6d;</a> of Opscode
+<p> Chef was written by Adam Jacob <a href="&#109;&#x61;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#115;&#x63;&#x6f;&#100;&#x65;&#46;&#x63;&#x6f;&#109;" data-bare-link="true">&#97;&#x64;&#x61;&#109;&#x40;&#x6f;&#x70;&#x73;&#x63;&#111;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;</a> of Opscode
(<a href="http://www.opscode.com" data-bare-link="true">http://www.opscode.com</a>), with contributions from the community.</p>
<h2 id="DOCUMENTATION">DOCUMENTATION</h2>
-<p> This manual page was written by Joshua Timberman <a href="&#x6d;&#97;&#x69;&#x6c;&#x74;&#x6f;&#58;&#106;&#x6f;&#x73;&#104;&#117;&#97;&#x40;&#111;&#112;&#x73;&#x63;&#x6f;&#x64;&#x65;&#46;&#99;&#111;&#x6d;" data-bare-link="true">&#x6a;&#x6f;&#x73;&#x68;&#x75;&#97;&#64;&#x6f;&#112;&#x73;&#99;&#x6f;&#100;&#101;&#46;&#x63;&#111;&#x6d;</a>.</p>
+<p> This manual page was written by Joshua Timberman <a href="&#x6d;&#97;&#x69;&#108;&#x74;&#111;&#x3a;&#x6a;&#x6f;&#x73;&#104;&#x75;&#x61;&#x40;&#x6f;&#x70;&#115;&#99;&#x6f;&#x64;&#101;&#46;&#99;&#x6f;&#x6d;" data-bare-link="true">&#x6a;&#x6f;&#x73;&#x68;&#117;&#97;&#64;&#x6f;&#112;&#x73;&#99;&#111;&#100;&#x65;&#46;&#x63;&#x6f;&#x6d;</a>.</p>
<h2 id="LICENSE">LICENSE</h2>
@@ -305,7 +305,7 @@ data editing entirely.</dd>
<ol class='man-decor man-foot man foot'>
- <li class='tl'>Chef 11.0.0</li>
+ <li class='tl'>Chef 11.2.0</li>
<li class='tc'>February 2013</li>
<li class='tr'>knife(1)</li>
</ol>
diff --git a/distro/common/man/man1/chef-shell.1 b/distro/common/man/man1/chef-shell.1
index 35caa9ec51..adaa3aac0d 100644
--- a/distro/common/man/man1/chef-shell.1
+++ b/distro/common/man/man1/chef-shell.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "CHEF\-SHELL" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "CHEF\-SHELL" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBchef\-shell\fR \- Interactive Chef Console
diff --git a/distro/common/man/man1/knife-bootstrap.1 b/distro/common/man/man1/knife-bootstrap.1
index dce7c86746..56eee90d4a 100644
--- a/distro/common/man/man1/knife-bootstrap.1
+++ b/distro/common/man/man1/knife-bootstrap.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-BOOTSTRAP" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-BOOTSTRAP" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-bootstrap\fR \- Install Chef Client on a remote host
diff --git a/distro/common/man/man1/knife-client.1 b/distro/common/man/man1/knife-client.1
index 98a34cc006..a0c36be126 100644
--- a/distro/common/man/man1/knife-client.1
+++ b/distro/common/man/man1/knife-client.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-CLIENT" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-CLIENT" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-client\fR \- Manage Chef API Clients
diff --git a/distro/common/man/man1/knife-configure.1 b/distro/common/man/man1/knife-configure.1
index 72246f786d..81828674ee 100644
--- a/distro/common/man/man1/knife-configure.1
+++ b/distro/common/man/man1/knife-configure.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-CONFIGURE" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-CONFIGURE" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-configure\fR \- Generate configuration files for knife or Chef Client
diff --git a/distro/common/man/man1/knife-cookbook-site.1 b/distro/common/man/man1/knife-cookbook-site.1
index 21ee1810dd..feca0c4314 100644
--- a/distro/common/man/man1/knife-cookbook-site.1
+++ b/distro/common/man/man1/knife-cookbook-site.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-COOKBOOK\-SITE" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-COOKBOOK\-SITE" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-cookbook\-site\fR \- Install and update open source cookbooks
diff --git a/distro/common/man/man1/knife-cookbook.1 b/distro/common/man/man1/knife-cookbook.1
index a16ff5e94f..a308025ef4 100644
--- a/distro/common/man/man1/knife-cookbook.1
+++ b/distro/common/man/man1/knife-cookbook.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-COOKBOOK" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-COOKBOOK" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-cookbook\fR \- upload and manage chef cookbooks
diff --git a/distro/common/man/man1/knife-data-bag.1 b/distro/common/man/man1/knife-data-bag.1
index d07ca2e208..9322bb4f2b 100644
--- a/distro/common/man/man1/knife-data-bag.1
+++ b/distro/common/man/man1/knife-data-bag.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-DATA\-BAG" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-DATA\-BAG" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-data\-bag\fR \- Store arbitrary data on a Chef Server
diff --git a/distro/common/man/man1/knife-environment.1 b/distro/common/man/man1/knife-environment.1
index 6285cfff8c..c0fb06c2c5 100644
--- a/distro/common/man/man1/knife-environment.1
+++ b/distro/common/man/man1/knife-environment.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-ENVIRONMENT" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-ENVIRONMENT" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-environment\fR \- Define cookbook policies for the environments in your infrastructure
diff --git a/distro/common/man/man1/knife-exec.1 b/distro/common/man/man1/knife-exec.1
index 7225c6f8e3..a2e64332d0 100644
--- a/distro/common/man/man1/knife-exec.1
+++ b/distro/common/man/man1/knife-exec.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-EXEC" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-EXEC" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-exec\fR \- Run user scripts using the Chef API DSL
diff --git a/distro/common/man/man1/knife-index.1 b/distro/common/man/man1/knife-index.1
index dee8933ac6..283d66ca4d 100644
--- a/distro/common/man/man1/knife-index.1
+++ b/distro/common/man/man1/knife-index.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-INDEX" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-INDEX" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-index\fR \- Rebuild the search index on a Chef Server
diff --git a/distro/common/man/man1/knife-node.1 b/distro/common/man/man1/knife-node.1
index f1e77da10d..b6c0e0bc1c 100644
--- a/distro/common/man/man1/knife-node.1
+++ b/distro/common/man/man1/knife-node.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-NODE" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-NODE" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-node\fR \- Manage the hosts in your infrastructure
diff --git a/distro/common/man/man1/knife-role.1 b/distro/common/man/man1/knife-role.1
index f42b223a94..babfcf14a8 100644
--- a/distro/common/man/man1/knife-role.1
+++ b/distro/common/man/man1/knife-role.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-ROLE" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-ROLE" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-role\fR \- Group common configuration settings
diff --git a/distro/common/man/man1/knife-search.1 b/distro/common/man/man1/knife-search.1
index 886862ef6b..d85499d6a3 100644
--- a/distro/common/man/man1/knife-search.1
+++ b/distro/common/man/man1/knife-search.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-SEARCH" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-SEARCH" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-search\fR \- Find objects on a Chef Server by query
diff --git a/distro/common/man/man1/knife-ssh.1 b/distro/common/man/man1/knife-ssh.1
index 0af22b8279..1b2e867378 100644
--- a/distro/common/man/man1/knife-ssh.1
+++ b/distro/common/man/man1/knife-ssh.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-SSH" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-SSH" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-ssh\fR \- Run a command or interactive session on multiple remote hosts
diff --git a/distro/common/man/man1/knife-status.1 b/distro/common/man/man1/knife-status.1
index ad0aaf361b..ddf882c9f8 100644
--- a/distro/common/man/man1/knife-status.1
+++ b/distro/common/man/man1/knife-status.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-STATUS" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-STATUS" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-status\fR \- Display status information for the nodes in your infrastructure
diff --git a/distro/common/man/man1/knife-tag.1 b/distro/common/man/man1/knife-tag.1
index b7332969b5..6226417d9e 100644
--- a/distro/common/man/man1/knife-tag.1
+++ b/distro/common/man/man1/knife-tag.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE\-TAG" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE\-TAG" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\-tag\fR \- Apply tags to nodes on a Chef Server
diff --git a/distro/common/man/man1/knife.1 b/distro/common/man/man1/knife.1
index b5f208df9a..1d2dbb6e3f 100644
--- a/distro/common/man/man1/knife.1
+++ b/distro/common/man/man1/knife.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "KNIFE" "1" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "KNIFE" "1" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBknife\fR \- Chef Server API client utility
diff --git a/distro/common/man/man8/chef-client.8 b/distro/common/man/man8/chef-client.8
index 3b20fc5a85..cba180a246 100644
--- a/distro/common/man/man8/chef-client.8
+++ b/distro/common/man/man8/chef-client.8
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "CHEF\-CLIENT" "8" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "CHEF\-CLIENT" "8" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBchef\-client\fR \- Runs a client node connecting to a chef\-server\.
diff --git a/distro/common/man/man8/chef-expander.8 b/distro/common/man/man8/chef-expander.8
index 0f0c0fe9ef..f4d5e2f7ce 100644
--- a/distro/common/man/man8/chef-expander.8
+++ b/distro/common/man/man8/chef-expander.8
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "CHEF\-EXPANDER" "8" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "CHEF\-EXPANDER" "8" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBchef\-expander\fR \- fetches messages from RabbitMQ, processes, and loads into chef\-solr
diff --git a/distro/common/man/man8/chef-expanderctl.8 b/distro/common/man/man8/chef-expanderctl.8
index 6c8d3ebdc5..5556ccc00e 100644
--- a/distro/common/man/man8/chef-expanderctl.8
+++ b/distro/common/man/man8/chef-expanderctl.8
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "CHEF\-EXPANDERCTL" "8" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "CHEF\-EXPANDERCTL" "8" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBchef\-expanderctl\fR \- management program for chef\-expander
diff --git a/distro/common/man/man8/chef-server-webui.8 b/distro/common/man/man8/chef-server-webui.8
index ad5df7a543..0ddc871bf5 100644
--- a/distro/common/man/man8/chef-server-webui.8
+++ b/distro/common/man/man8/chef-server-webui.8
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "CHEF\-SERVER\-WEBUI" "8" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "CHEF\-SERVER\-WEBUI" "8" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBchef\-server\-webui\fR \- Start the Chef Server merb application slice providing Web User Interface (Management Console)\.
diff --git a/distro/common/man/man8/chef-server.8 b/distro/common/man/man8/chef-server.8
index f2896cb766..e1e846dbb4 100644
--- a/distro/common/man/man8/chef-server.8
+++ b/distro/common/man/man8/chef-server.8
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "CHEF\-SERVER" "8" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "CHEF\-SERVER" "8" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBchef\-server\fR \- Start the Chef Server merb application slice\.
diff --git a/distro/common/man/man8/chef-solo.8 b/distro/common/man/man8/chef-solo.8
index 39f6444892..05c121e3c0 100644
--- a/distro/common/man/man8/chef-solo.8
+++ b/distro/common/man/man8/chef-solo.8
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "CHEF\-SOLO" "8" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "CHEF\-SOLO" "8" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBchef\-solo\fR \- Runs chef in solo mode against a specified cookbook location\.
diff --git a/distro/common/man/man8/chef-solr.8 b/distro/common/man/man8/chef-solr.8
index d8c49590fe..d7e42d8be2 100644
--- a/distro/common/man/man8/chef-solr.8
+++ b/distro/common/man/man8/chef-solr.8
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "CHEF\-SOLR" "8" "February 2013" "Chef 11.0.0" "Chef Manual"
+.TH "CHEF\-SOLR" "8" "February 2013" "Chef 11.2.0" "Chef Manual"
.
.SH "NAME"
\fBchef\-solr\fR \- Runs as Chef\'s search server
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index 6e65e48384..0ed8d3dd9f 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -29,9 +29,6 @@ require 'rbconfig'
class Chef::Application
include Mixlib::CLI
- class Wakeup < Exception
- end
-
def initialize
super
@@ -125,7 +122,7 @@ class Chef::Application
# that a user has configured a log_location in client.rb, but is running
# chef-client by hand to troubleshoot a problem.
def configure_logging
- Chef::Log.init(Chef::Config[:log_location])
+ Chef::Log.init(MonoLogger.new(Chef::Config[:log_location]))
if want_additional_logger?
configure_stdout_logger
end
@@ -133,7 +130,7 @@ class Chef::Application
end
def configure_stdout_logger
- stdout_logger = Logger.new(STDOUT)
+ stdout_logger = MonoLogger.new(STDOUT)
STDOUT.sync = true
stdout_logger.formatter = Chef::Log.logger.formatter
Chef::Log.loggers << stdout_logger
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index c72f82d7bd..fca2e9a92d 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -306,9 +306,6 @@ class Chef::Application::Client < Chef::Application
else
Chef::Application.exit! "Exiting", 0
end
- rescue Chef::Application::Wakeup => e
- Chef::Log.debug("Received Wakeup signal. Starting run.")
- next
rescue SystemExit => e
raise
rescue Exception => e
diff --git a/lib/chef/application/windows_service.rb b/lib/chef/application/windows_service.rb
index 0d4a022fdf..5b77a44392 100644
--- a/lib/chef/application/windows_service.rb
+++ b/lib/chef/application/windows_service.rb
@@ -17,6 +17,7 @@
#
require 'chef'
+require 'chef/monologger'
require 'chef/application'
require 'chef/client'
require 'chef/config'
@@ -56,58 +57,54 @@ class Chef
:description => "Set the number of seconds to wait between chef-client runs",
:proc => lambda { |s| s.to_i }
- option :override_runlist,
- :short => "-o RunlistItem,RunlistItem...",
- :long => "--override-runlist RunlistItem,RunlistItem...",
- :description => "Replace current run list with specified items",
- :proc => lambda{|items|
- items = items.split(',')
- items.compact.map{|item|
- Chef::RunList::RunListItem.new(item)
- }
- }
-
def service_init
+ @service_action_mutex = Mutex.new
+ @service_signal = ConditionVariable.new
+
reconfigure
Chef::Log.info("Chef Client Service initialized")
end
def service_main(*startup_parameters)
+ # Chef::Config is initialized during service_init
+ # Set the initial timeout to splay sleep time
+ timeout = rand Chef::Config[:splay]
- while running?
- if state == RUNNING
+ while running? do
+ # Grab the service_action_mutex to make a chef-client run
+ @service_action_mutex.synchronize do
begin
+ Chef::Log.info("Next chef-client run will happen in #{timeout} seconds")
+ @service_signal.wait(@service_action_mutex, timeout)
+
+ # Continue only if service is RUNNING
+ next if state != RUNNING
+
# Reconfigure each time through to pick up any changes in the client file
Chef::Log.info("Reconfiguring with startup parameters")
reconfigure(startup_parameters)
+ timeout = Chef::Config[:interval]
- splay = rand Chef::Config[:splay]
- Chef::Log.debug("Splay sleep #{splay} seconds")
- sleep splay
+ # Honor splay sleep config
+ timeout += rand Chef::Config[:splay]
- # If we've stopped, then bail out now, instead of going on to run Chef
+ # run chef-client only if service is in RUNNING state
next if state != RUNNING
+ Chef::Log.info("Chef-Client service is starting a chef-client run...")
run_chef_client
-
- Chef::Log.debug("Sleeping for #{Chef::Config[:interval]} seconds")
- client_sleep Chef::Config[:interval]
- rescue Chef::Application::Wakeup => e
- Chef::Log.debug("Received Wakeup signal. Starting run.")
- next
rescue SystemExit => e
- raise
+ # Do not raise any of the errors here in order to
+ # prevent service crash
+ Chef::Log.error("#{e.class}: #{e}")
rescue Exception => e
Chef::Log.error("#{e.class}: #{e}")
Chef::Application.debug_stacktrace(e)
- Chef::Log.error("Sleeping for #{Chef::Config[:interval]} seconds before trying again")
- client_sleep Chef::Config[:interval]
- retry
end
- else # PAUSED or IDLE
- sleep 5
end
end
+
+ Chef::Log.debug("Exiting service...")
end
################################################################################
@@ -115,19 +112,45 @@ class Chef
################################################################################
def service_stop
- Chef::Log.info("SERVICE_CONTROL_STOP received, stopping")
+ Chef::Log.info("STOP request from operating system.")
+ if @service_action_mutex.try_lock
+ @service_signal.signal
+ @service_action_mutex.unlock
+ Chef::Log.info("Service is stopping....")
+ else
+ Chef::Log.info("Currently a chef-client run is happening.")
+ Chef::Log.info("Service will stop once it's completed.")
+ end
end
def service_pause
- Chef::Log.info("SERVICE_CONTROL_PAUSE received, pausing")
+ Chef::Log.info("PAUSE request from operating system.")
+
+ # We don't need to wake up the service_main if it's waiting
+ # since this is a PAUSE signal.
+
+ if @service_action_mutex.locked?
+ Chef::Log.info("Currently a chef-client run is happening.")
+ Chef::Log.info("Service will pause once it's completed.")
+ else
+ Chef::Log.info("Service is pausing....")
+ end
end
def service_resume
- Chef::Log.info("SERVICE_CONTROL_CONTINUE received, resuming")
+ # We don't need to wake up the service_main if it's waiting
+ # since this is a RESUME signal.
+
+ Chef::Log.info("RESUME signal received from the OS.")
+ Chef::Log.info("Service is resuming....")
end
def service_shutdown
- Chef::Log.info("SERVICE_CONTROL_SHUTDOWN received, shutting down")
+ Chef::Log.info("SHUTDOWN signal received from the OS.")
+
+ # Treat shutdown similar to stop.
+
+ service_stop
end
################################################################################
@@ -136,6 +159,19 @@ class Chef
private
+ # Initializes Chef::Client instance and runs it
+ def run_chef_client
+ @chef_client = Chef::Client.new(
+ @chef_client_json,
+ :override_runlist => config[:override_runlist]
+ )
+ @chef_client_json = nil
+
+ @chef_client.run
+ @chef_client = nil
+ end
+
+
def apply_config(config_file_path)
Chef::Config.from_file(config_file_path)
Chef::Config.merge!(config)
@@ -155,16 +191,52 @@ class Chef
Chef::Config[:interval] ||= 1800
end
- # Lifted from Chef::Application and Chef::Application::Client
- # MUST BE RUN AFTER configuration has been parsed!
+ # Lifted from application.rb
+ # See application.rb for related comments.
+
def configure_logging
- # Implementation from Chef::Application
- Chef::Log.init(Chef::Config[:log_location])
- Chef::Log.level = Chef::Config[:log_level]
+ Chef::Log.init(MonoLogger.new(Chef::Config[:log_location]))
+ if want_additional_logger?
+ configure_stdout_logger
+ end
+ Chef::Log.level = resolve_log_level
+ end
- # Implementation from Chef::Application::Client
- Mixlib::Authentication::Log.use_log_devices( Chef::Log )
- Ohai::Log.use_log_devices( Chef::Log )
+ def configure_stdout_logger
+ stdout_logger = MonoLogger.new(STDOUT)
+ STDOUT.sync = true
+ stdout_logger.formatter = Chef::Log.logger.formatter
+ Chef::Log.loggers << stdout_logger
+ end
+
+ # Based on config and whether or not STDOUT is a tty, should we setup a
+ # secondary logger for stdout?
+ def want_additional_logger?
+ ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && (!Chef::Config[:daemonize]) && (Chef::Config[:force_logger])
+ end
+
+ # Use of output formatters is assumed if `force_formatter` is set or if
+ # `force_logger` is not set and STDOUT is to a console (tty)
+ def using_output_formatter?
+ Chef::Config[:force_formatter] || (!Chef::Config[:force_logger] && STDOUT.tty?)
+ end
+
+ def auto_log_level?
+ Chef::Config[:log_level] == :auto
+ end
+
+ # if log_level is `:auto`, convert it to :warn (when using output formatter)
+ # or :info (no output formatter). See also +using_output_formatter?+
+ def resolve_log_level
+ if auto_log_level?
+ if using_output_formatter?
+ :warn
+ else
+ :info
+ end
+ else
+ Chef::Config[:log_level]
+ end
end
def configure_chef(startup_parameters)
@@ -205,20 +277,6 @@ class Chef
end
end
- # Since we need to be able to respond to signals between Chef runs, we need to periodically
- # wake up to see if we're still in the running state. The method returns when it has slept
- # for +sec+ seconds (but at least +10+ seconds), or when the service
- # is no client_sleep in the +RUNNING+ state, whichever comes first.
- def client_sleep(sec)
- chunk_length = 10
- chunks = sec / chunk_length
- chunks = 1 if chunks < 1
- (1..chunks).each do
- return unless state == RUNNING
- sleep chunk_length
- end
- end
-
end
end
end
diff --git a/lib/chef/application/windows_service_manager.rb b/lib/chef/application/windows_service_manager.rb
new file mode 100644
index 0000000000..ef93e88517
--- /dev/null
+++ b/lib/chef/application/windows_service_manager.rb
@@ -0,0 +1,165 @@
+#
+# Author:: Seth Chisamore (<schisamo@opscode.com>)
+# Copyright:: Copyright (c) 2011 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'win32/service'
+require 'chef/config'
+require 'mixlib/cli'
+
+class Chef
+ class Application
+ class WindowsServiceManager
+ include Mixlib::CLI
+
+ option :action,
+ :short => "-a ACTION",
+ :long => "--action ACTION",
+ :default => "start",
+ :description => "Action to carry out on chef-service (install, uninstall, status, start, stop, pause, or resume)"
+
+ option :config_file,
+ :short => "-c CONFIG",
+ :long => "--config CONFIG",
+ :default => "#{ENV['SYSTEMDRIVE']}/chef/client.rb",
+ :description => "The configuration file to use for chef runs"
+
+ option :log_location,
+ :short => "-L LOGLOCATION",
+ :long => "--logfile LOGLOCATION",
+ :description => "Set the log file location for chef-service",
+ :default => "#{ENV['SYSTEMDRIVE']}/chef/client.log"
+
+ option :splay,
+ :short => "-s SECONDS",
+ :long => "--splay SECONDS",
+ :description => "The splay time for running at intervals, in seconds",
+ :proc => lambda { |s| s.to_i }
+
+ option :interval,
+ :short => "-i SECONDS",
+ :long => "--interval SECONDS",
+ :description => "Set the number of seconds to wait between chef-client runs",
+ :proc => lambda { |s| s.to_i }
+
+ option :help,
+ :short => "-h",
+ :long => "--help",
+ :description => "Show this message",
+ :on => :tail,
+ :boolean => true,
+ :show_options => true,
+ :exit => 0
+
+ CHEF_SERVICE_NAME = "chef-client"
+ CHEF_SERVICE_DISPLAY_NAME = "Chef-Client Service"
+ CHEF_SERVICE_DESCRIPTION = "Runs chef-client periodically"
+
+ def run
+ parse_options
+
+ case config[:action]
+ when 'install'
+ if service_exists?
+ puts "Service #{CHEF_SERVICE_NAME} already exists on the system."
+ else
+ ruby = File.join(RbConfig::CONFIG['bindir'], 'ruby')
+ path = File.expand_path(File.join(File.dirname(__FILE__), 'windows_service.rb'))
+
+ opts = ""
+ opts << " -c #{config[:config_file]}" if config[:config_file]
+ opts << " -L #{config[:log_location]}" if config[:log_location]
+ opts << " -i #{config[:interval]}" if config[:interval]
+ opts << " -s #{config[:splay]}" if config[:splay]
+
+ # Quote the full paths to deal with possible spaces in the path name.
+ # Also ensure all forward slashes are backslashes
+ cmd = "\"#{ruby}\" \"#{path}\" #{opts}".gsub(File::SEPARATOR, File::ALT_SEPARATOR)
+
+ ::Win32::Service.new(
+ :service_name => CHEF_SERVICE_NAME,
+ :display_name => CHEF_SERVICE_DISPLAY_NAME,
+ :description => CHEF_SERVICE_DESCRIPTION,
+ :start_type => ::Win32::Service::SERVICE_AUTO_START,
+ :binary_path_name => cmd)
+ puts "Service '#{CHEF_SERVICE_NAME}' has successfully been installed."
+ end
+ when 'status'
+ if !service_exists?
+ puts "Service #{CHEF_SERVICE_NAME} doesn't exist on the system."
+ else
+ puts "State of #{CHEF_SERVICE_NAME} service is: #{current_state}"
+ end
+ when 'start'
+ # TODO: allow override of startup parameters here?
+ take_action('start', RUNNING)
+ when 'stop'
+ take_action('stop', STOPPED)
+ when 'uninstall', 'delete'
+ take_action('stop', STOPPED)
+ unless service_exists?
+ puts "Service #{CHEF_SERVICE_NAME} doesn't exist on the system."
+ else
+ ::Win32::Service.delete(CHEF_SERVICE_NAME)
+ puts "Service #{CHEF_SERVICE_NAME} deleted"
+ end
+ when 'pause'
+ take_action('pause', PAUSED)
+ when 'resume'
+ take_action('resume', RUNNING)
+ end
+ end
+
+ private
+
+ # Just some state constants
+ STOPPED = "stopped"
+ RUNNING = "running"
+ PAUSED = "paused"
+
+ def service_exists?
+ return ::Win32::Service.exists?(CHEF_SERVICE_NAME)
+ end
+
+ def take_action(action=nil, desired_state=nil)
+ if service_exists?
+ if current_state != desired_state
+ ::Win32::Service.send(action, CHEF_SERVICE_NAME)
+ wait_for_state(desired_state)
+ puts "Service '#{CHEF_SERVICE_NAME}' is now '#{current_state}'."
+ else
+ puts "Service '#{CHEF_SERVICE_NAME}' is already '#{desired_state}'."
+ end
+ else
+ puts "Cannot '#{action}' service '#{CHEF_SERVICE_NAME}', service does not exist."
+ end
+ end
+
+ def current_state
+ ::Win32::Service.status(CHEF_SERVICE_NAME).current_state
+ end
+
+ # Helper method that waits for a status to change its state since state
+ # changes aren't usually instantaneous.
+ def wait_for_state(desired_state)
+ while current_state != desired_state
+ puts "One moment... #{current_state}"
+ sleep 1
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 580a64ffbe..a70c892e1b 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -565,7 +565,7 @@ class Chef
cookbook_version.manifest = o
# We don't need the following step when we decide to stop supporting deprecated operators in the metadata (e.g. <<, >>)
- cookbook_version.manifest["metadata"] = JSON.parse(cookbook_version.metadata.to_json)
+ cookbook_version.manifest["metadata"] = Chef::JSONCompat.from_json(cookbook_version.metadata.to_json)
cookbook_version.freeze_version if o["frozen?"]
cookbook_version
diff --git a/lib/chef/data_bag.rb b/lib/chef/data_bag.rb
index 9ce6215b20..be88d07e59 100644
--- a/lib/chef/data_bag.rb
+++ b/lib/chef/data_bag.rb
@@ -101,7 +101,7 @@ class Chef
end
Dir.glob(File.join(Chef::Config[:data_bag_path], "#{name}", "*.json")).inject({}) do |bag, f|
- item = JSON.parse(IO.read(f))
+ item = Chef::JSONCompat.from_json(IO.read(f))
bag[item['id']] = item
bag
end
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index c8654d7801..783a640654 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -97,6 +97,8 @@ class Chef
# Attempting to run windows code on a not-windows node
class Win32NotWindows < RuntimeError; end
class WindowsNotAdmin < RuntimeError; end
+ # Attempting to access a 64-bit only resource on a 32-bit Windows system
+ class Win32ArchitectureIncorrect < RuntimeError; end
class ObsoleteDependencySyntax < ArgumentError; end
class InvalidDataBagPath < ArgumentError; end
@@ -131,7 +133,7 @@ class Chef
class StaleAttributeRead < StandardError; end
#Registry Helper throws the following errors
- class Win32RegArchitectureIncorrect < RuntimeError; end
+ class Win32RegArchitectureIncorrect < Win32ArchitectureIncorrect; end
class Win32RegHiveMissing < ArgumentError; end
class Win32RegKeyMissing < RuntimeError; end
class Win32RegValueMissing < RuntimeError; end
diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb
index 9f59a41839..e4795cfd7e 100644
--- a/lib/chef/json_compat.rb
+++ b/lib/chef/json_compat.rb
@@ -24,7 +24,22 @@ class Chef
class JSONCompat
JSON_MAX_NESTING = 1000
+ JSON_CLASS = "json_class".freeze
+
+ CHEF_APICLIENT = "Chef::ApiClient".freeze
+ CHEF_CHECKSUM = "Chef::Checksum".freeze
+ CHEF_COOKBOOKVERSION = "Chef::CookbookVersion".freeze
+ CHEF_DATABAG = "Chef::DataBag".freeze
+ CHEF_DATABAGITEM = "Chef::DataBagItem".freeze
+ CHEF_ENVIRONMENT = "Chef::Environment".freeze
+ CHEF_NODE = "Chef::Node".freeze
+ CHEF_ROLE = "Chef::Role".freeze
+ CHEF_SANDBOX = "Chef::Sandbox".freeze
+ CHEF_RESOURCE = "Chef::Resource".freeze
+ CHEF_RESOURCECOLLECTION = "Chef::ResourceCollection".freeze
+
class <<self
+
# See CHEF-1292/PL-538. Increase the max nesting for JSON, which defaults
# to 19, and isn't enough for some (for example, a Node within a Node)
# structures.
@@ -38,7 +53,49 @@ class Chef
# Just call the JSON gem's parse method with a modified :max_nesting field
def from_json(source, opts = {})
- ::JSON.parse(source, opts_add_max_nesting(opts))
+ obj = ::Yajl::Parser.parse(source)
+
+ # JSON gem requires top level object to be a Hash or Array (otherwise
+ # you get the "must contain two octets" error). Yajl doesn't impose the
+ # same limitation. For compatibility, we re-impose this condition.
+ unless obj.kind_of?(Hash) or obj.kind_of?(Array)
+ raise JSON::ParserError, "Top level JSON object must be a Hash or Array. (actual: #{obj.class})"
+ end
+
+ # The old default in the json gem (which we are mimicing because we
+ # sadly rely on this misfeature) is to "create additions" i.e., convert
+ # JSON objects into ruby objects. Explicit :create_additions => false
+ # is required to turn it off.
+ if opts[:create_additions].nil? || opts[:create_additions]
+ map_to_rb_obj(obj)
+ else
+ obj
+ end
+ end
+
+ # Look at an object that's a basic type (from json parse) and convert it
+ # to an instance of Chef classes if desired.
+ def map_to_rb_obj(json_obj)
+ case json_obj
+ when Hash
+ mapped_hash = map_hash_to_rb_obj(json_obj)
+ if json_obj.has_key?(JSON_CLASS) && (class_to_inflate = class_for_json_class(json_obj[JSON_CLASS]))
+ class_to_inflate.json_create(mapped_hash)
+ else
+ mapped_hash
+ end
+ when Array
+ json_obj.map {|e| map_to_rb_obj(e) }
+ else
+ json_obj
+ end
+ end
+
+ def map_hash_to_rb_obj(json_hash)
+ json_hash.each do |key, value|
+ json_hash[key] = map_to_rb_obj(value)
+ end
+ json_hash
end
def to_json(obj, opts = nil)
@@ -48,6 +105,46 @@ class Chef
def to_json_pretty(obj, opts = nil)
::JSON.pretty_generate(obj, opts_add_max_nesting(opts))
end
+
+
+ # Map +json_class+ to a Class object. We use a +case+ instead of a Hash
+ # assigned to a constant because otherwise this file could not be loaded
+ # until all the constants were defined, which means you'd have to load
+ # the world to get json, which would make knife very slow.
+ def class_for_json_class(json_class)
+ case json_class
+ when CHEF_APICLIENT
+ Chef::ApiClient
+ when CHEF_CHECKSUM
+ Chef::Checksum
+ when CHEF_COOKBOOKVERSION
+ Chef::CookbookVersion
+ when CHEF_DATABAG
+ Chef::DataBag
+ when CHEF_DATABAGITEM
+ Chef::DataBagItem
+ when CHEF_ENVIRONMENT
+ Chef::Environment
+ when CHEF_NODE
+ Chef::Node
+ when CHEF_ROLE
+ Chef::Role
+ when CHEF_SANDBOX
+ # a falsey return here will disable object inflation/"create
+ # additions" in the caller. In Chef 11 this is correct, we just have
+ # a dummy Chef::Sandbox class for compat with Chef 10 servers.
+ false
+ when CHEF_RESOURCE
+ Chef::Resource
+ when CHEF_RESOURCECOLLECTION
+ Chef::ResourceCollection
+ when /^Chef::Resource/
+ Chef::Resource.find_subclass_by_name(json_class)
+ else
+ raise JSON::ParserError, "Unsupported `json_class` type '#{json_class}'"
+ end
+ end
+
end
end
end
diff --git a/lib/chef/knife/configure.rb b/lib/chef/knife/configure.rb
index e818239a89..eaf42544c0 100644
--- a/lib/chef/knife/configure.rb
+++ b/lib/chef/knife/configure.rb
@@ -27,6 +27,7 @@ class Chef
deps do
require 'ohai'
Chef::Knife::ClientCreate.load_deps
+ Chef::Knife::UserCreate.load_deps
end
banner "knife configure (options)"
@@ -40,15 +41,15 @@ class Chef
:short => "-i",
:long => "--initial",
:boolean => true,
- :description => "Create an initial API Client"
+ :description => "Create an initial API User"
option :admin_client_name,
:long => "--admin-client-name NAME",
- :description => "The existing admin clientname (usually chef-webui)"
+ :description => "The existing admin clientname (usually admin)"
option :admin_client_key,
:long => "--admin-client-key PATH",
- :description => "The path to the admin client's private key (usually a file named webui.pem)"
+ :description => "The path to the admin client's private key (usually a file named admin.pem)"
option :validation_client_name,
:long => "--validation-client-name NAME",
@@ -93,13 +94,15 @@ EOH
Chef::Config[:chef_server_url] = chef_server
Chef::Config[:node_name] = admin_client_name
Chef::Config[:client_key] = admin_client_key
- client_create = Chef::Knife::ClientCreate.new
- client_create.name_args = [ new_client_name ]
- client_create.config[:admin] = true
- client_create.config[:file] = new_client_key
- client_create.config[:yes] = true
- client_create.config[:disable_editing] = true
- client_create.run
+ user_create = Chef::Knife::UserCreate.new
+ user_create.name_args = [ new_client_name ]
+ user_create.config[:user_password] = config[:user_password] ||
+ ui.ask("Please enter a password for the new user: ") {|q| q.echo = false}
+ user_create.config[:admin] = true
+ user_create.config[:file] = new_client_key
+ user_create.config[:yes] = true
+ user_create.config[:disable_editing] = true
+ user_create.run
else
ui.msg("*****")
ui.msg("")
@@ -132,9 +135,9 @@ EOH
server_name = guess_servername
@chef_server = config[:chef_server_url] || ask_question("Please enter the chef server URL: ", :default => "http://#{server_name}:4000")
if config[:initial]
- @new_client_name = config[:node_name] || ask_question("Please enter a clientname for the new client: ", :default => Etc.getlogin)
- @admin_client_name = config[:admin_client_name] || ask_question("Please enter the existing admin clientname: ", :default => 'chef-webui')
- @admin_client_key = config[:admin_client_key] || ask_question("Please enter the location of the existing admin client's private key: ", :default => '/etc/chef/webui.pem')
+ @new_client_name = config[:node_name] || ask_question("Please enter a name for the new user: ", :default => Etc.getlogin)
+ @admin_client_name = config[:admin_client_name] || ask_question("Please enter the existing admin name: ", :default => 'admin')
+ @admin_client_key = config[:admin_client_key] || ask_question("Please enter the location of the existing admin's private key: ", :default => '/etc/chef/admin.pem')
@admin_client_key = File.expand_path(@admin_client_key)
else
@new_client_name = config[:node_name] || ask_question("Please enter an existing username or clientname for the API: ", :default => Etc.getlogin)
diff --git a/lib/chef/knife/user_create.rb b/lib/chef/knife/user_create.rb
new file mode 100644
index 0000000000..fa889f29ec
--- /dev/null
+++ b/lib/chef/knife/user_create.rb
@@ -0,0 +1,93 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/knife'
+
+class Chef
+ class Knife
+ class UserCreate < Knife
+
+ deps do
+ require 'chef/user'
+ require 'chef/json_compat'
+ end
+
+ option :file,
+ :short => "-f FILE",
+ :long => "--file FILE",
+ :description => "Write the private key to a file"
+
+ option :admin,
+ :short => "-a",
+ :long => "--admin",
+ :description => "Create the user as an admin",
+ :boolean => true
+
+ option :user_password,
+ :short => "-p PASSWORD",
+ :long => "--password PASSWORD",
+ :description => "Password for newly created user",
+ :default => ""
+
+ option :user_key,
+ :long => "--user-key FILENAME",
+ :description => "Public key for newly created user. By default a key will be created for you."
+
+ banner "knife user create USER (options)"
+
+ def run
+ @user_name = @name_args[0]
+
+ if @user_name.nil?
+ show_usage
+ ui.fatal("You must specify a user name")
+ exit 1
+ end
+
+ if config[:user_password].length == 0
+ show_usage
+ ui.fatal("You must specify a non-blank password")
+ exit 1
+ end
+
+ user = Chef::User.new
+ user.name(@user_name)
+ user.admin(config[:admin])
+ user.password config[:user_password]
+
+ if config[:user_key]
+ user.public_key File.read(File.expand_path(config[:user_key]))
+ end
+
+ output = edit_data(user)
+ user = Chef::User.from_hash(output).create
+
+ ui.info("Created #{user}")
+ if user.private_key
+ if config[:file]
+ File.open(config[:file], "w") do |f|
+ f.print(user.private_key)
+ end
+ else
+ puts user.private_key
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/user_delete.rb b/lib/chef/knife/user_delete.rb
new file mode 100644
index 0000000000..b7af11bec8
--- /dev/null
+++ b/lib/chef/knife/user_delete.rb
@@ -0,0 +1,46 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/knife'
+
+class Chef
+ class Knife
+ class UserDelete < Knife
+
+ deps do
+ require 'chef/user'
+ require 'chef/json_compat'
+ end
+
+ banner "knife user delete USER (options)"
+
+ def run
+ @user_name = @name_args[0]
+
+ if @user_name.nil?
+ show_usage
+ ui.fatal("You must specify a user name")
+ exit 1
+ end
+
+ delete_object(Chef::User, @user_name)
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/knife/user_edit.rb b/lib/chef/knife/user_edit.rb
new file mode 100644
index 0000000000..ae319c8872
--- /dev/null
+++ b/lib/chef/knife/user_edit.rb
@@ -0,0 +1,53 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/knife'
+
+class Chef
+ class Knife
+ class UserEdit < Knife
+
+ deps do
+ require 'chef/user'
+ require 'chef/json_compat'
+ end
+
+ banner "knife user edit USER (options)"
+
+ def run
+ @user_name = @name_args[0]
+
+ if @user_name.nil?
+ show_usage
+ ui.fatal("You must specify a user name")
+ exit 1
+ end
+
+ original_user = Chef::User.load(@user_name).to_hash
+ edited_user = edit_data(original_user)
+ if original_user != edited_user
+ user = Chef::User.from_hash(edited_user)
+ user.update
+ ui.msg("Saved #{user}.")
+ else
+ ui.msg("User unchaged, not saving.")
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/user_list.rb b/lib/chef/knife/user_list.rb
new file mode 100644
index 0000000000..5d2e735a73
--- /dev/null
+++ b/lib/chef/knife/user_list.rb
@@ -0,0 +1,42 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/knife'
+
+class Chef
+ class Knife
+ class UserList < Knife
+
+ deps do
+ require 'chef/user'
+ require 'chef/json_compat'
+ end
+
+ banner "knife user list (options)"
+
+ option :with_uri,
+ :short => "-w",
+ :long => "--with-uri",
+ :description => "Show corresponding URIs"
+
+ def run
+ output(format_list_for_display(Chef::User.list))
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/user_reregister.rb b/lib/chef/knife/user_reregister.rb
new file mode 100644
index 0000000000..946150e6e4
--- /dev/null
+++ b/lib/chef/knife/user_reregister.rb
@@ -0,0 +1,59 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/knife'
+
+class Chef
+ class Knife
+ class UserReregister < Knife
+
+ deps do
+ require 'chef/user'
+ require 'chef/json_compat'
+ end
+
+ banner "knife user reregister USER (options)"
+
+ option :file,
+ :short => "-f FILE",
+ :long => "--file FILE",
+ :description => "Write the private key to a file"
+
+ def run
+ @user_name = @name_args[0]
+
+ if @user_name.nil?
+ show_usage
+ ui.fatal("You must specify a user name")
+ exit 1
+ end
+
+ user = Chef::User.load(@user_name).reregister
+ Chef::Log.debug("Updated user data: #{user.inspect}")
+ key = user.private_key
+ if config[:file]
+ File.open(config[:file], "w") do |f|
+ f.print(key)
+ end
+ else
+ ui.msg key
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/user_show.rb b/lib/chef/knife/user_show.rb
new file mode 100644
index 0000000000..5088210b4d
--- /dev/null
+++ b/lib/chef/knife/user_show.rb
@@ -0,0 +1,52 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2009 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/knife'
+
+class Chef
+ class Knife
+ class UserShow < Knife
+
+ deps do
+ require 'chef/user'
+ require 'chef/json_compat'
+ end
+
+ banner "knife user show USER (options)"
+
+ option :attribute,
+ :short => "-a ATTR",
+ :long => "--attribute ATTR",
+ :description => "Show only one attribute"
+
+ def run
+ @user_name = @name_args[0]
+
+ if @user_name.nil?
+ show_usage
+ ui.fatal("You must specify a user name")
+ exit 1
+ end
+
+ user = Chef::User.load(@user_name)
+ output(format_for_display(user))
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/log.rb b/lib/chef/log.rb
index 7355ec7574..131d706a5e 100644
--- a/lib/chef/log.rb
+++ b/lib/chef/log.rb
@@ -18,6 +18,7 @@
# limitations under the License.
require 'logger'
+require 'chef/monologger'
require 'mixlib/log'
class Chef
@@ -25,8 +26,7 @@ class Chef
extend Mixlib::Log
# Force initialization of the primary log device (@logger)
- init
-
+ init(MonoLogger.new(STDOUT))
class Formatter
def self.show_time=(*args)
diff --git a/lib/chef/mixin/windows_architecture_helper.rb b/lib/chef/mixin/windows_architecture_helper.rb
new file mode 100644
index 0000000000..38c08e236d
--- /dev/null
+++ b/lib/chef/mixin/windows_architecture_helper.rb
@@ -0,0 +1,91 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+require 'chef/exceptions'
+require 'win32/api' if Chef::Platform.windows?
+
+class Chef
+ module Mixin
+ module WindowsArchitectureHelper
+
+ def node_windows_architecture(node)
+ node[:kernel][:machine].to_sym
+ end
+
+ def wow64_architecture_override_required?(node, desired_architecture)
+ is_i386_windows_process? &&
+ node_windows_architecture(node) == :x86_64 &&
+ desired_architecture == :x86_64
+ end
+
+ def node_supports_windows_architecture?(node, desired_architecture)
+ assert_valid_windows_architecture!(desired_architecture)
+ return (node_windows_architecture(node) == :x86_64 ||
+ desired_architecture == :i386) ? true : false
+ end
+
+ def valid_windows_architecture?(architecture)
+ return (architecture == :x86_64) || (architecture == :i386)
+ end
+
+ def assert_valid_windows_architecture!(architecture)
+ if ! valid_windows_architecture?(architecture)
+ raise Chef::Exceptions::Win32ArchitectureIncorrect,
+ "The specified architecture was not valid. It must be one of :i386 or :x86_64"
+ end
+ end
+
+ def is_i386_windows_process?
+ Chef::Platform.windows? && 'X86'.casecmp(ENV['PROCESSOR_ARCHITECTURE']) == 0
+ end
+
+ def disable_wow64_file_redirection( node )
+ original_redirection_state = ['0'].pack('P')
+
+ if ( ( node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?)
+ win32_wow_64_disable_wow_64_fs_redirection =
+ ::Win32::API.new('Wow64DisableWow64FsRedirection', 'P', 'L', 'kernel32')
+
+ succeeded = win32_wow_64_disable_wow_64_fs_redirection.call(original_redirection_state)
+
+ if succeeded == 0
+ raise Win32APIError "Failed to disable Wow64 file redirection"
+ end
+
+ end
+
+ original_redirection_state
+ end
+
+ def restore_wow64_file_redirection( node, original_redirection_state )
+ if ( (node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?)
+ win32_wow_64_revert_wow_64_fs_redirection =
+ ::Win32::API.new('Wow64RevertWow64FsRedirection', 'P', 'L', 'kernel32')
+
+ succeeded = win32_wow_64_revert_wow_64_fs_redirection.call(original_redirection_state)
+
+ if succeeded == 0
+ raise Win32APIError "Failed to revert Wow64 file redirection"
+ end
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/monologger.rb b/lib/chef/monologger.rb
new file mode 100644
index 0000000000..fed60514d7
--- /dev/null
+++ b/lib/chef/monologger.rb
@@ -0,0 +1,93 @@
+require 'logger'
+
+require 'pp'
+
+#== MonoLogger
+# A subclass of Ruby's stdlib Logger with all the mutex and logrotation stuff
+# ripped out.
+class MonoLogger < Logger
+
+ #
+ # === Synopsis
+ #
+ # Logger.new(name, shift_age = 7, shift_size = 1048576)
+ # Logger.new(name, shift_age = 'weekly')
+ #
+ # === Args
+ #
+ # +logdev+::
+ # The log device. This is a filename (String) or IO object (typically
+ # +STDOUT+, +STDERR+, or an open file).
+ # +shift_age+::
+ # Number of old log files to keep, *or* frequency of rotation (+daily+,
+ # +weekly+ or +monthly+).
+ # +shift_size+::
+ # Maximum logfile size (only applies when +shift_age+ is a number).
+ #
+ # === Description
+ #
+ # Create an instance.
+ #
+ def initialize(logdev)
+ @progname = nil
+ @level = DEBUG
+ @default_formatter = Formatter.new
+ @formatter = nil
+ @logdev = nil
+ if logdev
+ @logdev = LocklessLogDevice.new(logdev)
+ end
+ end
+
+
+ class LocklessLogDevice < LogDevice
+
+ def initialize(log = nil)
+ @dev = @filename = @shift_age = @shift_size = nil
+ if log.respond_to?(:write) and log.respond_to?(:close)
+ @dev = log
+ else
+ @dev = open_logfile(log)
+ @dev.sync = true
+ @filename = log
+ end
+ end
+
+ def write(message)
+ @dev.write(message)
+ rescue Exception => ignored
+ warn("log writing failed. #{ignored}")
+ end
+
+ def close
+ @dev.close rescue nil
+ end
+
+ private
+
+ def open_logfile(filename)
+ if (FileTest.exist?(filename))
+ open(filename, (File::WRONLY | File::APPEND))
+ else
+ create_logfile(filename)
+ end
+ end
+
+ def create_logfile(filename)
+ logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT))
+ logdev.sync = true
+ add_log_header(logdev)
+ logdev
+ end
+
+ def add_log_header(file)
+ file.write(
+ "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
+ )
+ end
+
+ end
+
+
+end
+
diff --git a/lib/chef/platform.rb b/lib/chef/platform.rb
index 6e6de6004e..b176e9c731 100644
--- a/lib/chef/platform.rb
+++ b/lib/chef/platform.rb
@@ -72,6 +72,14 @@ class Chef
:mdadm => Chef::Provider::Mdadm
}
},
+ :gcel => {
+ :default => {
+ :package => Chef::Provider::Package::Apt,
+ :service => Chef::Provider::Service::Debian,
+ :cron => Chef::Provider::Cron,
+ :mdadm => Chef::Provider::Mdadm
+ }
+ },
:linaro => {
:default => {
:package => Chef::Provider::Package::Apt,
diff --git a/lib/chef/provider/batch.rb b/lib/chef/provider/batch.rb
new file mode 100644
index 0000000000..e4b35b64f3
--- /dev/null
+++ b/lib/chef/provider/batch.rb
@@ -0,0 +1,35 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/provider/windows_script'
+
+class Chef
+ class Provider
+ class Batch < Chef::Provider::WindowsScript
+
+ def initialize (new_resource, run_context)
+ super(new_resource, run_context, '.bat')
+ end
+
+ def flags
+ @new_resource.flags.nil? ? '/c' : new_resource.flags + ' /c'
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb
index e60d73ab62..b451450a8c 100644
--- a/lib/chef/provider/package/rubygems.rb
+++ b/lib/chef/provider/package/rubygems.rb
@@ -31,7 +31,14 @@ require 'rubygems/version'
require 'rubygems/dependency'
require 'rubygems/spec_fetcher'
require 'rubygems/platform'
-require 'rubygems/format'
+
+# Compatibility note: Rubygems 2.0 removes rubygems/format in favor of
+# rubygems/package.
+begin
+ require 'rubygems/format'
+rescue LoadError
+ require 'rubygems/package'
+end
require 'rubygems/dependency_installer'
require 'rubygems/uninstaller'
require 'rubygems/specification'
@@ -106,6 +113,22 @@ class Chef
end
##
+ # Extracts the gemspec from a (on-disk) gem package.
+ # === Returns
+ # Gem::Specification
+ #
+ #--
+ # Compatibility note: Rubygems 1.x uses Gem::Format, 2.0 moved this
+ # code into Gem::Package.
+ def spec_from_file(file)
+ if defined?(Gem::Format)
+ Gem::Format.from_file_by_path(file).spec
+ else
+ Gem::Package.new(file).spec
+ end
+ end
+
+ ##
# Determines the candidate version for a gem from a .gem file on disk
# and checks if it matches the version contraints in +gem_dependency+
# === Returns
@@ -114,7 +137,7 @@ class Chef
# nil returns nil if the gem on disk doesn't match the
# version constraints for +gem_dependency+
def candidate_version_from_file(gem_dependency, source)
- spec = Gem::Format.from_file_by_path(source).spec
+ spec = spec_from_file(source)
if spec.satisfies_requirement?(gem_dependency)
logger.debug {"#{@new_resource} found candidate gem version #{spec.version} from local gem package #{source}"}
spec.version
@@ -142,17 +165,26 @@ class Chef
# Find the newest gem version available from Gem.sources that satisfies
# the constraints of +gem_dependency+
def find_newest_remote_version(gem_dependency, *sources)
- # DependencyInstaller sorts the results such that the last one is
- # always the one it considers best.
- spec_with_source = dependency_installer.find_gems_with_sources(gem_dependency).last
+ available_gems = dependency_installer.find_gems_with_sources(gem_dependency)
+ spec, source = if available_gems.respond_to?(:last)
+ # DependencyInstaller sorts the results such that the last one is
+ # always the one it considers best.
+ spec_with_source = available_gems.last
+ spec_with_source && spec_with_source
+ else
+ # Rubygems 2.0 returns a Gem::Available set, which is a
+ # collection of AvailableSet::Tuple structs
+ available_gems.pick_best!
+ best_gem = available_gems.set.first
+ best_gem && [best_gem.spec, best_gem.source]
+ end
- spec = spec_with_source && spec_with_source[0]
- version = spec && spec_with_source[0].version
+ version = spec && spec.version
if version
- logger.debug { "#{@new_resource} found gem #{spec.name} version #{version} for platform #{spec.platform} from #{spec_with_source[1]}" }
+ logger.debug { "#{@new_resource} found gem #{spec.name} version #{version} for platform #{spec.platform} from #{source}" }
version
else
- source_list = sources.compact.empty? ? "[#{Gem.sources.join(', ')}]" : "[#{sources.join(', ')}]"
+ source_list = sources.compact.empty? ? "[#{Gem.sources.to_a.join(', ')}]" : "[#{sources.join(', ')}]"
logger.warn { "#{@new_resource} failed to find gem #{gem_dependency} from #{source_list}" }
nil
end
diff --git a/lib/chef/provider/powershell.rb b/lib/chef/provider/powershell.rb
new file mode 100644
index 0000000000..aaa4a9255e
--- /dev/null
+++ b/lib/chef/provider/powershell.rb
@@ -0,0 +1,35 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/provider/windows_script'
+
+class Chef
+ class Provider
+ class Powershell < Chef::Provider::WindowsScript
+
+ def initialize (new_resource, run_context)
+ super(new_resource, run_context, '.ps1')
+ end
+
+ def flags
+ @new_resource.flags.nil? ? '-ExecutionPolicy RemoteSigned -Command' : @new_resource.flags + '-ExecutionPolicy RemoteSigned -Command'
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/provider/remote_file/ftp.rb b/lib/chef/provider/remote_file/ftp.rb
index cb06766bb3..74cc0d4ced 100644
--- a/lib/chef/provider/remote_file/ftp.rb
+++ b/lib/chef/provider/remote_file/ftp.rb
@@ -49,7 +49,7 @@ class Chef
raise ArgumentError, "invalid typecode: #{@typecode.inspect}"
end
@ftp_active_mode = ftp_active_mode
- @hostname = uri.hostname
+ @hostname = uri.host
@port = uri.port
@ftp = Net::FTP.new
if uri.userinfo
diff --git a/lib/chef/provider/script.rb b/lib/chef/provider/script.rb
index 9e5a7d7fe1..f1b765d52a 100644
--- a/lib/chef/provider/script.rb
+++ b/lib/chef/provider/script.rb
@@ -29,7 +29,7 @@ class Chef
set_owner_and_group
- @new_resource.command("\"#{@new_resource.interpreter}\" #{@new_resource.flags} \"#{script_file.path}\"")
+ @new_resource.command("\"#{interpreter}\" #{flags} \"#{script_file.path}\"")
super
converge_by(nil) do
# ensure script is unlinked at end of converge!
@@ -52,6 +52,13 @@ class Chef
@script_file && @script_file.close!
end
+ def interpreter
+ @new_resource.interpreter
+ end
+
+ def flags
+ @new_resource.flags
+ end
end
end
end
diff --git a/lib/chef/provider/windows_script.rb b/lib/chef/provider/windows_script.rb
new file mode 100644
index 0000000000..398e1aee6e
--- /dev/null
+++ b/lib/chef/provider/windows_script.rb
@@ -0,0 +1,73 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/provider/script'
+require 'chef/mixin/windows_architecture_helper'
+
+class Chef
+ class Provider
+ class WindowsScript < Chef::Provider::Script
+
+ protected
+
+ include Chef::Mixin::WindowsArchitectureHelper
+
+ def initialize( new_resource, run_context, script_extension='')
+ super( new_resource, run_context )
+ @script_extension = script_extension
+
+ target_architecture = new_resource.architecture.nil? ?
+ node_windows_architecture(run_context.node) : new_resource.architecture
+
+ @is_wow64 = wow64_architecture_override_required?(run_context.node, target_architecture)
+
+ if ( target_architecture == :i386 ) && ! is_i386_windows_process?
+ raise Chef::Exceptions::Win32ArchitectureIncorrect,
+ "Support for the i386 architecture from a 64-bit Ruby runtime is not yet implemented"
+ end
+ end
+
+ public
+
+ def action_run
+ wow64_redirection_state = nil
+
+ if @is_wow64
+ wow64_redirection_state = disable_wow64_file_redirection(@run_context.node)
+ end
+
+ begin
+ super
+ rescue
+ raise
+ ensure
+ if ! wow64_redirection_state.nil?
+ restore_wow64_file_redirection(@run_context.node, wow64_redirection_state)
+ end
+ end
+ end
+
+ def script_file
+ base_script_name = "chef-script"
+ temp_file_arguments = [ base_script_name, @script_extension ]
+
+ @script_file ||= Tempfile.open(temp_file_arguments)
+ end
+ end
+ end
+end
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index 0c7aed61b8..f4b3175546 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -16,6 +16,7 @@
# limitations under the License.
#
+require 'chef/provider/batch'
require 'chef/provider/breakpoint'
require 'chef/provider/cookbook_file'
require 'chef/provider/cron'
@@ -36,6 +37,7 @@ require 'chef/provider/ohai'
require 'chef/provider/mdadm'
require 'chef/provider/mount'
require 'chef/provider/package'
+require 'chef/provider/powershell'
require 'chef/provider/remote_directory'
require 'chef/provider/remote_file'
require 'chef/provider/route'
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index d18e8b0136..729632a69c 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -129,6 +129,23 @@ F
extend Chef::Mixin::ConvertToClassName
+ # Track all subclasses of Resource. This is used so names can be looked up
+ # when attempting to deserialize from JSON. (See: json_compat)
+ def self.resource_classes
+ @resource_classes ||= []
+ end
+
+ # Callback when subclass is defined. Adds subclass to list of subclasses.
+ def self.inherited(subclass)
+ resource_classes << subclass
+ end
+
+ # Look up a subclass by +class_name+ which should be a string that matches
+ # `Subclass.name`
+ def self.find_subclass_by_name(class_name)
+ resource_classes.first {|c| c.name == class_name }
+ end
+
# Set or return the list of "state attributes" implemented by the Resource
# subclass. State attributes are attributes that describe the desired state
# of the system, such as file permissions or ownership. In general, state
diff --git a/lib/chef/resource/batch.rb b/lib/chef/resource/batch.rb
new file mode 100644
index 0000000000..705260bbce
--- /dev/null
+++ b/lib/chef/resource/batch.rb
@@ -0,0 +1,31 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/resource/windows_script'
+
+class Chef
+ class Resource
+ class Batch < Chef::Resource::WindowsScript
+
+ def initialize(name, run_context=nil)
+ super(name, run_context, :batch, "cmd.exe")
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/resource/powershell.rb b/lib/chef/resource/powershell.rb
new file mode 100644
index 0000000000..e726e6f35a
--- /dev/null
+++ b/lib/chef/resource/powershell.rb
@@ -0,0 +1,31 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/resource/windows_script'
+
+class Chef
+ class Resource
+ class Powershell < Chef::Resource::WindowsScript
+
+ def initialize(name, run_context=nil)
+ super(name, run_context, :powershell, "powershell.exe")
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/resource/windows_script.rb b/lib/chef/resource/windows_script.rb
new file mode 100644
index 0000000000..5f2311a5bb
--- /dev/null
+++ b/lib/chef/resource/windows_script.rb
@@ -0,0 +1,62 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/resource/script'
+require 'chef/mixin/windows_architecture_helper'
+
+class Chef
+ class Resource
+ class WindowsScript < Chef::Resource::Script
+
+ protected
+
+ def initialize(name, run_context, resource_name, interpreter_command)
+ super(name, run_context)
+ @interpreter = interpreter_command
+ @resource_name = resource_name
+ end
+
+ include Chef::Mixin::WindowsArchitectureHelper
+
+ public
+
+ def architecture(arg=nil)
+ assert_architecture_compatible!(arg) if ! arg.nil?
+ result = set_or_return(
+ :architecture,
+ arg,
+ :kind_of => Symbol
+ )
+ end
+
+ protected
+
+ def assert_architecture_compatible!(desired_architecture)
+ if ! node_supports_windows_architecture?(node, desired_architecture)
+ raise Chef::Exceptions::Win32ArchitectureIncorrect,
+ "cannot execute script with requested architecture '#{desired_architecture.to_s}' on a system with architecture '#{node_windows_architecture(node)}'"
+ end
+ end
+
+ def node
+ run_context && run_context.node
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index 6dea46bfc9..1b295fc4e1 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -18,6 +18,7 @@
require 'chef/resource/apt_package'
require 'chef/resource/bash'
+require 'chef/resource/batch'
require 'chef/resource/breakpoint'
require 'chef/resource/cookbook_file'
require 'chef/resource/chef_gem'
@@ -49,6 +50,7 @@ require 'chef/resource/package'
require 'chef/resource/pacman_package'
require 'chef/resource/perl'
require 'chef/resource/portage_package'
+require 'chef/resource/powershell'
require 'chef/resource/python'
require 'chef/resource/registry_key'
require 'chef/resource/remote_directory'
diff --git a/lib/chef/user.rb b/lib/chef/user.rb
new file mode 100644
index 0000000000..3f592e4b65
--- /dev/null
+++ b/lib/chef/user.rb
@@ -0,0 +1,182 @@
+#
+# Author:: Steven Danna (steve@opscode.com)
+# Copyright:: Copyright 2012 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+require 'chef/config'
+require 'chef/mixin/params_validate'
+require 'chef/mixin/from_file'
+require 'chef/mash'
+require 'chef/json_compat'
+require 'chef/search/query'
+
+class Chef
+ class User
+
+ include Chef::Mixin::FromFile
+ include Chef::Mixin::ParamsValidate
+
+ def initialize
+ @name = ''
+ @public_key = nil
+ @private_key = nil
+ @password = nil
+ @admin = false
+ end
+
+ def name(arg=nil)
+ set_or_return(:name, arg,
+ :regex => /^[a-z0-9\-_]+$/)
+ end
+
+ def admin(arg=nil)
+ set_or_return(:admin,
+ arg, :kind_of => [TrueClass, FalseClass])
+ end
+
+ def public_key(arg=nil)
+ set_or_return(:public_key,
+ arg, :kind_of => String)
+ end
+
+ def private_key(arg=nil)
+ set_or_return(:private_key,
+ arg, :kind_of => String)
+ end
+
+ def password(arg=nil)
+ set_or_return(:password,
+ arg, :kind_of => String)
+ end
+
+ def to_hash
+ result = {
+ "name" => @name,
+ "public_key" => @public_key,
+ "admin" => @admin
+ }
+ result["private_key"] = @private_key if @private_key
+ result["password"] = @password if @password
+ result
+ end
+
+ def to_json(*a)
+ to_hash.to_json(*a)
+ end
+
+ def destroy
+ Chef::REST.new(Chef::Config[:chef_server_url]).delete_rest("users/#{@name}")
+ end
+
+ def create
+ payload = {:name => self.name, :admin => self.admin, :password => self.password }
+ payload[:public_key] = public_key if public_key
+ new_user =Chef::REST.new(Chef::Config[:chef_server_url]).post_rest("users", payload)
+ Chef::User.from_hash(self.to_hash.merge(new_user))
+ end
+
+ def update(new_key=false)
+ payload = {:name => name, :admin => admin}
+ payload[:private_key] = new_key if new_key
+ payload[:password] = password if password
+ updated_user = Chef::REST.new(Chef::Config[:chef_server_url]).put_rest("users/#{name}", payload)
+ Chef::User.from_hash(self.to_hash.merge(updated_user))
+ end
+
+ def save(new_key=false)
+ begin
+ create
+ rescue Net::HTTPServerException => e
+ if e.response.code == "409"
+ update(new_key)
+ else
+ raise e
+ end
+ end
+ end
+
+ def reregister
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
+ reregistered_self = r.put_rest("users/#{name}", { :name => name, :admin => admin, :private_key => true })
+ private_key(reregistered_self["private_key"])
+ self
+ end
+
+ def to_s
+ "user[#{@name}]"
+ end
+
+ def inspect
+ "Chef::User name:'#{name}' admin:'#{admin.inspect}'" +
+ "public_key:'#{public_key}' private_key:#{private_key}"
+ end
+
+ # Class Methods
+
+ def self.from_hash(user_hash)
+ user = Chef::User.new
+ user.name user_hash['name']
+ user.private_key user_hash['private_key'] if user_hash.key?('private_key')
+ user.password user_hash['password'] if user_hash.key?('password')
+ user.public_key user_hash['public_key']
+ user.admin user_hash['admin']
+ user
+ end
+
+ def self.from_json(json)
+ Chef::User.from_hash(Chef::JSONCompat.from_json(json))
+ end
+
+ class << self
+ alias_method :json_create, :from_json
+ end
+
+ def self.list(inflate=false)
+ response = if inflate
+ users = Chef::REST.new(Chef::Config[:chef_server_url]).get_rest('users')
+ users.map do |name|
+ Chef::User.load(name)
+ end
+ else
+ Chef::REST.new(Chef::Config[:chef_server_url]).get_rest('users')
+ end
+ if response.is_a? Array
+ transform_ohc_list_response(response)
+ else
+ response
+ end
+ end
+
+ def self.load(name)
+ response = Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("users/#{name}")
+ Chef::User.from_hash(response)
+ end
+
+ private
+
+ # Gross. Transforms an API response in the form of:
+ # [ { "user" => { "username" => USERNAME }}, ...]
+ # into the form
+ # { "USERNAME" => "URI" }
+ def self.transform_ohc_list_response(response)
+ new_response = Hash.new
+ response.each do |u|
+ name = u['user']['username']
+ new_response[name] = Chef::Config[:chef_server_url] + "/users/#{name}"
+ end
+ new_response
+ end
+ end
+end
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index 1c928d2d6b..faad63658c 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -17,7 +17,7 @@
class Chef
CHEF_ROOT = File.dirname(File.expand_path(File.dirname(__FILE__)))
- VERSION = '11.0.0'
+ VERSION = '11.4.0'
end
# NOTE: the Chef::Version class is defined in version_class.rb
diff --git a/lib/chef/win32/api/process.rb b/lib/chef/win32/api/process.rb
index d18ad411b4..0aca992ed5 100644
--- a/lib/chef/win32/api/process.rb
+++ b/lib/chef/win32/api/process.rb
@@ -33,6 +33,7 @@ class Chef
safe_attach_function :GetCurrentProcess, [], :HANDLE
safe_attach_function :GetProcessHandleCount, [ :HANDLE, :LPDWORD ], :BOOL
safe_attach_function :GetProcessId, [ :HANDLE ], :DWORD
+ safe_attach_function :CloseHandle, [ :HANDLE ], :BOOL
end
end
diff --git a/lib/chef/win32/handle.rb b/lib/chef/win32/handle.rb
index 60e35916ad..3e92703db9 100644
--- a/lib/chef/win32/handle.rb
+++ b/lib/chef/win32/handle.rb
@@ -26,6 +26,10 @@ class Chef
class Handle
extend Chef::ReservedNames::Win32::API::Process
+ # See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683179(v=vs.85).aspx
+ # The handle value returned by the GetCurrentProcess function is the pseudo handle (HANDLE)-1 (which is 0xFFFFFFFF)
+ CURRENT_PROCESS_HANDLE = 4294967295
+
def initialize(handle)
@handle = handle
ObjectSpace.define_finalizer(self, Handle.close_handle_finalizer(handle))
@@ -34,7 +38,10 @@ class Chef
attr_reader :handle
def self.close_handle_finalizer(handle)
- proc { close_handle(handle) }
+ # According to http://msdn.microsoft.com/en-us/library/windows/desktop/ms683179(v=vs.85).aspx, it is not necessary
+ # to close the pseudo handle returned by the GetCurrentProcess function. The docs also say that it doesn't hurt to call
+ # CloseHandle on it. However, doing so from inside of Ruby always seems to produce an invalid handle error.
+ proc { close_handle(handle) unless handle == CURRENT_PROCESS_HANDLE }
end
def self.close_handle(handle)
diff --git a/spec/data/big_json.json b/spec/data/big_json.json
index 8e095bc148..96c2818894 100644
--- a/spec/data/big_json.json
+++ b/spec/data/big_json.json
@@ -1 +1,2 @@
-{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":"test"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":"test"
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} \ No newline at end of file
diff --git a/spec/data/big_json_plus_one.json b/spec/data/big_json_plus_one.json
index 973f7fae50..8ea4b74644 100644
--- a/spec/data/big_json_plus_one.json
+++ b/spec/data/big_json_plus_one.json
@@ -1 +1,2 @@
-{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":"test"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":{"key":"test"
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
diff --git a/spec/functional/resource/batch_spec.rb b/spec/functional/resource/batch_spec.rb
new file mode 100644
index 0000000000..4374dd0730
--- /dev/null
+++ b/spec/functional/resource/batch_spec.rb
@@ -0,0 +1,70 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+shared_context Chef::Resource::WindowsScript do
+ let(:ohai) do
+ ohai_reader = Ohai::System.new
+ ohai_reader.require_plugin("os")
+ ohai_reader.require_plugin("windows::platform")
+ ohai_reader
+ end
+
+ let(:node) do
+ new_node = Chef::Node.new
+ new_node.consume_external_attrs(ohai.data,{})
+ new_node
+ end
+
+ let(:run_context) do
+ events = Chef::EventDispatch::Dispatcher.new
+
+ run_context = Chef::RunContext.new(node, {}, events)
+ end
+
+ let(:script_output_path) do
+ File.join(Dir.tmpdir, make_tmpname("windows_script_test"))
+ end
+
+ before(:each) do
+k File.delete(script_output_path) if File.exists?(script_output_path)
+ end
+
+ after(:each) do
+ File.delete(script_output_path) if File.exists?(script_output_path)
+ end
+end
+
+
+describe Chef::Resource::WindowsScript::Batch, :windows_only do
+ let(:script_content) { "whoami" }
+
+ let!(:resource) do
+ Chef::Resource::WindowsScript::Batch.new("Batch resource functional test", run_context)
+ end
+
+ context "when the run action is invoked on Windows" do
+ include_context Chef::Resource::WindowsScript
+ it "executes the script code" do
+ resource.code(script_content + " > #{script_output_path}")
+ resource.returns(0)
+ resource.run_action(:run)
+ end
+ end
+end
diff --git a/spec/functional/resource/powershell_spec.rb b/spec/functional/resource/powershell_spec.rb
new file mode 100644
index 0000000000..0673e06126
--- /dev/null
+++ b/spec/functional/resource/powershell_spec.rb
@@ -0,0 +1,40 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+require 'functional/resource/batch_spec.rb'
+
+describe Chef::Resource::WindowsScript::Powershell, :windows_only do
+ let(:script_content) { "whoami" }
+
+ let!(:resource) do
+ r = Chef::Resource::WindowsScript::Powershell.new("Powershell resource functional test", run_context)
+ r.code(script_content)
+ r
+ end
+
+ include_context Chef::Resource::WindowsScript
+
+ context "when the run action is invoked on Windows" do
+ it "executes the script code" do
+ resource.code(script_content + " > #{script_output_path}")
+ resource.returns(0)
+ resource.run_action(:run)
+ end
+ end
+end
diff --git a/spec/functional/run_lock_spec.rb b/spec/functional/run_lock_spec.rb
index 6b8039794d..5e64e42a0b 100644
--- a/spec/functional/run_lock_spec.rb
+++ b/spec/functional/run_lock_spec.rb
@@ -22,6 +22,10 @@ describe Chef::RunLock do
# This behavior is believed to work on windows, but the tests use UNIX APIs.
describe "when locking the chef-client run", :unix_only => true do
+
+ ##
+ # Lockfile location and helpers
+
let(:random_temp_root) do
Kernel.srand(Time.now.to_i + Process.pid)
"/tmp/#{Kernel.rand(Time.now.to_i + Process.pid)}"
@@ -30,75 +34,203 @@ describe Chef::RunLock do
let(:file_cache_path){ "/var/chef/cache" }
let(:lockfile){ "#{random_temp_root}/this/long/path/does/not/exist/chef-client-running.pid" }
+ # make sure to start with a clean slate.
+ before(:each){ FileUtils.rm_r(random_temp_root) if File.exist?(random_temp_root) }
after(:each){ FileUtils.rm_r(random_temp_root) }
+ def wait_on_lock
+ tries = 0
+ until File.exist?(lockfile)
+ raise "Lockfile never created, abandoning test" if tries > 10
+ tries += 1
+ sleep 0.1
+ end
+ end
+
+ ##
+ # Side channel via a pipe allows child processes to send errors to the parent
+
+ # Don't lazy create the pipe or else we might not share it with subprocesses
+ let!(:error_pipe) do
+ r,w = IO.pipe
+ w.sync = true
+ [r,w]
+ end
+
+ let(:error_read) { error_pipe[0] }
+ let(:error_write) { error_pipe[1] }
+
+ after do
+ error_read.close unless error_read.closed?
+ error_write.close unless error_write.closed?
+ end
+
+ # Send a RuntimeError from the child process to the parent process. Also
+ # prints error to $stdout, just in case something goes wrong with the error
+ # marshaling stuff.
+ def send_side_channel_error(message)
+ $stderr.puts(message)
+ $stderr.puts(caller)
+ e = RuntimeError.new(message)
+ error_write.print(Marshal.dump(e))
+ end
+
+ # Read the error (if any) from the error channel. If a marhaled error is
+ # present, it is unmarshaled and raised (which will fail the test)
+ def raise_side_channel_error!
+ error_write.close
+ err = error_read.read
+ error_read.close
+ begin
+ # ArgumentError from Marshal.load indicates no data, which we assume
+ # means no error in child process.
+ raise Marshal.load(err)
+ rescue ArgumentError
+ nil
+ end
+ end
+
+ ##
+ # Interprocess synchronization via a pipe. This allows us to control the
+ # state of the processes competing over the lock without relying on sleep.
+
+ let!(:sync_pipe) do
+ r,w = IO.pipe
+ w.sync = true
+ [r,w]
+ end
+ let(:sync_read) { sync_pipe[0] }
+ let(:sync_write) { sync_pipe[1] }
+
+ after do
+ sync_read.close unless sync_read.closed?
+ sync_write.close unless sync_write.closed?
+ end
+
+ # Wait on synchronization signal. If not received within the timeout, an
+ # error is sent via the error channel, and the process exits.
+ def sync_wait
+ if IO.select([sync_read], nil, nil, 20).nil?
+ # timeout reading from the sync pipe.
+ send_side_channel_error("Error syncing processes in run lock test (timeout)")
+ exit!(1)
+ else
+ sync_read.getc
+ end
+ end
+
+ # Sends a character in the sync pipe, which wakes ("unlocks") another
+ # process that is waiting on the sync signal
+ def sync_send
+ sync_write.putc("!")
+ sync_write.flush
+ end
+
+ ##
+ # IPC to record test results in a pipe. Tests can read pipe contents to
+ # check that operations occur in the expected order.
+
+ let!(:results_pipe) do
+ r,w = IO.pipe
+ w.sync = true
+ [r,w]
+ end
+ let(:results_read) { results_pipe[0] }
+ let(:results_write) { results_pipe[1] }
+
+ after do
+ results_read.close unless results_read.closed?
+ results_write.close unless results_write.closed?
+ end
+
+ # writes the message to the results pipe for later checking.
+ # note that nothing accounts for the pipe filling and waiting forever on a
+ # read or write call, so don't put too much data in.
+ def record(message)
+ results_write.puts(message)
+ results_write.flush
+ end
+
+ def results
+ results_write.flush
+ results_write.close
+ message = results_read.read
+ results_read.close
+ message
+ end
+
+ ##
+ # Run lock is the system under test
+ let!(:run_lock) { Chef::RunLock.new(:file_cache_path => file_cache_path, :lockfile => lockfile) }
+
it "creates the full path to the lockfile" do
- run_lock = Chef::RunLock.new(:file_cache_path => file_cache_path, :lockfile => lockfile)
lambda { run_lock.acquire }.should_not raise_error(Errno::ENOENT)
File.should exist(lockfile)
end
it "allows only one chef client run per lockfile" do
- read, write = IO.pipe
- run_lock = Chef::RunLock.new(:file_cache_path => file_cache_path, :lockfile => lockfile)
+ # First process, gets the lock and keeps it.
p1 = fork do
run_lock.acquire
- write.puts 1
- #puts "[#{Time.new.to_i % 100}] p1 (#{Process.pid}) running with lock"
+ record "p1 has lock"
+ # Wait until the other process is trying to get the lock:
+ sync_wait
+ # sleep a little bit to make process p2 wait on the lock
sleep 2
- write.puts 2
- #puts "[#{Time.new.to_i % 100}] p1 (#{Process.pid}) releasing lock"
+ record "p1 releasing lock"
run_lock.release
+ exit!(0)
end
- sleep 0.5
+ # Wait until p1 creates the lockfile
+ wait_on_lock
p2 = fork do
+ # inform process p1 that we're trying to get the lock
+ sync_send
run_lock.acquire
- write.puts 3
- #puts "[#{Time.new.to_i % 100}] p2 (#{Process.pid}) running with lock"
+ record "p2 has lock"
run_lock.release
+ exit!(0)
end
Process.waitpid2(p1)
Process.waitpid2(p2)
- write.close
- order = read.read
- read.close
+ raise_side_channel_error!
- order.should == "1\n2\n3\n"
+ expected=<<-E
+p1 has lock
+p1 releasing lock
+p2 has lock
+E
+ results.should == expected
end
it "clears the lock if the process dies unexpectedly" do
- read, write = IO.pipe
- run_lock = Chef::RunLock.new(:file_cache_path => file_cache_path, :lockfile => lockfile)
p1 = fork do
run_lock.acquire
- write.puts 1
- #puts "[#{Time.new.to_i % 100}] p1 (#{Process.pid}) running with lock"
- sleep 1
- write.puts 2
- #puts "[#{Time.new.to_i % 100}] p1 (#{Process.pid}) releasing lock"
- run_lock.release
+ record "p1 has lock"
+ sleep 60
+ record "p1 still has lock"
+ exit! 1
end
+ wait_on_lock
+ Process.kill(:KILL, p1)
+ Process.waitpid2(p1)
+
+
p2 = fork do
run_lock.acquire
- write.puts 3
- #puts "[#{Time.new.to_i % 100}] p2 (#{Process.pid}) running with lock"
+ record "p2 has lock"
run_lock.release
+ exit! 0
end
- Process.kill(:KILL, p1)
- Process.waitpid2(p1)
Process.waitpid2(p2)
- write.close
- order = read.read
- read.close
-
- order.should =~ /3\Z/
+ results.should =~ /p2 has lock\Z/
end
end
diff --git a/spec/support/shared/unit/execute_resource.rb b/spec/support/shared/unit/execute_resource.rb
new file mode 100644
index 0000000000..609e77ad63
--- /dev/null
+++ b/spec/support/shared/unit/execute_resource.rb
@@ -0,0 +1,125 @@
+#
+# Author:: Adam Jacob (<adam@opscode.com>)
+# Author:: Tyler Cloke (<tyler@opscode.com>)
+# Copyright:: Copyright (c) 2008 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+shared_examples_for "an execute resource" do
+
+ before(:each) do
+ @resource = execute_resource
+ end
+
+ it "should create a new Chef::Resource::Execute" do
+ @resource.should be_a_kind_of(Chef::Resource)
+ @resource.should be_a_kind_of(Chef::Resource::Execute)
+ end
+
+ it "should set the command to the first argument to new" do
+ @resource.command.should eql(resource_instance_name)
+ end
+
+ it "should accept an array on instantiation, too" do
+ resource = Chef::Resource::Execute.new(%w{something else})
+ resource.should be_a_kind_of(Chef::Resource)
+ resource.should be_a_kind_of(Chef::Resource::Execute)
+ resource.command.should eql(%w{something else})
+ end
+
+ it "should accept a string for the command to run" do
+ @resource.command "something"
+ @resource.command.should eql("something")
+ end
+
+ it "should accept an array for the command to run" do
+ @resource.command %w{something else}
+ @resource.command.should eql(%w{something else})
+ end
+
+ it "should accept a string for the cwd" do
+ @resource.cwd "something"
+ @resource.cwd.should eql("something")
+ end
+
+ it "should accept a hash for the environment" do
+ test_hash = { :one => :two }
+ @resource.environment(test_hash)
+ @resource.environment.should eql(test_hash)
+ end
+
+ it "allows the environment to be specified with #env" do
+ @resource.should respond_to(:env)
+ end
+
+ it "should accept a string for the group" do
+ @resource.group "something"
+ @resource.group.should eql("something")
+ end
+
+ it "should accept an integer for the group" do
+ @resource.group 1
+ @resource.group.should eql(1)
+ end
+
+ it "should accept an array for the execution path" do
+ @resource.path ["woot"]
+ @resource.path.should eql(["woot"])
+ end
+
+ it "should accept an integer for the return code" do
+ @resource.returns 1
+ @resource.returns.should eql(1)
+ end
+
+ it "should accept an integer for the timeout" do
+ @resource.timeout 1
+ @resource.timeout.should eql(1)
+ end
+
+ it "should accept a string for the user" do
+ @resource.user "something"
+ @resource.user.should eql("something")
+ end
+
+ it "should accept an integer for the user" do
+ @resource.user 1
+ @resource.user.should eql(1)
+ end
+
+ it "should accept a string for creates" do
+ @resource.creates "something"
+ @resource.creates.should eql("something")
+ end
+
+ describe "when it has cwd, environment, group, path, return value, and a user" do
+ before do
+ @resource.command("grep")
+ @resource.cwd("/tmp/")
+ @resource.environment({ :one => :two })
+ @resource.group("legos")
+ @resource.path(["/var/local/"])
+ @resource.returns(1)
+ @resource.user("root")
+ end
+
+ it "returns the command as its identity" do
+ @resource.identity.should == "grep"
+ end
+ end
+end
+
diff --git a/spec/support/shared/unit/script_resource.rb b/spec/support/shared/unit/script_resource.rb
new file mode 100644
index 0000000000..0451f4694a
--- /dev/null
+++ b/spec/support/shared/unit/script_resource.rb
@@ -0,0 +1,52 @@
+#
+# Author:: Adam Jacob (<adam@opscode.com>)
+# Author:: Tyler Cloke (<tyler@opscode.com>)
+# Copyright:: Copyright (c) 2008 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+shared_examples_for "a script resource" do
+
+ before(:each) do
+ @resource = script_resource
+ end
+
+ it "should create a new Chef::Resource::Script" do
+ @resource.should be_a_kind_of(Chef::Resource)
+ @resource.should be_a_kind_of(Chef::Resource::Script)
+ end
+
+ it "should have a resource name of :script" do
+ @resource.resource_name.should eql(resource_name)
+ end
+
+ it "should set command to the argument provided to new" do
+ @resource.command.should eql(resource_instance_name)
+ end
+
+ it "should accept a string for the code" do
+ @resource.code "hey jude"
+ @resource.code.should eql("hey jude")
+ end
+
+ it "should accept a string for the flags" do
+ @resource.flags "-f"
+ @resource.flags.should eql("-f")
+ end
+
+end
+
diff --git a/spec/support/shared/unit/windows_script_resource.rb b/spec/support/shared/unit/windows_script_resource.rb
new file mode 100644
index 0000000000..0a0079a287
--- /dev/null
+++ b/spec/support/shared/unit/windows_script_resource.rb
@@ -0,0 +1,48 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+require 'support/shared/unit/execute_resource'
+require 'support/shared/unit/script_resource'
+
+shared_examples_for "a Windows script resource" do
+ before(:each) do
+ node = Chef::Node.new
+
+ node.default["kernel"] = Hash.new
+ node.default["kernel"][:machine] = :x86_64.to_s
+
+ run_context = Chef::RunContext.new(node, nil, nil)
+
+ @resource = resource_instance
+
+ end
+
+ it "should be a kind of Chef::Resource::WindowsScript" do
+ @resource.should be_a_kind_of(Chef::Resource)
+ @resource.should be_a_kind_of(Chef::Resource::WindowsScript)
+ end
+
+ context "script" do
+ let(:script_resource) { resource_instance }
+ it_should_behave_like "a script resource"
+ end
+
+end
+
diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb
index e0b0ab7568..4ec9112c4f 100644
--- a/spec/unit/application_spec.rb
+++ b/spec/unit/application_spec.rb
@@ -183,7 +183,9 @@ describe Chef::Application do
it "should initialise the chef logger" do
Chef::Log.stub!(:level=)
- Chef::Log.should_receive(:init).with(Chef::Config[:log_location]).and_return(true)
+ @monologger = mock("Monologger")
+ MonoLogger.should_receive(:new).with(Chef::Config[:log_location]).and_return(@monologger)
+ Chef::Log.should_receive(:init).with(@monologger)
@app.configure_logging
end
diff --git a/spec/unit/json_compat_spec.rb b/spec/unit/json_compat_spec.rb
index f21493e060..cce31b0c7c 100644
--- a/spec/unit/json_compat_spec.rb
+++ b/spec/unit/json_compat_spec.rb
@@ -36,7 +36,7 @@ describe Chef::JSONCompat do
end
end
- describe "with a file with 1000 or less nested entries" do
+ describe "with a file with 300 or less nested entries" do
before(:all) do
@json = IO.read(File.join(CHEF_SPEC_DATA, 'big_json.json'))
@hash = Chef::JSONCompat.from_json(@json)
@@ -46,23 +46,23 @@ describe Chef::JSONCompat do
it "should create a Hash from the file" do
@hash.should be_kind_of(Hash)
end
- it "should has 'test' as a 1000th nested value" do
- @hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key'].should == 'test'
+ it "should has 'test' as a 300th nested value" do
+ @hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key'].should == 'test'
end
end
end
- describe "with a file with more than 1000 nested entries" do
+ describe "with a file with more than 300 nested entries" do
before(:all) do
@json = IO.read(File.join(CHEF_SPEC_DATA, 'big_json_plus_one.json'))
- @hash = Chef::JSONCompat.from_json(@json, {:max_nesting => 1001})
+ @hash = Chef::JSONCompat.from_json(@json, {:max_nesting => 301})
end
describe "when a big json file is loaded" do
it "should create a Hash from the file" do
@hash.should be_kind_of(Hash)
end
- it "should has 'test' as a 1001th nested value" do
- @hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key'].should == 'test'
+ it "should has 'test' as a 301st nested value" do
+ @hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key'].should == 'test'
end
end
end
diff --git a/spec/unit/knife/configure_spec.rb b/spec/unit/knife/configure_spec.rb
index 692fc5ea15..8d5b51551d 100644
--- a/spec/unit/knife/configure_spec.rb
+++ b/spec/unit/knife/configure_spec.rb
@@ -41,7 +41,7 @@ describe Chef::Knife::Configure do
@knife.config[:initial] = true
Etc.stub!(:getlogin).and_return("a-new-user")
@knife.ask_user_for_config
- @out.string.should match(Regexp.escape("Please enter a clientname for the new client: [a-new-user]"))
+ @out.string.should match(Regexp.escape("Please enter a name for the new user: [a-new-user]"))
@knife.new_client_name.should == Etc.getlogin
end
@@ -50,7 +50,7 @@ describe Chef::Knife::Configure do
@knife.config[:node_name] = 'testnode'
Etc.stub!(:getlogin).and_return("a-new-user")
@knife.ask_user_for_config
- @out.string.should_not match(Regexp.escape("Please enter a clientname for the new client"))
+ @out.string.should_not match(Regexp.escape("Please enter a name for the new user"))
@knife.new_client_name.should == 'testnode'
end
@@ -64,32 +64,32 @@ describe Chef::Knife::Configure do
it "asks the user for the existing admin client's name if -i is specified" do
@knife.config[:initial] = true
@knife.ask_user_for_config
- @out.string.should match(Regexp.escape("Please enter the existing admin clientname: [chef-webui]"))
- @knife.admin_client_name.should == 'chef-webui'
+ @out.string.should match(Regexp.escape("Please enter the existing admin name: [admin]"))
+ @knife.admin_client_name.should == 'admin'
end
it "should not ask the user for the existing admin client's name if -i and --admin-client_name are specified" do
@knife.config[:initial] = true
@knife.config[:admin_client_name] = 'my-webui'
@knife.ask_user_for_config
- @out.string.should_not match(Regexp.escape("Please enter the existing admin clientname:"))
+ @out.string.should_not match(Regexp.escape("Please enter the existing admin:"))
@knife.admin_client_name.should == 'my-webui'
end
it "should not ask the user for the existing admin client's name if -i is not specified" do
@knife.ask_user_for_config
- @out.string.should_not match(Regexp.escape("Please enter the existing admin clientname: [chef-webui]"))
- @knife.admin_client_name.should_not == 'chef-webui'
+ @out.string.should_not match(Regexp.escape("Please enter the existing admin: [admin]"))
+ @knife.admin_client_name.should_not == 'admin'
end
it "asks the user for the location of the existing admin key if -i is specified" do
@knife.config[:initial] = true
@knife.ask_user_for_config
- @out.string.should match(Regexp.escape("Please enter the location of the existing admin client's private key: [/etc/chef/webui.pem]"))
+ @out.string.should match(Regexp.escape("Please enter the location of the existing admin's private key: [/etc/chef/admin.pem]"))
if windows?
- @knife.admin_client_key.should == 'C:/etc/chef/webui.pem'
+ @knife.admin_client_key.should == 'C:/etc/chef/admin.pem'
else
- @knife.admin_client_key.should == '/etc/chef/webui.pem'
+ @knife.admin_client_key.should == '/etc/chef/admin.pem'
end
end
@@ -111,7 +111,7 @@ describe Chef::Knife::Configure do
if windows?
@knife.admin_client_key.should_not == 'C:/etc//chef/webui.pem'
else
- @knife.admin_client_key.should_not == '/etc/chef/webui.pem'
+ @knife.admin_client_key.should_not == '/etc/chef/webui.pem'
end
end
@@ -140,7 +140,7 @@ describe Chef::Knife::Configure do
if windows?
@knife.validation_key.should == 'C:/etc/chef/validation.pem'
else
- @knife.validation_key.should == '/etc/chef/validation.pem'
+ @knife.validation_key.should == '/etc/chef/validation.pem'
end
end
@@ -208,28 +208,25 @@ describe Chef::Knife::Configure do
File.should_receive(:expand_path).with("/home/you/.chef/knife.rb").and_return("/home/you/.chef/knife.rb")
File.should_receive(:expand_path).with("/home/you/.chef/a-new-user.pem").and_return("/home/you/.chef/a-new-user.pem")
File.should_receive(:expand_path).with("/etc/chef/validation.pem").and_return("/etc/chef/validation.pem")
- File.should_receive(:expand_path).with("/etc/chef/webui.pem").and_return("/etc/chef/webui.pem")
+ File.should_receive(:expand_path).with("/etc/chef/admin.pem").and_return("/etc/chef/admin.pem")
Chef::Config[:node_name] = "webmonkey.example.com"
-
- client_command_config = {}
-
- client_command = mock("knife client create command", :config => client_command_config)
- client_command.should_receive(:name_args=).with(["a-new-user"])
- client_command.stub!(:name_args).and_return(["a-new-user"])
- client_command.should_receive(:run)
+ user_command = Chef::Knife::UserCreate.new
+ user_command.should_receive(:run)
Etc.stub!(:getlogin).and_return("a-new-user")
- Chef::Knife::ClientCreate.stub!(:new).and_return(client_command)
+ Chef::Knife::UserCreate.stub!(:new).and_return(user_command)
FileUtils.should_receive(:mkdir_p).with("/home/you/.chef")
::File.should_receive(:open).with("/home/you/.chef/knife.rb", "w")
@knife.config[:initial] = true
+ @knife.config[:user_password] = "blah"
@knife.run
- client_command.name_args.should == Array("a-new-user")
- client_command.config[:admin].should be_true
- client_command.config[:file].should == "/home/you/.chef/a-new-user.pem"
- client_command.config[:yes].should be_true
- client_command.config[:disable_editing].should be_true
+ user_command.name_args.should == Array("a-new-user")
+ user_command.config[:user_password].should == "blah"
+ user_command.config[:admin].should be_true
+ user_command.config[:file].should == "/home/you/.chef/a-new-user.pem"
+ user_command.config[:yes].should be_true
+ user_command.config[:disable_editing].should be_true
end
end
diff --git a/spec/unit/knife/user_create_spec.rb b/spec/unit/knife/user_create_spec.rb
new file mode 100644
index 0000000000..0e36e148ac
--- /dev/null
+++ b/spec/unit/knife/user_create_spec.rb
@@ -0,0 +1,86 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+Chef::Knife::UserCreate.load_deps
+
+describe Chef::Knife::UserCreate do
+ before(:each) do
+ @knife = Chef::Knife::UserCreate.new
+ @knife.name_args = [ 'a_user' ]
+ @knife.config[:user_password] = "foobar"
+ @user = Chef::User.new
+ @user.name "a_user"
+ @user_with_private_key = Chef::User.new
+ @user_with_private_key.name "a_user"
+ @user_with_private_key.private_key 'private_key'
+ @user.stub!(:create).and_return(@user_with_private_key)
+ Chef::User.stub!(:new).and_return(@user)
+ Chef::User.stub!(:from_hash).and_return(@user)
+ @knife.stub!(:edit_data).and_return(@user.to_hash)
+ @stdout = StringIO.new
+ @stderr = StringIO.new
+ @knife.ui.stub!(:stdout).and_return(@stdout)
+ @knife.ui.stub!(:stderr).and_return(@stderr)
+ end
+
+ it "creates a new user" do
+ Chef::User.should_receive(:new).and_return(@user)
+ @user.should_receive(:create)
+ @knife.run
+ @stdout.string.should match /created user.+a_user/i
+ end
+
+ it "sets the password" do
+ @knife.config[:user_password] = "a_password"
+ @user.should_receive(:password).with("a_password")
+ @knife.run
+ end
+
+ it "exits with an error if password is blank" do
+ @knife.config[:user_password] = ''
+ lambda { @knife.run }.should raise_error SystemExit
+ @stderr.string.should match /You must specify a non-blank password/
+ end
+
+ it "sets the user name" do
+ @user.should_receive(:name).with("a_user")
+ @knife.run
+ end
+
+ it "sets the public key if given" do
+ @knife.config[:user_key] = "/a/filename"
+ File.stub(:read).with(File.expand_path("/a/filename")).and_return("a_key")
+ @user.should_receive(:public_key).with("a_key")
+ @knife.run
+ end
+
+ it "allows you to edit the data" do
+ @knife.should_receive(:edit_data).with(@user)
+ @knife.run
+ end
+
+ it "writes the private key to a file when --file is specified" do
+ @knife.config[:file] = "/tmp/a_file"
+ filehandle = mock("filehandle")
+ filehandle.should_receive(:print).with('private_key')
+ File.should_receive(:open).with("/tmp/a_file", "w").and_yield(filehandle)
+ @knife.run
+ end
+end
diff --git a/spec/unit/knife/user_delete_spec.rb b/spec/unit/knife/user_delete_spec.rb
new file mode 100644
index 0000000000..be027e5128
--- /dev/null
+++ b/spec/unit/knife/user_delete_spec.rb
@@ -0,0 +1,39 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+describe Chef::Knife::UserDelete do
+ before(:each) do
+ Chef::Knife::UserDelete.load_deps
+ @knife = Chef::Knife::UserDelete.new
+ @knife.name_args = [ 'my_user' ]
+ end
+
+ it 'deletes the user' do
+ @knife.should_receive(:delete_object).with(Chef::User, 'my_user')
+ @knife.run
+ end
+
+ it 'prints usage and exits when a user name is not provided' do
+ @knife.name_args = []
+ @knife.should_receive(:show_usage)
+ @knife.ui.should_receive(:fatal)
+ lambda { @knife.run }.should raise_error(SystemExit)
+ end
+end
diff --git a/spec/unit/knife/user_edit_spec.rb b/spec/unit/knife/user_edit_spec.rb
new file mode 100644
index 0000000000..d5b380a12f
--- /dev/null
+++ b/spec/unit/knife/user_edit_spec.rb
@@ -0,0 +1,42 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+describe Chef::Knife::UserEdit do
+ before(:each) do
+ Chef::Knife::UserEdit.load_deps
+ @knife = Chef::Knife::UserEdit.new
+ @knife.name_args = [ 'my_user' ]
+ @knife.config[:disable_editing] = true
+ end
+
+ it 'loads and edits the user' do
+ data = { :name => "my_user" }
+ Chef::User.stub(:load).with("my_user").and_return(data)
+ @knife.should_receive(:edit_data).with(data).and_return(data)
+ @knife.run
+ end
+
+ it 'prints usage and exits when a user name is not provided' do
+ @knife.name_args = []
+ @knife.should_receive(:show_usage)
+ @knife.ui.should_receive(:fatal)
+ lambda { @knife.run }.should raise_error(SystemExit)
+ end
+end
diff --git a/spec/unit/knife/user_list_spec.rb b/spec/unit/knife/user_list_spec.rb
new file mode 100644
index 0000000000..7a47f9ddba
--- /dev/null
+++ b/spec/unit/knife/user_list_spec.rb
@@ -0,0 +1,32 @@
+#
+# Author:: Steven Danna
+# Copyright:: Copyright (c) 2012 Opscode, Inc
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+describe Chef::Knife::UserList do
+ before(:each) do
+ Chef::Knife::UserList.load_deps
+ @knife = Chef::Knife::UserList.new
+ end
+
+ it 'lists the users' do
+ Chef::User.should_receive(:list)
+ @knife.should_receive(:format_list_for_display)
+ @knife.run
+ end
+end
diff --git a/spec/unit/knife/user_reregister_spec.rb b/spec/unit/knife/user_reregister_spec.rb
new file mode 100644
index 0000000000..fddab57467
--- /dev/null
+++ b/spec/unit/knife/user_reregister_spec.rb
@@ -0,0 +1,53 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+describe Chef::Knife::UserReregister do
+ before(:each) do
+ Chef::Knife::UserReregister.load_deps
+ @knife = Chef::Knife::UserReregister.new
+ @knife.name_args = [ 'a_user' ]
+ @user_mock = mock('user_mock', :private_key => "private_key")
+ Chef::User.stub!(:load).and_return(@user_mock)
+ @stdout = StringIO.new
+ @knife.ui.stub!(:stdout).and_return(@stdout)
+ end
+
+ it 'prints usage and exits when a user name is not provided' do
+ @knife.name_args = []
+ @knife.should_receive(:show_usage)
+ @knife.ui.should_receive(:fatal)
+ lambda { @knife.run }.should raise_error(SystemExit)
+ end
+
+ it 'reregisters the user and prints the key' do
+ @user_mock.should_receive(:reregister).and_return(@user_mock)
+ @knife.run
+ @stdout.string.should match( /private_key/ )
+ end
+
+ it 'writes the private key to a file when --file is specified' do
+ @user_mock.should_receive(:reregister).and_return(@user_mock)
+ @knife.config[:file] = '/tmp/a_file'
+ filehandle = StringIO.new
+ File.should_receive(:open).with('/tmp/a_file', 'w').and_yield(filehandle)
+ @knife.run
+ filehandle.string.should == "private_key"
+ end
+end
diff --git a/spec/unit/knife/user_show_spec.rb b/spec/unit/knife/user_show_spec.rb
new file mode 100644
index 0000000000..f2bd959d15
--- /dev/null
+++ b/spec/unit/knife/user_show_spec.rb
@@ -0,0 +1,41 @@
+#
+# Author:: Steven Danna (<steve@opscode.com>)
+# Copyright:: Copyright (c) 2012 Opscode, Inc
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+describe Chef::Knife::UserShow do
+ before(:each) do
+ Chef::Knife::UserShow.load_deps
+ @knife = Chef::Knife::UserShow.new
+ @knife.name_args = [ 'my_user' ]
+ @user_mock = mock('user_mock')
+ end
+
+ it 'loads and displays the user' do
+ Chef::User.should_receive(:load).with('my_user').and_return(@user_mock)
+ @knife.should_receive(:format_for_display).with(@user_mock)
+ @knife.run
+ end
+
+ it 'prints usage and exits when a user name is not provided' do
+ @knife.name_args = []
+ @knife.should_receive(:show_usage)
+ @knife.ui.should_receive(:fatal)
+ lambda { @knife.run }.should raise_error(SystemExit)
+ end
+end
diff --git a/spec/unit/mixin/windows_architecture_helper_spec.rb b/spec/unit/mixin/windows_architecture_helper_spec.rb
new file mode 100644
index 0000000000..c7813a5efc
--- /dev/null
+++ b/spec/unit/mixin/windows_architecture_helper_spec.rb
@@ -0,0 +1,83 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+require 'spec_helper'
+require 'chef/mixin/windows_architecture_helper'
+
+
+
+describe Chef::Mixin::WindowsArchitectureHelper do
+ include Chef::Mixin::WindowsArchitectureHelper
+
+ before do
+ @valid_architectures = [ :i386, :x86_64 ]
+ @invalid_architectures = [ "i386", "x86_64", :x64, :x86, :arm ]
+
+ @node_i386 = Chef::Node.new
+ @node_x86_64 = Chef::Node.new
+ end
+
+ it "returns true when valid architectures are passed to valid_windows_architecture?" do
+ @valid_architectures.each do | architecture |
+ valid_windows_architecture?(architecture).should == true
+ end
+ end
+
+ it "returns false when invalid architectures are passed to valid_windows_architecture?" do
+ @invalid_architectures.each do | architecture |
+ valid_windows_architecture?(architecture).should == false
+ end
+ end
+
+ it "does not raise an exception when a valid architecture is passed to assert_valid_windows_architecture!" do
+ @valid_architectures.each do | architecture |
+ assert_valid_windows_architecture!(architecture)
+ end
+ end
+
+ it "raises an error if an invalid architecture is passed to assert_valid_windows_architecture!" do
+ @invalid_architectures.each do | architecture |
+ begin
+ assert_valid_windows_architecture!(architecture).should raise_error Chef::Exceptions::Win32ArchitectureIncorrect
+ rescue Chef::Exceptions::Win32ArchitectureIncorrect
+ end
+ end
+ end
+
+ it "returns true for each supported desired architecture for all nodes with each valid architecture passed to node_supports_windows_architecture" do
+ enumerate_architecture_node_combinations(true)
+ end
+
+ it "returns false for each unsupported desired architecture for all nodes with each valid architecture passed to node_supports_windows_architecture?" do
+ enumerate_architecture_node_combinations(true)
+ end
+
+ def enumerate_architecture_node_combinations(only_valid_combinations)
+ @valid_architectures.each do | node_architecture |
+ new_node = Chef::Node.new
+ new_node.default["kernel"] = Hash.new
+ new_node.default["kernel"][:machine] = node_architecture.to_s
+
+ @valid_architectures.each do | supported_architecture |
+ node_supports_windows_architecture?(new_node, supported_architecture).should == true if only_valid_combinations && (supported_architecture != :x86_64 && node_architecture != :i386 )
+ node_supports_windows_architecture?(new_node, supported_architecture).should == false if ! only_valid_combinations && (supported_architecture == :x86_64 && node_architecture == :i386 )
+ end
+ end
+ end
+end
diff --git a/spec/unit/platform_spec.rb b/spec/unit/platform_spec.rb
index b09a68b528..6897837a42 100644
--- a/spec/unit/platform_spec.rb
+++ b/spec/unit/platform_spec.rb
@@ -35,7 +35,8 @@ describe "Chef::Platform supports" do
:solaris,
:mswin,
:mingw32,
- :windows
+ :windows,
+ :gcel
].each do |platform|
it "#{platform}" do
Chef::Platform.platforms.should have_key(platform)
diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb
index b3b7a030db..d7941af76d 100644
--- a/spec/unit/provider/package/rubygems_spec.rb
+++ b/spec/unit/provider/package/rubygems_spec.rb
@@ -95,6 +95,18 @@ describe Chef::Provider::Package::Rubygems::CurrentGemEnvironment do
@gem_env.candidate_version_from_remote(Gem::Dependency.new('rspec', '>= 0')).should == Gem::Version.new('1.3.0')
end
+ it "finds a matching gem candidate version on rubygems 2.0.0+" do
+ dep = Gem::Dependency.new('rspec', '>= 0')
+ dep_installer = Gem::DependencyInstaller.new
+ @gem_env.stub!(:dependency_installer).and_return(dep_installer)
+ best_gem = mock("best gem match", :spec => gemspec("rspec", Gem::Version.new("1.3.0")), :source => "https://rubygems.org")
+ available_set = mock("Gem::AvailableSet test double")
+ available_set.should_receive(:pick_best!)
+ available_set.should_receive(:set).and_return([best_gem])
+ dep_installer.should_receive(:find_gems_with_sources).with(dep).and_return(available_set)
+ @gem_env.candidate_version_from_remote(Gem::Dependency.new('rspec', '>= 0')).should == Gem::Version.new('1.3.0')
+ end
+
it "gives the candidate version as nil if none is found" do
dep = Gem::Dependency.new('rspec', '>= 0')
latest = []
diff --git a/spec/unit/provider/powershell_spec.rb b/spec/unit/provider/powershell_spec.rb
new file mode 100644
index 0000000000..038de47742
--- /dev/null
+++ b/spec/unit/provider/powershell_spec.rb
@@ -0,0 +1,38 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+describe Chef::Provider::Powershell, "action_run" do
+
+ before(:each) do
+ @node = Chef::Node.new
+
+ @node.default["kernel"] = Hash.new
+ @node.default["kernel"][:machine] = :x86_64.to_s
+
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+ @new_resource = Chef::Resource::Powershell.new('run some powershell code', @run_context)
+
+ @provider = Chef::Provider::Powershell.new(@new_resource, @run_context)
+ end
+
+ it "should set the -command flag as the last flag" do
+ @provider.flags.split(' ').pop.should == "-Command"
+ end
+
+end
diff --git a/spec/unit/provider/remote_file/ftp_spec.rb b/spec/unit/provider/remote_file/ftp_spec.rb
index 246301c0e1..bf27e1aee0 100644
--- a/spec/unit/provider/remote_file/ftp_spec.rb
+++ b/spec/unit/provider/remote_file/ftp_spec.rb
@@ -110,7 +110,7 @@ describe Chef::Provider::RemoteFile::FTP do
describe "when it finishes downloading" do
it "should return a tempfile" do
- ftpfile, mtime, target_matched = Chef::Provider::RemoteFile::FTP.fetch(@uri, nil, false, nil)
+ ftpfile, mtime = Chef::Provider::RemoteFile::FTP.fetch(@uri, nil, false, nil)
ftpfile.should equal @tempfile
ftpfile.close!
end
diff --git a/spec/unit/resource/batch_spec.rb b/spec/unit/resource/batch_spec.rb
new file mode 100644
index 0000000000..91b840908e
--- /dev/null
+++ b/spec/unit/resource/batch_spec.rb
@@ -0,0 +1,48 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+describe Chef::Resource::Batch do
+
+ before(:each) do
+ node = Chef::Node.new
+
+ node.default["kernel"] = Hash.new
+ node.default["kernel"][:machine] = :x86_64.to_s
+
+ run_context = Chef::RunContext.new(node, nil, nil)
+
+ @resource = Chef::Resource::Batch.new("batch_unit_test", run_context)
+
+ end
+
+ it "should create a new Chef::Resource::Batch" do
+ @resource.should be_a_kind_of(Chef::Resource::Batch)
+ end
+
+ context "windows script" do
+ let(:resource_instance) { @resource }
+ let(:resource_instance_name ) { @resource.command }
+ let(:resource_name) { :batch }
+ let(:interpreter_file_name) { 'cmd.exe' }
+
+ it_should_behave_like "a Windows script resource"
+ end
+
+end
diff --git a/spec/unit/resource/execute_spec.rb b/spec/unit/resource/execute_spec.rb
index 0dcdab7409..8c8dcfb6ca 100644
--- a/spec/unit/resource/execute_spec.rb
+++ b/spec/unit/resource/execute_spec.rb
@@ -20,105 +20,7 @@
require 'spec_helper'
describe Chef::Resource::Execute do
-
- before(:each) do
- @resource = Chef::Resource::Execute.new("some command")
- end
-
- it "should create a new Chef::Resource::Execute" do
- @resource.should be_a_kind_of(Chef::Resource)
- @resource.should be_a_kind_of(Chef::Resource::Execute)
- end
-
- it "should set the command to the first argument to new" do
- @resource.command.should eql("some command")
- end
-
- it "should accept an array on instantiation, too" do
- resource = Chef::Resource::Execute.new(%w{something else})
- resource.should be_a_kind_of(Chef::Resource)
- resource.should be_a_kind_of(Chef::Resource::Execute)
- resource.command.should eql(%w{something else})
- end
-
- it "should accept a string for the command to run" do
- @resource.command "something"
- @resource.command.should eql("something")
- end
-
- it "should accept an array for the command to run" do
- @resource.command %w{something else}
- @resource.command.should eql(%w{something else})
- end
-
- it "should accept a string for the cwd" do
- @resource.cwd "something"
- @resource.cwd.should eql("something")
- end
-
- it "should accept a hash for the environment" do
- test_hash = { :one => :two }
- @resource.environment(test_hash)
- @resource.environment.should eql(test_hash)
- end
-
- it "allows the environment to be specified with #env" do
- @resource.should respond_to(:env)
- end
-
- it "should accept a string for the group" do
- @resource.group "something"
- @resource.group.should eql("something")
- end
-
- it "should accept an integer for the group" do
- @resource.group 1
- @resource.group.should eql(1)
- end
-
- it "should accept an array for the execution path" do
- @resource.path ["woot"]
- @resource.path.should eql(["woot"])
- end
-
- it "should accept an integer for the return code" do
- @resource.returns 1
- @resource.returns.should eql(1)
- end
-
- it "should accept an integer for the timeout" do
- @resource.timeout 1
- @resource.timeout.should eql(1)
- end
-
- it "should accept a string for the user" do
- @resource.user "something"
- @resource.user.should eql("something")
- end
-
- it "should accept an integer for the user" do
- @resource.user 1
- @resource.user.should eql(1)
- end
-
- it "should accept a string for creates" do
- @resource.creates "something"
- @resource.creates.should eql("something")
- end
-
- describe "when it has cwd, environment, group, path, return value, and a user" do
- before do
- @resource.command("grep")
- @resource.cwd("/tmp/")
- @resource.environment({ :one => :two })
- @resource.group("legos")
- @resource.path(["/var/local/"])
- @resource.returns(1)
- @resource.user("root")
- end
-
- it "returns the command as its identity" do
- @resource.identity.should == "grep"
- end
- end
+ let(:resource_instance_name) { "some command" }
+ let(:execute_resource) { Chef::Resource::Execute.new(resource_instance_name) }
+ it_behaves_like "an execute resource"
end
diff --git a/spec/unit/resource/powershell_spec.rb b/spec/unit/resource/powershell_spec.rb
new file mode 100644
index 0000000000..22d5b5371b
--- /dev/null
+++ b/spec/unit/resource/powershell_spec.rb
@@ -0,0 +1,48 @@
+#
+# Author:: Adam Edwards (<adamed@opscode.com>)
+# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+describe Chef::Resource::Powershell do
+
+ before(:each) do
+ node = Chef::Node.new
+
+ node.default["kernel"] = Hash.new
+ node.default["kernel"][:machine] = :x86_64.to_s
+
+ run_context = Chef::RunContext.new(node, nil, nil)
+
+ @resource = Chef::Resource::Powershell.new("powershell_unit_test", run_context)
+
+ end
+
+ it "should create a new Chef::Resource::Powershell" do
+ @resource.should be_a_kind_of(Chef::Resource::Powershell)
+ end
+
+ context "windowsscript" do
+ let(:resource_instance) { @resource }
+ let(:resource_instance_name ) { @resource.command }
+ let(:resource_name) { :powershell }
+ let(:interpreter_file_name) { 'powershell.exe' }
+
+ it_should_behave_like "a Windows script resource"
+ end
+
+end
diff --git a/spec/unit/resource/script_spec.rb b/spec/unit/resource/script_spec.rb
index 569602008b..53735daf01 100644
--- a/spec/unit/resource/script_spec.rb
+++ b/spec/unit/resource/script_spec.rb
@@ -20,50 +20,27 @@
require 'spec_helper'
describe Chef::Resource::Script do
+ let(:resource_instance_name) { "fakey_fakerton" }
+ let(:script_resource) { Chef::Resource::Script.new(resource_instance_name) }
+ let(:resource_name) { :script }
- before(:each) do
- @resource = Chef::Resource::Script.new("fakey_fakerton")
- end
-
- it "should create a new Chef::Resource::Script" do
- @resource.should be_a_kind_of(Chef::Resource)
- @resource.should be_a_kind_of(Chef::Resource::Script)
- end
-
- it "should have a resource name of :script" do
- @resource.resource_name.should eql(:script)
- end
-
- it "should set command to the argument provided to new" do
- @resource.command.should eql("fakey_fakerton")
- end
-
- it "should accept a string for the code" do
- @resource.code "hey jude"
- @resource.code.should eql("hey jude")
- end
-
it "should accept a string for the interpreter" do
- @resource.interpreter "naaaaNaNaNaaNaaNaaNaa"
- @resource.interpreter.should eql("naaaaNaNaNaaNaaNaaNaa")
- end
-
- it "should accept a string for the flags" do
- @resource.flags "-f"
- @resource.flags.should eql("-f")
+ script_resource.interpreter "naaaaNaNaNaaNaaNaaNaa"
+ script_resource.interpreter.should eql("naaaaNaNaNaaNaaNaaNaa")
end
describe "when it has interpreter and flags" do
before do
- @resource.command("grep")
- @resource.interpreter("gcc")
- @resource.flags("-al")
+ script_resource.command("grep")
+ script_resource.interpreter("gcc")
+ script_resource.flags("-al")
end
- it "returns the command as its identity" do
- @resource.identity.should == "grep"
+ it "returns the command as its identity" do
+ script_resource.identity.should == "grep"
end
end
-
-
+
+ it_behaves_like "a script resource"
end
+
diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb
new file mode 100644
index 0000000000..9121babeed
--- /dev/null
+++ b/spec/unit/user_spec.rb
@@ -0,0 +1,255 @@
+#
+# Author:: Steven Danna (steve@opscode.com)
+# Copyright:: Copyright (c) 2012 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+require 'chef/user'
+require 'tempfile'
+
+describe Chef::User do
+ before(:each) do
+ @user = Chef::User.new
+ end
+
+ describe "initialize" do
+ it "should be a Chef::User" do
+ @user.should be_a_kind_of(Chef::User)
+ end
+ end
+
+ describe "name" do
+ it "should let you set the name to a string" do
+ @user.name("ops_master").should == "ops_master"
+ end
+
+ it "should return the current name" do
+ @user.name "ops_master"
+ @user.name.should == "ops_master"
+ end
+
+ # It is not feasible to check all invalid characters. Here are a few
+ # that we probably care about.
+ it "should not accept invalid characters" do
+ # capital letters
+ lambda { @user.name "Bar" }.should raise_error(ArgumentError)
+ # slashes
+ lambda { @user.name "foo/bar" }.should raise_error(ArgumentError)
+ # ?
+ lambda { @user.name "foo?" }.should raise_error(ArgumentError)
+ # &
+ lambda { @user.name "foo&" }.should raise_error(ArgumentError)
+ end
+
+
+ it "should not accept spaces" do
+ lambda { @user.name "ops master" }.should raise_error(ArgumentError)
+ end
+
+ it "should throw an ArgumentError if you feed it anything but a string" do
+ lambda { @user.name Hash.new }.should raise_error(ArgumentError)
+ end
+ end
+
+ describe "admin" do
+ it "should let you set the admin bit" do
+ @user.admin(true).should == true
+ end
+
+ it "should return the current admin value" do
+ @user.admin true
+ @user.admin.should == true
+ end
+
+ it "should default to false" do
+ @user.admin.should == false
+ end
+
+ it "should throw an ArgumentError if you feed it anything but true or false" do
+ lambda { @user.name Hash.new }.should raise_error(ArgumentError)
+ end
+ end
+
+ describe "public_key" do
+ it "should let you set the public key" do
+ @user.public_key("super public").should == "super public"
+ end
+
+ it "should return the current public key" do
+ @user.public_key("super public")
+ @user.public_key.should == "super public"
+ end
+
+ it "should throw an ArgumentError if you feed it something lame" do
+ lambda { @user.public_key Hash.new }.should raise_error(ArgumentError)
+ end
+ end
+
+ describe "private_key" do
+ it "should let you set the private key" do
+ @user.private_key("super private").should == "super private"
+ end
+
+ it "should return the private key" do
+ @user.private_key("super private")
+ @user.private_key.should == "super private"
+ end
+
+ it "should throw an ArgumentError if you feed it something lame" do
+ lambda { @user.private_key Hash.new }.should raise_error(ArgumentError)
+ end
+ end
+
+ describe "when serializing to JSON" do
+ before(:each) do
+ @user.name("black")
+ @user.public_key("crowes")
+ @json = @user.to_json
+ end
+
+ it "serializes as a JSON object" do
+ @json.should match(/^\{.+\}$/)
+ end
+
+ it "includes the name value" do
+ @json.should include(%q{"name":"black"})
+ end
+
+ it "includes the public key value" do
+ @json.should include(%{"public_key":"crowes"})
+ end
+
+ it "includes the 'admin' flag" do
+ @json.should include(%q{"admin":false})
+ end
+
+ it "includes the private key when present" do
+ @user.private_key("monkeypants")
+ @user.to_json.should include(%q{"private_key":"monkeypants"})
+ end
+
+ it "does not include the private key if not present" do
+ @json.should_not include("private_key")
+ end
+
+ it "includes the password if present" do
+ @user.password "password"
+ @user.to_json.should include(%q{"password":"password"})
+ end
+
+ it "does not include the password if not present" do
+ @json.should_not include("password")
+ end
+ end
+
+ describe "when deserializing from JSON" do
+ before(:each) do
+ user = { "name" => "mr_spinks",
+ "public_key" => "turtles",
+ "private_key" => "pandas",
+ "password" => "password",
+ "admin" => true }
+ @user = Chef::User.from_json(user.to_json)
+ end
+
+ it "should deserialize to a Chef::User object" do
+ @user.should be_a_kind_of(Chef::User)
+ end
+
+ it "preserves the name" do
+ @user.name.should == "mr_spinks"
+ end
+
+ it "preserves the public key" do
+ @user.public_key.should == "turtles"
+ end
+
+ it "preserves the admin status" do
+ @user.admin.should be_true
+ end
+
+ it "includes the private key if present" do
+ @user.private_key.should == "pandas"
+ end
+
+ it "includes the password if present" do
+ @user.password.should == "password"
+ end
+
+ end
+
+ describe "API Interactions" do
+ before (:each) do
+ @user = Chef::User.new
+ @user.name "foobar"
+ @http_client = mock("Chef::REST mock")
+ Chef::REST.stub!(:new).and_return(@http_client)
+ end
+
+ describe "list" do
+ before(:each) do
+ Chef::Config[:chef_server_url] = "http://www.example.com"
+ @osc_response = { "admin" => "http://www.example.com/users/admin"}
+ @ohc_response = [ { "user" => { "username" => "admin" }} ]
+ end
+
+ it "lists all clients on an OSC server" do
+ @http_client.stub!(:get_rest).with("users").and_return(@osc_response)
+ Chef::User.list.should == @osc_response
+ end
+
+ it "lists all clients on an OHC/OPC server" do
+ @http_client.stub!(:get_rest).with("users").and_return(@ohc_response)
+ # We expect that Chef::User.list will give a consistent response
+ # so OHC API responses should be transformed to OSC-style output.
+ Chef::User.list.should == @osc_response
+ end
+ end
+
+ describe "create" do
+ it "creates a new user via the API" do
+ @user.password "password"
+ @http_client.should_receive(:post_rest).with("users", {:name => "foobar", :admin => false, :password => "password"}).and_return({})
+ @user.create
+ end
+ end
+
+ describe "read" do
+ it "loads a named user from the API" do
+ @http_client.should_receive(:get_rest).with("users/foobar").and_return({"name" => "foobar", "admin" => true, "public_key" => "pubkey"})
+ user = Chef::User.load("foobar")
+ user.name.should == "foobar"
+ user.admin.should == true
+ user.public_key.should == "pubkey"
+ end
+ end
+
+ describe "update" do
+ it "updates an existing user on via the API" do
+ @http_client.should_receive(:put_rest).with("users/foobar", {:name => "foobar", :admin => false}).and_return({})
+ @user.update
+ end
+ end
+
+ describe "destroy" do
+ it "deletes the specified user via the API" do
+ @http_client.should_receive(:delete_rest).with("users/foobar")
+ @user.destroy
+ end
+ end
+ end
+end