diff options
626 files changed, 17562 insertions, 6460 deletions
diff --git a/.travis.yml b/.travis.yml index bda8c79211..6468f54d57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,12 @@ rvm: - 1.8.7 -# - 1.9.2 - 1.9.3 - 2.0.0 -script: bundle exec rake spec +branches: + only: + - master + - 10-stable + - 11-stable +script: bundle exec rspec --color --format progress diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4744593eeb..523fadc45f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ You can find the answers to additional frequently asked questions [on the wiki]( * Create an account on our [bug tracker](http://tickets.opscode.com) * Sign our contributor agreement (CLA) [ -online](https://secure.echosign.com/public/hostedForm?formid=PJIF5694K6L) +online](https://secure.echosign.com/public/hostedForm?formid=PJIF5694K6L) (keep reading if you're contributing on behalf of your employer) * Create a ticket for your change on the [bug tracker](http://tickets.opscode.com) * Link to your patch as a rebased git branch or pull request from the ticket @@ -19,7 +19,7 @@ We regularly review contributions and will get back to you if we have any sugges ## The Apache License and the CLA/CCLA Licensing is very important to open source projects, it helps ensure the software continues to be available under the terms that the author desired. -Chef uses the Apache 2.0 license to strike a balance between open contribution and allowing you to use the software however you would like to. +Chef uses the Apache 2.0 license to strike a balance between open contribution and allowing you to use the software however you would like to. The license tells you what rights you have that are provided by the copyright holder. It is important that the contributor fully understands what rights they are licensing and agrees to them. Sometimes the copyright holder isn't the contributor, most often when the contributor is doing work for a company. @@ -43,26 +43,26 @@ such as: * Discussion regarding the design and merits of features * Error output to aid in finding similar bugs -Each ticket should aim to fix one bug or add one feature. +Each ticket should aim to fix one bug or add one feature. ## Using git -You can get a quick copy of the chef repository by running `git clone git://github.com/opscode/chef.git`. +You can get a quick copy of the chef repository by running `git clone git://github.com/opscode/chef.git`. -For collaboration purposes, it is best if you create a Github account and fork the repository to your own account. +For collaboration purposes, it is best if you create a Github account and fork the repository to your own account. Once you do this you will be able to push your changes to your Github repository for others to see and use. ### Branches and Commits You should submit your patch as a git branch named after the ticket, such as CHEF-1337. -This is called a _topic branch_ and allows users to associate a branch of code with the ticket. +This is called a _topic branch_ and allows users to associate a branch of code with the ticket. It is a best practice to have your commit message have a _summary line_ that includes the ticket number, followed by an empty line and then a brief description of the commit. This also helps other contributors understand the purpose of changes to the code. CHEF-3435: Create deploy dirs before calling scm_provider - + The SCM providers have an assertation that requires the deploy directory to exist. The deploy provider will create missing directories, we don't converge the actions before we call run_action against the SCM provider, so it is not @@ -76,7 +76,7 @@ helpful to be clear about your use case and change so they can understand it eve All of Opscode's open source projects are available on [Github](http://www.github.com/opscode). -We don't require you to use Github, and we will even take patch diffs attached to tickets on the tracker. +We don't require you to use Github, and we will even take patch diffs attached to tickets on the tracker. However Github has a lot of convenient features, such as being able to see a diff of changes between a pull request and the main repository quickly without downloading the branch. @@ -92,14 +92,14 @@ Additional help with git is available on the [Working with Git](http://wiki.opsc There are rspec unit tests in the 'spec' directory. If you don't have rspec already installed, you can use the 'bundler' gem to help you get the necessary prerequisites by running `sudo gem install bundler` and then `bundle install` from -the chef respository. You can run the chef client spec tests by running `rspec spec/*` or `rake spec` from the chef +the chef respository. You can run the chef client spec tests by running `rspec spec/*` or `rake spec` from the chef directory of the chef repository. -These tests should pass successfully on Ruby 1.8 and 1.9 on all of the platforms that Chef runs on. It is good to run the tests +These tests should pass successfully on Ruby 1.8 and 1.9 on all of the platforms that Chef runs on. It is good to run the tests once on your system before you get started to ensure they all pass so you have a valid baseline. After you write your patch, run the tests again to see if they all pass. -If any don't pass, investigate them before submitting your patch. +If any don't pass, investigate them before submitting your patch. These tests don't modify your system, and sometimes tests fail because a command that would be run has changed because of your patch. This should be a simple fix. Other times the failure can show you that an important feature no longer works because of @@ -136,7 +136,7 @@ The versioning for the Chef project is X.Y.Z. Major releases and have historically been once a year. Minor releases for Chef average every two months and patch releases come as needed. -There are usually beta releases and release candidates (RC) of major and minor releases announced on +There are usually beta releases and release candidates (RC) of major and minor releases announced on the [chef-dev mailing list](http://lists.opscode.com/sympa/info/chef-dev). Once an RC is released, we wait at least three days to allow for testing for regressions before the final release. If a blocking regression is found then another RC is made containing the fix and the timer is reset. @@ -1,6 +1,5 @@ source "https://rubygems.org" - -gemspec +gemspec :name => "chef" gem "activesupport", "< 4.0.0", :group => :compat_testing, :platform => "ruby" @@ -18,24 +17,6 @@ group(:development, :test) do # gem 'pry' end -platforms :mswin, :mingw do - gem "systemu", "2.2.0" # CHEF-3718 - gem "ffi", "1.0.9" - gem "rdp-ruby-wmi", "0.3.1" - gem "windows-api", "0.4.0" - gem "windows-pr", "1.2.1" - gem "win32-api", "1.4.8" - gem "win32-dir", "0.3.7" - gem "win32-event", "0.5.2" - gem "win32-mutex", "0.3.1" - gem "win32-process", "0.6.5" - gem "win32-service", "0.7.2" -end - -platforms :mingw_18 do - gem "win32-open3", "0.3.2" -end - # If you want to load debugging tools into the bundle exec sandbox, # add these additional dependencies into chef/Gemfile.local eval(IO.read(__FILE__ + '.local'), binding) if File.exists?(__FILE__ + '.local') @@ -17,3 +17,5 @@ Contributors and Copyright holders: Chef incorporates code modified from Open4 (http://www.codeforpeople.com/lib/ruby/open4/), which was written by Ara T. Howard. Chef incorporates code modified from deep_merge (http://trac.misuse.org/science/wiki/DeepMerge), which is Copyright (c) 2008 Steve Midgley + +Chef incorporates code modified from diff-lcs (http://diff-lcs.rubyforge.org/), which is Copyright (c) 2004–2013 Austin Ziegler @@ -26,13 +26,12 @@ require './tasks/rspec.rb' GEM_NAME = "chef" -spec = eval(File.read("chef.gemspec")) - # This has to be here or else the docs get generated *after* the gem is created task :gem => 'docs:all' -Gem::PackageTask.new(spec) do |pkg| - pkg.gem_spec = spec +Dir[File.expand_path("../*gemspec", __FILE__)].reverse.each do |gemspec_path| + gemspec = eval(IO.read(gemspec_path)) + Gem::PackageTask.new(gemspec).define end begin @@ -60,6 +59,15 @@ task :uninstall do sh %{gem uninstall #{GEM_NAME} -x -v #{Chef::VERSION} } end +desc "Build it, tag it and ship it" +task :ship => :gem do + sh("git tag #{Chef::VERSION}") + sh("git push opscode --tags") + Dir[File.expand_path("../pkg/*.gem", __FILE__)].reverse.each do |built_gem| + sh("gem push #{built_gem}") + end +end + RONN_OPTS = "--manual='Chef Manual' --organization='Chef #{Chef::VERSION}' --date='#{Time.new.strftime('%Y-%m-%d')}'" namespace :docs do @@ -85,7 +93,15 @@ namespace :docs do end end - if system('which ronn > /dev/null') + # we can have ronn in the path, but not in the bundle, require both + ronn_in_bundle = true + begin + require 'ronn' + rescue LoadError + ronn_in_bundle = false + end + + if ronn_in_bundle && system('which ronn > /dev/null') ['distro/common/markdown/man1/*.mkd', 'distro/common/markdown/man8/*.mkd'].each do |dir| Dir[dir].each do |mkd| basename = File.basename(mkd, '.mkd') diff --git a/bin/chef-apply b/bin/chef-apply index 54ce230582..c617129aa3 100755 --- a/bin/chef-apply +++ b/bin/chef-apply @@ -9,9 +9,9 @@ # 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. diff --git a/bin/chef-client b/bin/chef-client index bfd5544319..5b2b058f91 100755 --- a/bin/chef-client +++ b/bin/chef-client @@ -9,9 +9,9 @@ # 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. diff --git a/bin/chef-service-manager b/bin/chef-service-manager index 781fd116de..3d48f203cb 100755 --- a/bin/chef-service-manager +++ b/bin/chef-service-manager @@ -9,9 +9,9 @@ # 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. diff --git a/bin/chef-shell b/bin/chef-shell index 90598d665d..f334635742 100755 --- a/bin/chef-shell +++ b/bin/chef-shell @@ -31,4 +31,7 @@ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))) require "chef/shell" +# On Windows only, enable irb --noreadline because of input problems -- +# See CHEF-3284. +IRB.conf[:USE_READLINE] = false if Chef::Platform::windows? Shell.start diff --git a/bin/chef-solo b/bin/chef-solo index 69891acb73..958ab21a41 100755 --- a/bin/chef-solo +++ b/bin/chef-solo @@ -9,9 +9,9 @@ # 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. @@ -1,6 +1,6 @@ #!/usr/bin/env ruby # -# ./knife - Chef CLI interface +# ./knife - Chef CLI interface # # Author:: Adam Jacob (<adam@opscode.com>) # Copyright:: Copyright (c) 2009 Opscode, Inc. @@ -9,9 +9,9 @@ # 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. diff --git a/chef-x86-mingw32.gemspec b/chef-x86-mingw32.gemspec new file mode 100644 index 0000000000..8e59f8257f --- /dev/null +++ b/chef-x86-mingw32.gemspec @@ -0,0 +1,20 @@ +# x86-mingw32 Gemspec # +gemspec = eval(IO.read(File.expand_path("../chef.gemspec", __FILE__))) + +gemspec.platform = "x86-mingw32" + +gemspec.add_dependency "mixlib-shellout", "1.2.0" +gemspec.add_dependency "systemu", "2.5.2" # CHEF-3718 +gemspec.add_dependency "ffi", "1.3.1" +gemspec.add_dependency "rdp-ruby-wmi", "0.3.1" +gemspec.add_dependency "windows-api", "0.4.2" +gemspec.add_dependency "windows-pr", "1.2.2" +gemspec.add_dependency "win32-api", "1.4.8" +gemspec.add_dependency "win32-dir", "0.4.5" +gemspec.add_dependency "win32-event", "0.6.1" +gemspec.add_dependency "win32-mutex", "0.4.1" +gemspec.add_dependency "win32-process", "0.7.3" +gemspec.add_dependency "win32-service", "0.8.2" +gemspec.add_dependency "win32-mmap", "0.4.0" + +gemspec diff --git a/chef.gemspec b/chef.gemspec index caf2e4cffc..2837dabe35 100644 --- a/chef.gemspec +++ b/chef.gemspec @@ -12,12 +12,12 @@ Gem::Specification.new do |s| s.email = "adam@opscode.com" s.homepage = "http://wiki.opscode.com/display/chef" - s.add_dependency "mixlib-config", ">= 1.1.2" - s.add_dependency "mixlib-cli", "~> 1.3.0" - s.add_dependency "mixlib-log", ">= 1.3.0" - s.add_dependency "mixlib-authentication", ">= 1.3.0" - s.add_dependency "mixlib-shellout" - s.add_dependency "ohai", ">= 0.6.0" + s.add_dependency "mixlib-config", "~> 2.0" + s.add_dependency "mixlib-cli", "~> 1.3" + s.add_dependency "mixlib-log", "~> 1.3" + s.add_dependency "mixlib-authentication", "~> 1.3" + s.add_dependency "mixlib-shellout", "~> 1.2" + s.add_dependency "ohai", "~> 6.0" s.add_dependency "rest-client", ">= 1.0.4", "< 1.7.0" @@ -27,13 +27,15 @@ Gem::Specification.new do |s| 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" + s.add_dependency "highline", "~> 1.6", ">= 1.6.9" + s.add_dependency "erubis", "~> 2.7" + s.add_dependency "diff-lcs", "~> 1.2", ">= 1.2.4" + s.add_dependency "chef-zero", "~> 1.6", ">= 1.6.2" + s.add_dependency "puma", "~> 1.6" + %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.add_development_dependency "chef-zero", "~> 1.4" - s.add_development_dependency "puma", "~> 1.6" + %w(rspec-core rspec-expectations rspec-mocks).each { |gem| s.add_development_dependency gem, "~> 2.13.0" } s.bindir = "bin" # chef-service-manager is a windows only executable. diff --git a/ci/jenkins_run_tests.sh b/ci/jenkins_run_tests.sh index 9330d7cd07..5bf7def062 100755 --- a/ci/jenkins_run_tests.sh +++ b/ci/jenkins_run_tests.sh @@ -1,6 +1,6 @@ #!/bin/bash -export PATH=/usr/local/bin:$PATH +export PATH=$PATH:/usr/local/bin ruby -v; # remove the Gemfile.lock and try again if bundler fails. diff --git a/distro/arch/etc/rc.d/chef-client b/distro/arch/etc/rc.d/chef-client index 36f00bad6a..6e2feb2e52 100644 --- a/distro/arch/etc/rc.d/chef-client +++ b/distro/arch/etc/rc.d/chef-client @@ -5,9 +5,9 @@ # 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. diff --git a/distro/arch/etc/rc.d/chef-server b/distro/arch/etc/rc.d/chef-server index 59f926c2c9..1ffbf8dce5 100644 --- a/distro/arch/etc/rc.d/chef-server +++ b/distro/arch/etc/rc.d/chef-server @@ -5,9 +5,9 @@ # 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. diff --git a/distro/arch/etc/rc.d/chef-server-webui b/distro/arch/etc/rc.d/chef-server-webui index 79a9b77c1c..bec185151f 100644 --- a/distro/arch/etc/rc.d/chef-server-webui +++ b/distro/arch/etc/rc.d/chef-server-webui @@ -5,9 +5,9 @@ # 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. diff --git a/distro/arch/etc/rc.d/chef-solr b/distro/arch/etc/rc.d/chef-solr index a3682a495a..10bd15ea08 100644 --- a/distro/arch/etc/rc.d/chef-solr +++ b/distro/arch/etc/rc.d/chef-solr @@ -5,9 +5,9 @@ # 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. diff --git a/distro/common/html/chef-client.8.html b/distro/common/html/chef-client.8.html index 17a80768d9..5e7eee7861 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="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode +<p>Chef was written by Adam Jacob <a href="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode (http://www.opscode.com), with contributions from the community. This -manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a> with +manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +135,8 @@ found in /usr/share/common-licenses/Apache-2.0.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 b025cdb89d..b4117034d3 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="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode +<p>Chef was written by Adam Jacob <a href="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode (http://www.opscode.com), with contributions from the community. This -manual page was created by Nuo Yan <a href="mailto:nuo@opscode.com" data-bare-link="true">nuo@opscode.com</a>. Permission is +manual page was created by Nuo Yan <a href="mailto:nuo@opscode.com" data-bare-link="true">nuo@opscode.com</a>. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p> @@ -154,8 +154,8 @@ found in /usr/share/common-licenses/Apache-2.0.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 ddedce711b..2d93233feb 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="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode +<p>Chef was written by Adam Jacob <a href="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode (http://www.opscode.com), with contributions from the community. This -manual page was created by Nuo Yan <a href="mailto:nuo@opscode.com" data-bare-link="true">nuo@opscode.com</a>. Permission is +manual page was created by Nuo Yan <a href="mailto:nuo@opscode.com" data-bare-link="true">nuo@opscode.com</a>. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p> @@ -136,8 +136,8 @@ found in /usr/share/common-licenses/Apache-2.0.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 2da387b735..f498e36302 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="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode +<p>Chef was written by Adam Jacob <a href="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode (http://www.opscode.com), with contributions from the community. This -manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a> with +manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +175,8 @@ found in /usr/share/common-licenses/Apache-2.0.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 a183114aaf..ed59f0f62c 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="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode +<p>Chef was written by Adam Jacob <a href="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode (http://www.opscode.com), with contributions from the community. This -manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a> with +manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +172,8 @@ found in /usr/share/common-licenses/Apache-2.0.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 56f548d305..a77e2b9060 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</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="mailto:dan@opscode.com" data-bare-link="true">dan@opscode.com</a>. +<p> This manual page was written by Daniel DeLeo <a href="mailto:dan@opscode.com" data-bare-link="true">dan@opscode.com</a>. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p> @@ -276,8 +276,8 @@ libraries.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 a97c84a0fc..3356c32bed 100644 --- a/distro/common/html/chef-solo.8.html +++ b/distro/common/html/chef-solo.8.html @@ -164,9 +164,9 @@ http://wiki.opscode.com/display/chef/Home.</p> <h2 id="AUTHOR">AUTHOR</h2> -<p>Chef was written by Adam Jacob <a href="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode +<p>Chef was written by Adam Jacob <a href="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode (http://www.opscode.com), with contributions from the community. This -manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a> with +manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a> with help2man. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License.</p> @@ -175,8 +175,8 @@ found in /usr/share/common-licenses/Apache-2.0.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 d930b8011d..3ef7108ad0 100644 --- a/distro/common/html/chef-solr.8.html +++ b/distro/common/html/chef-solr.8.html @@ -3,7 +3,7 @@ <head> <meta http-equiv='content-type' value='text/html;charset=utf8'> <meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'> - <title>chef-solr(8) - Runs as Chef's search server</title> + <title>chef-solr(8) - Runs as Chef's search server</title> <style type='text/css' media='all'> /* style: man */ body#manpage {margin:0} @@ -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="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode +<p>Chef was written by Adam Jacob <a href="mailto:adam@ospcode.com" data-bare-link="true">adam@ospcode.com</a> of Opscode (http://www.opscode.com), with contributions from the community. This -manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a> with +manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +155,8 @@ found in /usr/share/common-licenses/Apache-2.0.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 cfb32f4bb5..f2bf638895 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +231,8 @@ 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.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 b696bf22a2..f306e9fd53 100644 --- a/distro/common/html/knife-client.1.html +++ b/distro/common/html/knife-client.1.html @@ -196,11 +196,11 @@ setting up a host for management with Chef.</p> <h2 id="AUTHOR">AUTHOR</h2> -<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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> @@ -209,8 +209,8 @@ setting up a host for management with Chef.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 54450ce11a..fe66789054 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +160,8 @@ 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.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 60f82a79dd..8b093b5671 100644 --- a/distro/common/html/knife-cookbook-site.1.html +++ b/distro/common/html/knife-cookbook-site.1.html @@ -218,11 +218,11 @@ configuration file.</p> <h2 id="AUTHOR">AUTHOR</h2> -<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +231,8 @@ configuration file.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 1b4d53a5f9..e044adfa1c 100644 --- a/distro/common/html/knife-cookbook.1.html +++ b/distro/common/html/knife-cookbook.1.html @@ -217,9 +217,9 @@ regular expression (<em>regex</em>) should be in quotes, not in //'s.</p> <dl> <dt><code>-o</code>, <code>--cookbook-path path</code></dt><dd>the directory where the cookbook will be created</dd> <dt><code>-r</code>, <code>--readme-format format</code></dt><dd>format of the readme file md, mkd, txt, rdoc</dd> -<dt><code>-c</code>, <code>--copyright copyright</code></dt><dd>name of copyright holder</dd> +<dt><code>-C</code>, <code>--copyright copyright</code></dt><dd>name of copyright holder</dd> <dt><code>-i</code>, <code>--license license</code></dt><dd>license for cookbook, apachev2 or none</dd> -<dt><code>-e</code>, <code>--email email</code></dt><dd>email address of cookbook maintainer</dd> +<dt><code>-m</code>, <code>--email email</code></dt><dd>email address of cookbook maintainer</dd> </dl> @@ -245,7 +245,7 @@ named cookbook.</p> readme file will be written with the specified extension and a set of helpful starting headers.</p> -<p>specify <code>-c</code> or <code>--copyright</code> with the name of the copyright holder as +<p>specify <code>-C</code> or <code>--copyright</code> with the name of the copyright holder as your name or your company/organization name in a quoted string. if this value is not specified an all-caps string <code>your_company_name</code> is used which can be easily changed with find/replace.</p> @@ -258,7 +258,7 @@ the cookbook and follow any restrictions they describe. when using are pre-filled. the <code>none</code> license will be treated as non-redistributable.</p> -<p>specify <code>-e</code> or <code>--email</code> with the email address of the cookbook's +<p>specify <code>-m</code> or <code>--email</code> with the email address of the cookbook's maintainer. if this value is not specified, an all-caps string <code>your_email</code> is used which can easily be changed with find/replace.</p> @@ -358,11 +358,11 @@ cookbook.</p> <h2 id="AUTHOR">AUTHOR</h2> -<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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> @@ -371,8 +371,8 @@ cookbook.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 749f405fb3..058088fe3c 100644 --- a/distro/common/html/knife-data-bag.1.html +++ b/distro/common/html/knife-data-bag.1.html @@ -212,11 +212,11 @@ encryption keys.</p> <h2 id="AUTHOR">AUTHOR</h2> -<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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> @@ -225,8 +225,8 @@ encryption keys.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 972597b9d6..dce5bebe02 100644 --- a/distro/common/html/knife-environment.1.html +++ b/distro/common/html/knife-environment.1.html @@ -242,11 +242,11 @@ override_attributes "aws_s3_bucket" => "production" <h2 id="AUTHOR">AUTHOR</h2> -<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Daniel DeLeo <a href="mailto:dan@opscode.com" data-bare-link="true">dan@opscode.com</a>. +<p> This manual page was written by Daniel DeLeo <a href="mailto:dan@opscode.com" data-bare-link="true">dan@opscode.com</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> @@ -255,8 +255,8 @@ override_attributes "aws_s3_bucket" => "production" <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 c57b8d0dd7..80b94ef63f 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +124,8 @@ description of the commands available.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 fad4e94356..30ed0f5342 100644 --- a/distro/common/html/knife-index.1.html +++ b/distro/common/html/knife-index.1.html @@ -102,11 +102,11 @@ 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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> @@ -115,8 +115,8 @@ time for all objects to be indexed and available for search.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 f5b865d400..4e18fdc9c3 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +240,8 @@ run list, the correct syntax is "role[ROLE_NAME]"</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 c522a519d1..87a6082c69 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +190,8 @@ run_list.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 9c0192416b..323928fe80 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +278,8 @@ www.example.com:</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 64fda20128..926876c4c5 100644 --- a/distro/common/html/knife-ssh.1.html +++ b/distro/common/html/knife-ssh.1.html @@ -133,11 +133,11 @@ option.</dd> <h2 id="AUTHOR">AUTHOR</h2> -<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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> @@ -146,8 +146,8 @@ option.</dd> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 a30eb37743..b2c13bc1fb 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>. +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</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,8 +118,8 @@ may not be publicly reachable.</p> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 bc219db597..becdb07bcf 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> with many contributions from the community.</p> <h2 id="DOCUMENTATION">DOCUMENTATION</h2> -<p> This manual page was written by Daniel DeLeo <a href="mailto:dan@opscode.com" data-bare-link="true">dan@opscode.com</a>. +<p> This manual page was written by Daniel DeLeo <a href="mailto:dan@opscode.com" data-bare-link="true">dan@opscode.com</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,8 +127,8 @@ <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 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 9be0f41754..6f3758323d 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="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</a> of Opscode +<p> Chef was written by Adam Jacob <a href="mailto:adam@opscode.com" data-bare-link="true">adam@opscode.com</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="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>.</p> +<p> This manual page was written by Joshua Timberman <a href="mailto:joshua@opscode.com" data-bare-link="true">joshua@opscode.com</a>.</p> <h2 id="LICENSE">LICENSE</h2> @@ -305,8 +305,8 @@ data editing entirely.</dd> <ol class='man-decor man-foot man foot'> - <li class='tl'>Chef 11.6.0.hotfix.1</li> - <li class='tc'>August 2013</li> + <li class='tl'>Chef 11.8.0.alpha.0</li> + <li class='tc'>July 2013</li> <li class='tr'>knife(1)</li> </ol> diff --git a/distro/common/man/man1/README.md b/distro/common/man/man1/README.md new file mode 100644 index 0000000000..9a915fb4cc --- /dev/null +++ b/distro/common/man/man1/README.md @@ -0,0 +1,58 @@ +# Man pages for Knife + +The source of the Chef Documentation is located at +http://docs.opscode.com/. + +This README documents how the man pages for all of the Knife subcommands +that are built into the chef-client are managed. + +## Source Files + +The source files are located in the chef-docs repository: +https://github.com/opscode/chef-docs + +Each Knife subcommand has its own source folder. The folder naming +pattern begins with man_. + +Each man page is a single file called index.html. + +In the conf.py file, the following settings are unique to each man page: + +`today` setting is used to define the Chef version. This is because we +don't want an arbitrary date populated in the file, yet we still need a +version number. For example: `today = 'Chef 11.8`. + +`project` setting is set to be the same as the name of the subcommand. +For example: `project = u'knife-foo'`. + +`Options for man page output` settings are set to be similar across all +man pages, but each one needs to be tailored specifically for the name +of the man page. + +All of the other settings in the General Configuration section should be +left alone. These exist to ensure that all of the doc builds are sharing +the right common elements and have the same overall presentation. + +## Building Docs + +The docs are built using Sphinx and must be set to the `-b man` output. +Currently, the man pages are built locally and then added to the Chef +builds in chef-master. + +## Editing + +These files should never be edited. All of the content is pulled in from +elsewhere in the chef-docs repo at build time. If changes need to be +made, those changes are done elsewhere and then the man pages must be +rebuilt. This is to help ensure that all of the changes are made across +all of the locations in which these documents need to live. For example, +by design, every Knife subcommand with a man page also has an HTML doc +at docs.opscode.com/knife_foo.html. + +## License + +[Creative Commons Attribution 3.0 Unported License](http://creativecommons.org/licenses/by/3.0/) + +## Questions? + +Open an [Issue](https://github.com/opscode/chef-docs/issues) and ask. diff --git a/distro/common/man/man1/chef-shell.1 b/distro/common/man/man1/chef-shell.1 index 1e2b55f34c..095e8623c0 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "CHEF\-SHELL" "1" "July 2013" "Chef 11.8.0.alpha.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 651a75b9e2..57afe45343 100644 --- a/distro/common/man/man1/knife-bootstrap.1 +++ b/distro/common/man/man1/knife-bootstrap.1 @@ -1,201 +1,199 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "KNIFE\-BOOTSTRAP" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" -. -.SH "NAME" -\fBknife\-bootstrap\fR \- Install Chef Client on a remote host -. -.SH "SYNOPSIS" -\fBknife\fR \fBbootstrap\fR \fI(options)\fR -. +.TH "KNIFE-BOOTSTRAP" "1" "Chef 11.8" "" "knife bootstrap" +.SH NAME +knife-bootstrap \- The man page for the knife bootstrap subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +A bootstrap is a process that installs the chef\-client on a target system so that it can run as a chef\-client and communicate with a server. +.sp +The \fBknife bootstrap\fP subcommand is used run a bootstrap operation that installs the chef\-client on the target system. The bootstrap operation must specify the IP address or FQDN of the target system. +.IP Note +To bootstrap the chef\-client on Microsoft Windows machines, the \fI\%knife-windows\fP plugins is required, which includes the necessary bootstrap scripts that are used to do the actual installation. +.RE +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-i\fR, \fB\-\-identity\-file IDENTITY_FILE\fR -The SSH identity file used for authentication -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-N\fR, \fB\-\-node\-name NAME\fR -The Chef node name for your new node -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB\-P\fR, \fB\-\-ssh\-password PASSWORD\fR -The ssh password -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -\fB\-x\fR, \fB\-\-ssh\-user USERNAME\fR -The ssh username -. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. .TP -\fB\-p\fR, \fB\-\-ssh\-port PORT\fR -The ssh port -. +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. .TP -\fB\-\-bootstrap\-version VERSION\fR -The version of Chef to install -. +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. .TP -\fB\-\-bootstrap\-proxy PROXY_URL\fR -\fBThe proxy server for the node being bootstrapped\fR -. +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. .TP -\fB\-\-prerelease\fR -Install pre\-release Chef gems -. +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. .TP -\fB\-r\fR, \fB\-\-run\-list RUN_LIST\fR -Comma separated list of roles/recipes to apply -. +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. .TP -\fB\-\-template\-file TEMPLATE\fR -Full path to location of template to use -. +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. .TP -\fB\-\-sudo\fR -Execute the bootstrap via sudo -. +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. .TP -\fB\-d\fR, \fB\-\-distro DISTRO\fR -Bootstrap a distro using a template -. +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. .TP -\fB\-\-[no\-]host\-key\-verify\fR -Enable host key verification, which is the default behavior\. -. +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. .TP -\fB\-\-hint HINT_NAME[=HINT_FILE]\fR -Provide the name of a hint (with option JSON file) to set for use by Ohai plugins\. -. -.SH "DESCRIPTION" -Performs a Chef Bootstrap on the target node\. The goal of the bootstrap is to get Chef installed on the target system so it can run Chef Client with a Chef Server\. The main assumption is a baseline OS installation exists\. This sub\-command is used internally by some cloud computing plugins\. -. -.P -The bootstrap sub\-command supports supplying a template to perform the bootstrap steps\. If the distro is not specified (via \fB\-d\fR or \fB\-\-distro\fR option), an Ubuntu 10\.04 host bootstrapped with RubyGems is assumed\. The \fBDISTRO\fR value corresponds to the base filename of the template, in other words \fBDISTRO\fR\.erb\. A template file can be specified with the \fB\-\-template\-file\fR option in which case the \fBDISTRO\fR is not used\. The sub\-command looks in the following locations for the template to use: -. -.IP "\(bu" 4 -\fBbootstrap\fR directory in the installed Chef Knife library\. -. -.IP "\(bu" 4 -\fBbootstrap\fR directory in the \fB$PWD/\.chef\fR\. -. -.IP "\(bu" 4 -\fBbootstrap\fR directory in the users \fB$HOME/\.chef\fR\. -. -.IP "" 0 -. -.P -The default bootstrap templates are scripts that get copied to the target node (FQDN)\. The following distros are supported: -. -.IP "\(bu" 4 -centos5\-gems -. -.IP "\(bu" 4 -fedora13\-gems -. -.IP "\(bu" 4 -ubuntu10\.04\-gems -. -.IP "\(bu" 4 -ubuntu10\.04\-apt -. -.IP "" 0 -. -.P -The gems installations will use RubyGems 1\.3\.6 and Chef installed as a gem\. The apt installation will use the Opscode APT repository\. -. -.P -In addition to handling the software installation, these bootstrap templates do the following: -. -.IP "\(bu" 4 -Write the validation\.pem per the local knife configuration\. -. -.IP "\(bu" 4 -Write a default config file for Chef (\fB/etc/chef/client\.rb\fR) using values from the \fBknife\.rb\fR\. -. -.IP "\(bu" 4 -Create a JSON attributes file containing the specified run list and run Chef\. -. -.IP "" 0 -. -.P -In the case of the RubyGems, the \fBclient\.rb\fR will be written from scratch with a minimal set of values; see \fBEXAMPLES\fR\. In the case of APT Package installation, \fBclient\.rb\fR will have the \fBvalidation_client_name\fR appended if it is not set to \fBchef\-validator\fR (default config value), and the \fBnode_name\fR will be added if \fBchef_node_name\fR option is specified\. -. -.P -When this is complete, the bootstrapped node will have: -. -.IP "\(bu" 4 -Latest Chef version installed from RubyGems or APT Packages from Opscode\. This may be a later version than the local system\. -. -.IP "\(bu" 4 -Be validated with the configured Chef Server\. -. -.IP "\(bu" 4 -Have run Chef with its default run list if one is specfied\. -. -.IP "" 0 -. -.P -Additional custom bootstrap templates can be created and stored in \fB\.chef/bootstrap/DISTRO\.erb\fR, replacing \fBDISTRO\fR with the value passed with the \fB\-d\fR or \fB\-\-distro\fR option\. See \fBEXAMPLES\fR for more information\. -. -.SH "EXAMPLES" -Setting up a custom bootstrap is fairly straightforward\. Create a \fB\.chef/bootstrap\fR directory in your Chef Repository or in \fB$HOME/\.chef/bootstrap\fR\. Then create the ERB template file\. -. -.IP "" 4 -. +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp .nf - -mkdir ~/\.chef/bootstrap -vi ~/\.chef/bootstrap/debian5\.0\-apt\.erb -. +.ft C +$ knife bootstrap FQDN_or_IP_ADDRESS (options) +.ft P .fi -. -.IP "" 0 -. -.P -For example, to create a new bootstrap template that should be used when setting up a new Debian node\. Edit the template to run the commands, set up the validation certificate and the client configuration file, and finally to run chef\-client on completion\. The bootstrap template can be called with: -. -.IP "" 4 -. +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-A\fP, \fB\-\-forward\-agent\fP +Indicates that SSH agent forwarding is enabled. +.TP +.B \fB\-\-bootstrap\-proxy PROXY_URL\fP +The proxy server for the node that is the target of a bootstrap operation. +.TP +.B \fB\-\-bootstrap\-version VERSION\fP +The version of the chef\-client to install. +.TP +.B \fB\-d DISTRO\fP, \fB\-\-distro DISTRO\fP +The template file to be used during a bootstrap operation. The following distributions are supported: \fBchef\-full\fP (the default bootstrap), \fBcentos5\-gems\fP, \fBfedora13\-gems\fP, \fBubuntu10.04\-gems\fP, \fBubuntu10.04\-apt\fP, \fBubuntu12.04\-gems\fP, and the name of a custom bootstrap template file. When this option is used, Knife will search for the template file in the following order: the \fBbootstrap/\fP folder in the current working directory, the \fBbootstrap/\fP folder in the chef\-repo, the \fBbootstrap/\fP folder in the \fB~/.chef/\fP directory, or a default bootstrap file. Do not use the \fB\-\-template\-file\fP option when \fB\-\-distro\fP is specified. +.TP +.B \fB\-G GATEWAY\fP, \fB\-\-ssh\-gateway GATEWAY\fP +The SSH tunnel or gateway that is used to run a bootstrap action on a machine that is not accessible from the workstation. +.TP +.B \fB\-\-hint HINT_NAME[=HINT_FILE]\fP +An Ohai hint to be set on the target of the bootstrap. The hint is contained in a file and is formatted as JSON: \fB{"attribute":"value","attribute":"value"...}\fP. \fBHINT_NAME\fP is the name of the hint and \fBHINT_FILE\fP is the name of the hint file located at \fB/etc/chef/ohai/hints/HINT_FILE.json\fP. Use multiple \fB\-\-hint\fP options in the command to specify multiple hints. +.TP +.B \fB\-i IDENTITY_FILE\fP, \fB\-\-identity\-file IDENTITY_FILE\fP +The SSH identity file used for authentication. Key\-based authentication is recommended. +.TP +.B \fB\-j JSON_ATTRIBS\fP, \fB\-\-json\-attributes JSON_ATTRIBS\fP +A JSON string that is added to the first run of a chef\-client. +.TP +.B \fB\-N NAME\fP, \fB\-\-node\-name NAME\fP +The name of the node. +.TP +.B \fB\-\-[no\-]host\-key\-verify\fP +Use \fB\-\-no\-host\-key\-verify\fP to disable host key verification. Default setting: \fB\-\-host\-key\-verify\fP. +.TP +.B \fB\-p PORT\fP, \fB\-\-ssh\-port PORT\fP +The SSH port. +.TP +.B \fB\-P PASSWORD\fP, \fB\-\-ssh\-password PASSWORD\fP +The SSH password. This can be used to pass the password directly on the command line. If this option is not specified (and a password is required) Knife will prompt for the password. +.TP +.B \fB\-\-prerelease\fP +Indicates that pre\-release gems should be installed. +.TP +.B \fB\-r RUN_LIST\fP, \fB\-\-run\-list RUN_LIST\fP +A comma\-separated list of roles and/or recipes to be applied. +.TP +.B \fB\-\-secret SECRET\fP +The encryption key that is used for values contained within a data bag. +.TP +.B \fB\-\-secret\-file FILE\fP +The path to the file that contains the encryption key. +.TP +.B \fB\-\-sudo\fP +Indicates that a bootstrap operation should be executed using sudo. +.TP +.B \fB\-\-template\-file TEMPLATE\fP +The path to a template file that will be used during a bootstrap operation. Do not use the \fB\-\-distro\fP option when \fB\-\-template\-file\fP is specified. +.TP +.B \fB\-\-use\-sudo\-password\fP +Indicates that a bootstrap operation is done using sudo, with the password specified by the \fB\-P\fP (or \fB\-\-ssh\-password\fP) option. +.TP +.B \fB\-x USERNAME\fP, \fB\-\-ssh\-user USERNAME\fP +The SSH user name. +.UNINDENT +.sp +\fBExamples\fP +.sp +To pass an SSH password as part of the command: +.sp .nf - -knife bootstrap mynode\.example\.com \-\-template\-file ~/\.chef/bootstrap/debian5\.0\-apt\.erb -. +.ft C +$ knife bootstrap 192.168.1.1 \-x username \-P PASSWORD \-\-sudo +.ft P .fi -. -.IP "" 0 -. -.P -Or, -. -.IP "" 4 -. +.sp +To use a file that contains a private key: +.sp .nf - -knife bootstrap mynode\.example\.com \-\-distro debian5\.0\-apt -. +.ft C +$ knife bootstrap 192.168.1.1 \-x username \-i ~/.ssh/id_rsa \-\-sudo +.ft P .fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.IP "" 0 -. -.P -The \fB\-\-distro\fR parameter will automatically look in the \fB~/\.chef/bootstrap\fR directory for a file named \fBdebian5\.0\-apt\.erb\fR\. -. -.P -Templates provided by the Chef installation are located in \fBBASEDIR/lib/chef/knife/bootstrap/*\.erb\fR, where \fIBASEDIR\fR is the location where the package or Gem installed the Chef client libraries\. -. -.SH "BUGS" -\fBknife bootstrap\fR is not capable of bootstrapping multiple hosts in parallel\. -. -.P -The bootstrap script is passed as an argument to sh(1) on the remote system, so sensitive information contained in the script will be visible to other users via the process list using tools such as ps(1)\. -. -.SH "SEE ALSO" -\fBknife\-ssh\fR(1) -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. -. -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-client.1 b/distro/common/man/man1/knife-client.1 index 4479856b9f..50b42c759b 100644 --- a/distro/common/man/man1/knife-client.1 +++ b/distro/common/man/man1/knife-client.1 @@ -1,99 +1,370 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 +.TH "KNIFE-CLIENT" "1" "Chef 11.8" "" "knife client" +.SH NAME +knife-client \- The man page for the knife client subcommand. . -.TH "KNIFE\-CLIENT" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.nr rst2man-indent-level 0 . -.SH "NAME" -\fBknife\-client\fR \- Manage Chef API Clients -. -.SH "SYNOPSIS" -\fBknife\fR \fBclient\fR \fIsub\-command\fR \fI(options)\fR -. -.SH "SUB\-COMMANDS" -Client subcommands follow a basic create, read, update, delete (CRUD) pattern\. The Following subcommands are available: -. -.SH "BULK DELETE" -\fBknife client bulk delete\fR \fIregex\fR \fI(options)\fR -. -.P -Delete clients where the client name matches the regular expression \fIregex\fR on the Chef Server\. The regular expression should be given as a quoted string, and not surrounded by forward slashes\. -. -.SH "CREATE" -\fBknife client create\fR \fIclient name\fR \fI(options)\fR +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. . +.sp +When a node runs the chef\-client for the first time, it generally does not yet have an API client identity, and so it cannot make authenticated requests to the server. This is where the validation client\-\-\-known as the chef\-validator\-\-\-comes in. When the chef\-client runs, it checks if it has a client key. If the client key does not exist, it then attempts to borrow the identity of the chef\-validator to register itself with the server. In order to register with the server, the private key for the chef\-validator needs to be copied to the host and placed in /etc/chef/validation.pem. +.sp +Once the chef\-client has registered itself with the server, it no longer uses the validation client for anything. It is recommended that you delete the private key for the chef\-validator from the host after the host has registered or use the \fBdelete_validation\fP recipe that can be found in the \fBchef\-client\fP cookbook (\fI\%https://github.com/opscode-cookbooks/chef-client\fP). +.sp +The \fBknife client\fP subcommand is used to manage an API client list and their associated RSA public key\-pairs. This allows authentication requests to be made to the server by any entity that uses the Chef Server API, such as the chef\-client and Knife. +.sp +This subcommand has the following syntax: +.sp +.nf +.ft C +$ knife client [ARGUMENT] (options) +.ft P +.fi +.SH COMMON OPTIONS +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-a\fR, \fB\-\-admin\fR -Create the client as an admin -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-f\fR, \fB\-\-file FILE\fR -Write the key to a file -. -.P -Create a new client\. This generates an RSA keypair\. The private key will be displayed on \fISTDOUT\fR or written to the named file\. The public half will be stored on the Server\. For \fIchef\-client\fR systems, the private key should be copied to the system as \fB/etc/chef/client\.pem\fR\. -. -.P -Admin clients should be created for users that will use \fIknife\fR to access the API as an administrator\. The private key will generally be copied to \fB~/\.chef/client\e_name\.pem\fR and referenced in the \fBknife\.rb\fR configuration file\. -. -.SH "DELETE" -\fBknife client delete\fR \fIclient name\fR \fI(options)\fR -. -.P -Deletes a registered client\. -. -.SH "EDIT" -\fBclient edit\fR \fIclient name\fR \fI(options)\fR -. -.P -Edit a registered client\. -. -.SH "LIST" -\fBclient list\fR \fI(options)\fR -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB\-w\fR, \fB\-\-with\-uri\fR -Show corresponding URIs -. -.P -List all registered clients\. -. -.SH "REREGISTER" -\fBclient reregister\fR \fIclient name\fR \fI(options)\fR -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -\fB\-f\fR, \fB\-\-file FILE\fR -Write the key to a file -. -.P -Regenerate the RSA keypair for a client\. The public half will be stored on the server and the private key displayed on \fISTDOUT\fR or written to the named file\. This operation will invalidate the previous keypair used by the client, preventing it from authenticating with the Chef Server\. Use care when reregistering the validator client\. -. -.SH "SHOW" -\fBclient show\fR \fIclient name\fR \fI(options)\fR -. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. .TP -\fB\-a\fR, \fB\-\-attribute ATTR\fR -Show only one attribute -. -.P -Show a client\. Output format is determined by the \-\-format option\. -. -.SH "DESCRIPTION" -Clients are identities used for communication with the Chef Server API, roughly equivalent to user accounts on the Chef Server, except that clients only communicate with the Chef Server API and are authenticated via request signatures\. -. -.P -In the typical case, there will be one client object on the server for each node, and the corresponding client and node will have identical names\. -. -.P -In the Chef authorization model, there is one special client, the "validator", which is authorized to create new non\-administrative clients but has minimal privileges otherwise\. This identity is used as a sort of "guest account" to create a client identity when initially setting up a host for management with Chef\. -. -.SH "SEE ALSO" -\fBknife\-node\fR(1) -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.SH BULK DELETE +.sp +The \fBbulk delete\fP argument is used to delete any API client that matches a pattern defined by a regular expression. The regular expression must be within quotes and not be surrounded by forward slashes (/). +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife client bulk delete REGEX +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.SH CREATE +.sp +The \fBcreate\fP argument is used to create a new API client. This process will generate an RSA key pair for the named API client. The public key will be stored on the server and the private key will be displayed on \fBSTDOUT\fP or written to a named file. +.INDENT 0.0 +.IP \(bu 2 +For the chef\-client, the private key should be copied to the system as /etc/chef/client.pem. +.IP \(bu 2 +For Knife, the private key is typically copied to ~/.chef/client_name.pem and referenced in the knife.rb configuration file. +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife client create CLIENT_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-admin\fP +Indicates that a client will be created as an admin client. This is required when users of the open source server need to access the Chef Server API as an administrator. This option only works when used with the open source server and will have no effect when used with Hosted Chef or Private Chef. +.UNINDENT +.sp +\fBExamples\fP +.sp +To create a Chef Admin client with the name "exampleorg" and save its private key to a file, enter: +.sp +.nf +.ft C +$ knife client create exampleorg \-a \-f "/etc/chef/client.pem" +.ft P +.fi +.sp +When running the \fBcreate\fP argument on Hosted Chef or Private Chef, be sure to omit the \fB\-a\fP option: +.sp +.nf +.ft C +$ knife client create exampleorg \-f "/etc/chef/client.pem" +.ft P +.fi +.SH DELETE +.sp +The \fBdelete\fP argument is used to delete a registered API client. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife client delete CLIENT_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To delete a client with the name "client_foo", enter: +.sp +.nf +.ft C +$ knife client delete client_foo +.ft P +.fi +.sp +Type \fBY\fP to confirm a deletion. +.SH EDIT +.sp +The \fBedit\fP argument is used to edit the details of a registered API client. When this argument is run, Knife will open $EDITOR to enable editing of the \fBadmin\fP attribute. (None of the other attributes should be changed using this argument.) When finished, Knife will update the server with those changes. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife client edit CLIENT_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To edit a client with the name "exampleorg", enter: +.sp +.nf +.ft C +$ knife client edit exampleorg +.ft P +.fi +.SH LIST +.sp +The \fBlist\fP argument is used to view a list of registered API client. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife client list (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-w\fP, \fB\-\-with\-uri\fP +Indicates that the corresponding URIs will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +To verify the API client list for the server, enter: +.sp +.nf +.ft C +$ knife client list +.ft P +.fi +.sp +to return something similar to: +.sp +.nf +.ft C +exampleorg +i\-12345678 +rs\-123456 +.ft P +.fi +.sp +To verify that an API client can authenticate to the +server correctly, try getting a list of clients using \fB\-u\fP and \fB\-k\fP options to specify its name and private key: +.sp +.nf +.ft C +$ knife client list \-u ORGNAME \-k .chef/ORGNAME.pem +.ft P +.fi +.SH REREGISTER +.sp +The \fBreregister\fP argument is used to regenerate an RSA key pair for an API client. The public key will be stored on the server and the private key will be displayed on \fBSTDOUT\fP or written to a named file. +.IP Note +Running this argument will invalidate the previous RSA key pair, making it unusable during authentication to the server. +.RE +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife client reregister CLIENT_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.UNINDENT +.sp +\fBExamples\fP +.sp +To regenerate the RSA key pair for a client named "testclient" and save it to a file named "rsa_key", enter: +.sp +.nf +.ft C +$ knife client regenerate testclient \-f rsa_key +.ft P +.fi +.SH SHOW +.sp +The \fBshow\fP argument is used to show the details of an API client. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife client show CLIENT_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a ATTR\fP, \fB\-\-attribute ATTR\fP +The attribute (or attributes) to show. +.UNINDENT +.sp +\fBExamples\fP +.sp +To view a client named "testclient", enter: +.sp +.nf +.ft C +$ knife client show testclient +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +admin: false +chef_type: client +json_class: Chef::ApiClient +name: testclient +public_key: +.ft P +.fi +.sp +To view information in JSON format, use the \fB\-F\fP common option as part of the command like this: +.sp +.nf +.ft C +$ knife role show devops \-F json +.ft P +.fi +.sp +Other formats available include \fBtext\fP, \fByaml\fP, and \fBpp\fP. +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-configure.1 b/distro/common/man/man1/knife-configure.1 index 1c3d793364..8ca138f3d4 100644 --- a/distro/common/man/man1/knife-configure.1 +++ b/distro/common/man/man1/knife-configure.1 @@ -1,88 +1,152 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "KNIFE\-CONFIGURE" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" -. -.SH "NAME" -\fBknife\-configure\fR \- Generate configuration files for knife or Chef Client -. -.SH "SYNOPSIS" -\fBknife\fR \fBconfigure\fR [client] \fI(options)\fR -. -.SH "DESCRIPTION" -Generates a knife\.rb configuration file interactively\. When given the \-\-initial option, also creates a new administrative user\. -. -.SH "CONFIGURE SUBCOMMANDS" -\fBknife configure\fR \fI(options)\fR -. +.TH "KNIFE-CONFIGURE" "1" "Chef 11.8" "" "knife configure" +.SH NAME +knife-configure \- The man page for the knife configure subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife configure\fP subcommand is used to create the knife.rb and client.rb files so that they can be distributed to workstations and nodes. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-i\fR, \fB\-\-initial\fR -Create an initial API Client -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-r\fR, \fB\-\-repository REPO\fR -The path to your chef\-repo -. -.P -Create a configuration file for knife\. This will prompt for values to enter into the file\. Default values are listed in square brackets if no other entry is typed\. See \fBknife\fR(1) for a description of configuration options\. -. -.P -\fBknife configure client\fR \fIdirectory\fR -. -.P -Read the \fIknife\.rb\fR config file and generate a config file suitable for use in \fI/etc/chef/client\.rb\fR and copy the validation certificate into the specified \fIdirectory\fR\. -. -.SH "EXAMPLES" -. -.IP "\(bu" 4 -On a freshly installed Chef Server, use \fIknife configure \-i\fR to create an administrator and knife configuration file\. Leave the field blank to accept the default value\. On most systems, the default values are acceptable\. -. -.IP -user@host$ knife configure \-i -. -.br -Please enter the chef server URL: [http://localhost:4000] -. -.br -Please enter a clientname for the new client: [username] -. -.br -Please enter the existing admin clientname: [chef\-webui] -. -.br -Please enter the location of the existing admin client\'s private key: [/etc/chef/webui\.pem] -. -.br -Please enter the validation clientname: [chef\-validator] -. -.br -Please enter the location of the validation key: [/etc/chef/validation\.pem] -. -.br -Please enter the path to a chef repository (or leave blank): -. -.br -Creating initial API user\.\.\. -. -.br -Created (or updated) client[username] -. -.br -Configuration file written to /home/username/\.chef/knife\.rb -. -.IP -This creates a new administrator client named \fIusername\fR, writes a configuration file to \fI/home/username/\.chef/knife\.rb\fR, and the private key to \fI/home/username/\.chef/username\.pem\fR\. The configuration file and private key may be copied to another system to facilitate administration of the Chef Server from a remote system\. Depending on the value given for the Chef Server URL, you may need to modify that setting after copying to a remote host\. -. -.IP "" 0 -. -.SH "SEE ALSO" -\fBknife\fR(1) \fBknife\-client\fR(1) -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife configure (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-admin\-client\-name NAME\fP +The name of the client, typically the name of the admin client. +.TP +.B \fB\-\-admin\-client\-key PATH\fP +The path to the private key used by the client, typically a file named \fBadmin.pem\fP. +.TP +.B \fB\-i\fP, \fB\-\-initial\fP +Use to create a API client, typically an administrator client on a freshly\-installed server. +.TP +.B \fB\-r REPO\fP, \fB\-\-repository REPO\fP +The path to the chef\-repo. +.TP +.B \fB\-\-validation\-client\-name NAME\fP +The name of the validation client. +.TP +.B \fB\-\-validation\-key PATH\fP +The path to the validation key used by the client, typically a file named \fBvalidation.pem\fP. +.UNINDENT +.sp +\fBExamples\fP +.sp +To create a knife.rb file, enter: +.sp +.nf +.ft C +$ knife configure +.ft P +.fi +.sp +To configure a client.rb, enter: +.sp +.nf +.ft C +$ knife configure client \(aq/directory\(aq +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-cookbook-site.1 b/distro/common/man/man1/knife-cookbook-site.1 index 6a0d7a61bd..049900fce8 100644 --- a/distro/common/man/man1/knife-cookbook-site.1 +++ b/distro/common/man/man1/knife-cookbook-site.1 @@ -1,145 +1,479 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "KNIFE\-COOKBOOK\-SITE" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" -. -.SH "NAME" -\fBknife\-cookbook\-site\fR \- Install and update open source cookbooks -. -.SH "SYNOPSIS" -\fBknife\fR \fBcookbook site\fR \fIsub\-command\fR \fI(options)\fR -. -.SH "COOKBOOK SITE SUB\-COMMANDS" -\fBknife cookbook site\fR provides the following subcommands: -. -.SH "INSTALL" -\fBcookbook site install COOKBOOK [VERSION]\fR \fI(options)\fR -. +.TH "KNIFE-COOKBOOK-SITE" "1" "Chef 11.8" "" "knife cookbook site" +.SH NAME +knife-cookbook-site \- The man page for the knife cookbook site subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The Cookbooks Site API is used to provide access to the cookbooks community hosted at \fI\%https://cookbooks.opscode.com\fP. All of the cookbooks in the community are accessible through a REST API located at \fI\%https://cookbooks.opscode.com/api/v1/\fP by using any of the supported endpoints. In most cases, using Knife and the \fBknife cookbook site\fP sub\-command (and any of its arguments) is the recommended method of interacting with these cookbooks, but in some cases, using the REST API directly may make sense. +.sp +The \fBknife cookbook site\fP subcommand is used to interact with cookbooks that are located at \fI\%https://cookbooks.opscode.com\fP. A user account is required for any community actions that write data to this site. The following arguments do not require a user account: \fBdownload\fP, \fBsearch\fP, \fBinstall\fP, and \fBlist\fP. +.sp +This subcommand has the following syntax: +.sp +.nf +.ft C +$ knife cookbook site [ARGUMENT] (options) +.ft P +.fi +.SH COMMON OPTIONS +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-D\fR, \fB\-\-skip\-dependencies\fR -Skip automatic installation of dependencies\. -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-o\fR, \fB\-\-cookbook\-path PATH\fR -Install cookbooks to PATH -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB\-B\fR, \fB\-\-branch BRANCH\fR -Default branch to work with [defaults to master] -. -.P -Uses git(1) version control in conjunction with the cookbook site to install community contributed cookbooks to your local cookbook repository\. Running \fBknife cookbook site install\fR does the following: -. -.IP "1." 4 -A new "pristine copy" branch is created in git for tracking the upstream; -. -.IP "2." 4 -All existing cookbooks are removed from the branch; -. -.IP "3." 4 -The cookbook is downloaded from the cookbook site in tarball form; -. -.IP "4." 4 -The downloaded cookbook is untarred, and its contents commited via git; -. -.IP "5." 4 -The pristine copy branch is merged into the master branch\. -. -.IP "" 0 -. -.P -By installing cookbook with this process, you can locally modify the upstream cookbook in your master branch and let git maintain your changes as a separate patch\. When an updated upstream version becomes available, you will be able to merge the upstream changes while maintaining your local modifications\. -. -.P -Unless \fI\-\-skip\-dependencies\fR is specified, the process is applied recursively to all the cookbooks \fICOOKBOOK\fR depends on (via metadata \fIdependencies\fR)\. -. -.SH "DOWNLOAD" -\fBknife cookbook site download COOKBOOK [VERSION]\fR \fI(options)\fR -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -\fB\-f\fR, \fB\-\-file FILE\fR -The filename to write to -. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. .TP -\fB\-\-force\fR -Force download deprecated cookbook -. -.P -Downloads a specific cookbook from the Community site, optionally specifying a certain version\. -. -.SH "LIST" -\fBknife cookbook site list\fR \fI(options)\fR -. +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. .TP -\fB\-w\fR, \fB\-\-with\-uri\fR -Show corresponding URIs -. -.P -Lists available cookbooks from the Community site\. -. -.SH "SEARCH" -\fBknife cookbook site search QUERY\fR \fI(options)\fR -. -.P -Searches for available cookbooks matching the specified query\. -. -.SH "SHARE" -\fBknife cookbook site share COOKBOOK CATEGORY\fR \fI(options)\fR -. +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. .TP -\fB\-k\fR, \fB\-\-key KEY\fR -API Client Key -. +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. .TP -\fB\-u\fR, \fB\-\-user USER\fR -API Client Username -. +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. .TP -\fB\-o\fR, \fB\-\-cookbook\-path PATH:PATH\fR -A colon\-separated path to look for cookbooks in -. -.P -Uploads the specified cookbook using the given category to the Opscode cookbooks site\. Requires a login user and certificate for the Opscode Cookbooks site\. By default, knife will use the username and API key you\'ve configured in your configuration file; otherwise you must explicitly set these values on the command line or use an alternate configuration file\. -. -.SH "UNSHARE" -\fBknife cookbook site unshare COOKBOOK\fR -. -.P -Stops sharing the specified cookbook on the Opscode cookbooks site\. -. -.SH "SHOW" -\fBknife cookbook site show COOKBOOK [VERSION]\fR \fI(options)\fR -. -.P -Shows information from the site about a particular cookbook\. -. -.SH "DESCRIPTION" -The cookbook site, \fIhttp://community\.opscode\.com/\fR, 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 -\fBknife cookbook site\fR commands provide an interface to the cookbook site\'s HTTP API\. For commands that read data from the API, no account is required\. In order to upload cookbooks using the \fBknife cookbook site share\fR command, you must create an account on the cookbook site and configure your credentials via command line option or in your knife configuration file\. -. -.SH "EXAMPLES" -Uploading cookbooks to the Opscode cookbooks site: -. -.IP "" 4 -. +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.SH DOWNLOAD +.sp +The \fBdownload\fP argument is used to download a cookbook from the community website. A cookbook will be downloaded as a tar.gz archive and placed in the current working directory. If a cookbook (or cookbook version) has been deprecated and the \fB\-\-force\fP option is not used, Knife will alert the user that the cookbook is deprecated and then will provide the name of the most recent non\-deprecated version of that cookbook. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp .nf - -knife cookbook site share example Other \-k ~/\.chef/USERNAME\.pem \-u USERNAME -. +.ft C +$ knife cookbook site download COOKBOOK_NAME [COOKBOOK_VERSION] (options) +.ft P .fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fBCOOKBOOK_VERSION\fP +The version of a cookbook to be downloaded. If a cookbook has only one version, this option does not need to be specified. If a cookbook has more than one version and this option is not specified, Knife will prompt for a version. +.TP +.B \fB\-f\fP, \fB\-\-force\fP +Indicates that an existing directory will be overwritten. +.UNINDENT +.sp +\fBExamples\fP +.sp +To download the cookbook "getting\-started", enter: +.sp +.nf +.ft C +$ knife cookbook site download getting\-started +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +Downloading getting\-started from the cookbooks site at version 0.3.0 to + /Users/sdanna/opscodesupport/getting\-started\-0.3.0.tar.gz +Cookbook saved: /Users/sdanna/opscodesupport/getting\-started\-0.3.0.tar.gz +.ft P +.fi +.SH INSTALL +.sp +The \fBinstall\fP argument is used to install a cookbook that has been downloaded from the community site to a local git repository . This action uses the git version control system in conjunction with the \fI\%https://cookbooks.opscode.com\fP site to install community\-contributed cookbooks to the local chef\-repo. Using this argument does the following: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP 1. 3 +A new "pristine copy" branch is created in git for tracking the upstream. +.IP 2. 3 +All existing versions of a cookbook are removed from the branch. +.IP 3. 3 +The cookbook is downloaded from \fI\%https://cookbooks.opscode.com\fP in the tar.gz format. +.IP 4. 3 +The downloaded cookbook is untarred and its contents are committed to git and a tag is created. +.IP 5. 3 +The "pristine copy" branch is merged into the master branch. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +This process allows the upstream cookbook in the master branch to be modified while letting git maintain changes as a separate patch. When an updated upstream version becomes available, those changes can be merged while maintaining any local modifications. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook site install COOKBOOK_NAME [COOKBOOK_VERSION] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-b\fP, \fB\-\-use\-current\-branch\fP +Indicates that the current branch will be used. +.TP +.B \fB\-B BRANCH\fP, \fB\-\-branch BRANCH\fP +The name of the default branch. This will default to the master branch. +.TP +.B \fBCOOKBOOK_VERSION\fP +The version of the cookbook to be installed. If a version is not specified, the most recent version of the cookbook will be installed. +.TP +.B \fB\-D\fP, \fB\-\-skip\-dependencies\fP +Indicates that all cookbooks to which the installed cookbook has a dependency will not be installed. +.TP +.B \fB\-o PATH:PATH\fP, \fB\-\-cookbook\-path PATH:PATH\fP +The directory in which cookbook are created. This can be a colon\-separated path. +.UNINDENT +.sp +\fBExamples\fP +.sp +To install the cookbook "getting\-started", enter: +.sp +.nf +.ft C +$ knife cookbook site install getting\-started +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +Installing getting\-started to /Users/sdanna/opscodesupport/.chef/../cookbooks +Checking out the master branch. +Creating pristine copy branch chef\-vendor\-getting\-started +Downloading getting\-started from the cookbooks site at version 0.3.0 to + /Users/sdanna/opscodesupport/.chef/../cookbooks/getting\-started.tar.gz +Cookbook saved: /Users/sdanna/opscodesupport/.chef/../cookbooks/getting\-started.tar.gz +Removing pre\-existing version. +Uncompressing getting\-started version /Users/sdanna/opscodesupport/.chef/../cookbooks. +removing downloaded tarball +1 files updated, committing changes +Creating tag cookbook\-site\-imported\-getting\-started\-0.3.0 +Checking out the master branch. +Updating 4d44b5b..b4c32f2 +Fast\-forward + cookbooks/getting\-started/README.rdoc | 4 +++ + cookbooks/getting\-started/attributes/default.rb | 1 + + cookbooks/getting\-started/metadata.json | 29 ++++++++++++++++++++ + cookbooks/getting\-started/metadata.rb | 6 ++++ + cookbooks/getting\-started/recipes/default.rb | 23 +++++++++++++++ + .../templates/default/chef\-getting\-started.txt.erb | 5 +++ + 6 files changed, 68 insertions(+), 0 deletions(\-) + create mode 100644 cookbooks/getting\-started/README.rdoc + create mode 100644 cookbooks/getting\-started/attributes/default.rb + create mode 100644 cookbooks/getting\-started/metadata.json + create mode 100644 cookbooks/getting\-started/metadata.rb + create mode 100644 cookbooks/getting\-started/recipes/default.rb + create mode 100644 cookbooks/getting\-started/templates/default/chef\-getting\-started.txt.erb +Cookbook getting\-started version 0.3.0 successfully installed +.ft P +.fi +.SH LIST +.sp +The \fBlist\fP argument is used to view a list of cookbooks that are currently available at \fI\%https://cookbooks.opscode.com\fP. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook site list +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-w\fP, \fB\-\-with\-uri\fP +Indicates that the corresponding URIs will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +To view a list of cookbooks at \fI\%https://cookbooks.opscode.com\fP server, enter: +.sp +.nf +.ft C +$ knife cookbook site list +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +1password homesick rabbitmq +7\-zip hostname rabbitmq\-management +AmazonEC2Tag hosts rabbitmq_chef +R hosts\-awareness rackspaceknife +accounts htop radiant +ack\-grep hudson rails +activemq icinga rails_enterprise +ad id3lib redis\-package +ad\-likewise iftop redis2 +ant iis redmine +[...truncated...] +.ft P +.fi +.SH SEARCH +.sp +The \fBsearch\fP argument is used to search for a cookbook at \fI\%https://cookbooks.opscode.com\fP. A search query is used to return a list of cookbooks at \fI\%https://cookbooks.opscode.com\fP and uses the same syntax as the \fBknife search\fP sub\-command. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook site search SEARCH_QUERY (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To search for all of the cookbooks that can be used with Apache, enter: +.sp +.nf +.ft C +$ knife cookbook site search apache* +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +apache2: + cookbook: http://cookbooks.opscode.com/api/v1/cookbooks/apache2 + cookbook_description: Installs and configures apache2 using Debian symlinks with helper definitions + cookbook_maintainer: opscode + cookbook_name: apache2 +instiki: + cookbook: http://cookbooks.opscode.com/api/v1/cookbooks/instiki + cookbook_description: Installs instiki, a Ruby on Rails wiki server under passenger+Apache2. + cookbook_maintainer: jtimberman + cookbook_name: instiki +kickstart: + cookbook: http://cookbooks.opscode.com/api/v1/cookbooks/kickstart + cookbook_description: Creates apache2 vhost and serves a kickstart file. + cookbook_maintainer: opscode + cookbook_name: kickstart +[...truncated...] +.ft P +.fi +.SH SHARE +.sp +The \fBshare\fP argument is used to add a cookbook to \fI\%https://cookbooks.opscode.com\fP. This action will require a user account and a certificate for \fI\%http://community.opscode.com\fP. By default, Knife will use the user name and API key that is identified in the configuration file used during the upload; otherwise these values must be specified on the command line or in an alternate configuration file. If a cookbook already exists on \fI\%https://cookbooks.opscode.com\fP, then only an owner or maintainer of that cookbook can make updates. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook site share COOKBOOK_NAME CATEGORY (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fBCATEGORY\fP +The cookbook category: \fBDatabases\fP, \fBWeb Servers\fP, \fBProcess Management\fP, \fBMonitoring and Trending\fP, \fBProgramming Languages\fP, \fBPackage Management\fP, \fBApplications\fP, \fBNetworking\fP, \fBOperations Systems and Virtualization\fP, \fBUtilities\fP, or \fBOther\fP. +.TP +.B \fB\-o PATH:PATH\fP, \fB\-\-cookbook\-path PATH:PATH\fP +The directory in which cookbook are created. This can be a colon\-separated path. +.UNINDENT +.sp +\fBExamples\fP +.sp +To share a cookbook named "apache2": +.sp +.nf +.ft C +$ knife cookbook site share "apache2" "Web Servers" +.ft P +.fi +.SH SHOW +.sp +The \fBshow\fP argument is used to view information about a cookbook on \fI\%https://cookbooks.opscode.com\fP. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook site show COOKBOOK_NAME [COOKBOOK_VERSION] +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fBCOOKBOOK_VERSION\fP +The version of a cookbook to be shown. If a cookbook has only one version, this option does not need to be specified. If a cookbook has more than one version and this option is not specified, a list of cookbook versions will be returned. +.UNINDENT +.sp +\fBExamples\fP +.sp +To show the details for a cookbook named "haproxy": +.sp +.nf +.ft C +$ knife cookbook site show haproxy +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +average_rating: +category: Networking +created_at: 2009\-10\-25T23:51:07Z +description: Installs and configures haproxy +external_url: +latest_version: http://cookbooks.opscode.com/api/v1/cookbooks/haproxy/versions/1_0_3 +maintainer: opscode +name: haproxy +updated_at: 2011\-06\-30T21:53:25Z +versions: + http://cookbooks.opscode.com/api/v1/cookbooks/haproxy/versions/1_0_3 + http://cookbooks.opscode.com/api/v1/cookbooks/haproxy/versions/1_0_2 + http://cookbooks.opscode.com/api/v1/cookbooks/haproxy/versions/1_0_1 + http://cookbooks.opscode.com/api/v1/cookbooks/haproxy/versions/1_0_0 + http://cookbooks.opscode.com/api/v1/cookbooks/haproxy/versions/0_8_1 + http://cookbooks.opscode.com/api/v1/cookbooks/haproxy/versions/0_8_0 + http://cookbooks.opscode.com/api/v1/cookbooks/haproxy/versions/0_7_0 +.ft P +.fi +.sp +To view information in JSON format, use the \fB\-F\fP common option as part of the command like this: +.sp +.nf +.ft C +$ knife role show devops \-F json +.ft P +.fi +.sp +Other formats available include \fBtext\fP, \fByaml\fP, and \fBpp\fP. +.SH UNSHARE +.sp +The \fBunshare\fP argument is used to stop the sharing of a cookbook at \fI\%https://cookbooks.opscode.com\fP. Only the maintainer of a cookbook may perform this action. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook site unshare COOKBOOK_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To unshare a cookbook named "getting\-started", enter: +.sp +.nf +.ft C +$ knife cookbook site unshare getting\-started +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.IP "" 0 -. -.SH "SEE ALSO" -\fBknife\-cookbook(1)\fR \fIhttp://community\.opscode\.com/cookbooks\fR -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. -. -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-cookbook.1 b/distro/common/man/man1/knife-cookbook.1 index 60931f37c6..82e991687c 100644 --- a/distro/common/man/man1/knife-cookbook.1 +++ b/distro/common/man/man1/knife-cookbook.1 @@ -1,332 +1,644 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "KNIFE\-COOKBOOK" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" -. -.SH "NAME" -\fBknife\-cookbook\fR \- upload and manage chef cookbooks -. -.SH "SYNOPSIS" -\fBknife\fR \fBcookbook\fR \fIsub\-command\fR \fI(options)\fR -. -.SH "SUB\-COMMANDS" -\fBknife cookbook\fR supports the following sub commands: -. -.SH "LIST" -\fBknife cookbook list\fR \fI(options)\fR -. -.TP -\fB\-a\fR, \fB\-\-all\fR -show all versions of a cookbook instead of just the most recent -. -.TP -\fB\-w\fR, \fB\-\-with\-uri\fR -show corresponding uris -. -.P -Lists the cookbooks available on the Chef server\. -. -.SH "SHOW" -\fBknife cookbook show cookbook [version] [part] [filename]\fR \fI(options)\fR -. -.TP -\fB\-f\fR, \fB\-\-fqdn fqdn\fR -the fqdn of the host to see the file for -. -.TP -\fB\-p\fR, \fB\-\-platform platform\fR -the platform to see the file for -. -.TP -\fB\-v\fR, \fB\-\-platform\-version version\fR -the platform version to see the file for -. +.TH "KNIFE-COOKBOOK" "1" "Chef 11.8" "" "knife cookbook" +.SH NAME +knife-cookbook \- The man page for the knife cookbook subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +A cookbook is the fundamental unit of configuration and policy distribution. Each cookbook defines a scenario, such as everything needed to install and configure MySQL, and then it contains all of the components that are required to support that scenario, including: +.INDENT 0.0 +.IP \(bu 2 +Attribute values that are set on nodes +.IP \(bu 2 +Definitions that allow the creation of reusable collections of resources +.IP \(bu 2 +File distributions +.IP \(bu 2 +Libraries that extend the chef\-client and/or provide helpers to Ruby code +.IP \(bu 2 +Recipes that specify which resources to manage and the order in which those resources will be applied +.IP \(bu 2 +Custom resources and providers +.IP \(bu 2 +Templates +.IP \(bu 2 +Versions +.IP \(bu 2 +Metadata about recipes (including dependencies), version constraints, supported platforms, and so on +.UNINDENT +.sp +The \fBknife cookbook\fP subcommand is used to interact with cookbooks that are located on the server or the local chef\-repo. +.sp +This subcommand has the following syntax: +.sp +.nf +.ft C +$ knife cookbook [ARGUMENT] (options) +.ft P +.fi +.SH COMMON OPTIONS +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-w\fR, \fB\-\-with\-uri\fR -Show corresponding URIs -. -.P -show a particular part of a \fIcookbook\fR for the specified \fIversion\fR\. \fIpart\fR can be one of: -. -.IP "\(bu" 4 -\fIattributes\fR -. -.IP "\(bu" 4 -\fIdefinitions\fR -. -.IP "\(bu" 4 -\fIfiles\fR -. -.IP "\(bu" 4 -\fIlibraries\fR -. -.IP "\(bu" 4 -\fIproviders\fR -. -.IP "\(bu" 4 -\fIrecipes\fR -. -.IP "\(bu" 4 -\fIresources\fR -. -.IP "\(bu" 4 -\fItemplates\fR -. -.IP "" 0 -. -.SH "UPLOAD" -\fBknife cookbook upload [cookbooks\.\.\.]\fR \fI(options)\fR -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-a\fR, \fB\-\-all\fR -upload all cookbooks, rather than just a single cookbook -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB\-o\fR, \fB\-\-cookbook\-path path:path\fR -a colon\-separated path to look for cookbooks in -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -\fB\-d\fR, \fB\-\-upload\-dependencies\fR -Uploads additional cookbooks that this cookbook lists in as dependencies in its metadata\. -. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. .TP -\fB\-E\fR, \fB\-\-environment ENVIRONMENT\fR -An \fIENVIRONMENT\fR to apply the uploaded cookbooks to\. Specifying this option will cause knife to edit the \fIENVIRONMENT\fR to place a strict version constraint on the cookbook version(s) uploaded\. -. +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. .TP -\fB\-\-freeze\fR -Sets the frozen flag on the uploaded cookbook(s) Any future attempt to modify the cookbook without changing the version number will return an error unless \-\-force is specified\. -. +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. .TP -\fB\-\-force\fR -Overrides the frozen flag on a cookbook, allowing you to overwrite a cookbook version that has previously been uploaded with the \-\-freeze option\. -. -.P -Uploads one or more cookbooks from your local cookbook repository(ies) to the Chef Server\. Only files that don\'t yet exist on the server will be uploaded\. -. -.P -As the command parses the name args as 1\.\.n cookbook names: \fBknife cookbook upload COOKBOOK COOKBOOK \.\.\.\fR works for one to many cookbooks\. -. -.SH "DOWNLOAD" -\fBknife cookbook download cookbook [version]\fR \fI(options)\fR -. +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. .TP -\fB\-d\fR, \fB\-\-dir download_directory\fR -the directory to download the cookbook into -. +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. .TP -\fB\-f\fR, \fB\-\-force\fR -overwrite an existing directory with the download -. +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. .TP -\fB\-n\fR, \fB\-\-latest\fR -download the latest version of the cookbook -. -.P -download a cookbook from the chef server\. if no version is specified and only one version exists on the server, that version will be downloaded\. if no version is specified and multiple versions are available on the server, you will be prompted for a version to download\. -. -.SH "DELETE" -\fBknife cookbook delete cookbook [version]\fR \fI(options)\fR -. +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. .TP -\fB\-a\fR, \fB\-\-all\fR -delete all versions -. +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. .TP -\fB\-p\fR, \fB\-\-purge\fR -purge files from backing store\. this will disable any cookbook that contains any of the same files as the cookbook being purged\. -. -.P -delete the specified \fIversion\fR of the named \fIcookbook\fR\. if no version is specified, and only one version exists on the server, that version will be deleted\. if multiple versions are available on the server, you will be prompted for a version to delete\. -. -.SH "BULK DELETE" -\fBknife cookbook bulk delete regex\fR \fI(options)\fR -. +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. .TP -\fB\-p\fR, \fB\-\-purge\fR -purge files from backing store\. this will disable any cookbook that contains any of the same files as the cookbook being purged\. -. -.P -delete cookbooks on the chef server based on a regular expression\. the regular expression (\fIregex\fR) should be in quotes, not in //\'s\. -. -.SH "COOKBOOK CREATE" -\fBknife cookbook create cookbook\fR \fI(options)\fR -. +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. .TP -\fB\-o\fR, \fB\-\-cookbook\-path path\fR -the directory where the cookbook will be created -. +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. .TP -\fB\-r\fR, \fB\-\-readme\-format format\fR -format of the readme file md, mkd, txt, rdoc -. +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. .TP -\fB\-c\fR, \fB\-\-copyright copyright\fR -name of copyright holder -. +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. .TP -\fB\-i\fR, \fB\-\-license license\fR -license for cookbook, apachev2 or none -. +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. .TP -\fB\-e\fR, \fB\-\-email email\fR -email address of cookbook maintainer -. -.P -this is a helper command that creates a new cookbook directory in the \fBcookbook_path\fR\. the following directories and files are created for the named cookbook\. -. -.IP "\(bu" 4 +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.SH BULK DELETE +.sp +The \fBbulk delete\fP argument is used to delete cookbook files that match a pattern defined by a regular expression. The regular expression must be within quotes and not be surrounded by forward slashes (/). +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook bulk delete REGEX (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-p\fP, \fB\-\-purge\fP +Indicates that a cookbook (or cookbook version) will be removed entirely from the server. This action should be used carefully because only one copy of any single file is stored on the server. Consequently, purging a cookbook will disable any other cookbook that references one or more files from a cookbook that has been purged. +.UNINDENT +.sp +\fBExamples\fP +.sp +To bulk delete many cookbooks, use a regular expression to define the pattern: +.sp +.nf +.ft C +$ knife cookbook bulk delete "^[0\-9]{3}$" \-p +.ft P +.fi +.SH CREATE +.sp +The \fBcreate\fP argument is used to create a new cookbook directory on the local machine, including the following directories and files: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 cookbook/attributes -. -.IP "\(bu" 4 +.IP \(bu 2 +cookbook/CHANGELOG.md +.IP \(bu 2 cookbook/definitions -. -.IP "\(bu" 4 +.IP \(bu 2 cookbook/files/default -. -.IP "\(bu" 4 +.IP \(bu 2 cookbook/libraries -. -.IP "\(bu" 4 -cookbook/metadata\.rb -. -.IP "\(bu" 4 +.IP \(bu 2 +cookbook/metadata.rb +.IP \(bu 2 cookbook/providers -. -.IP "\(bu" 4 -cookbook/readme\.md -. -.IP "\(bu" 4 -cookbook/recipes/default\.rb -. -.IP "\(bu" 4 +.IP \(bu 2 +cookbook/README.md (or .rdoc) +.IP \(bu 2 +cookbook/recipes/default.rb +.IP \(bu 2 cookbook/resources -. -.IP "\(bu" 4 +.IP \(bu 2 cookbook/templates/default -. -.IP "" 0 -. -.P -supported readme formats are \'md\' (default), \'mkd\', \'txt\', \'rdoc\'\. the readme file will be written with the specified extension and a set of helpful starting headers\. -. -.P -specify \fB\-c\fR or \fB\-\-copyright\fR with the name of the copyright holder as your name or your company/organization name in a quoted string\. if this value is not specified an all\-caps string \fByour_company_name\fR is used which can be easily changed with find/replace\. -. -.P -specify \fB\-i\fR or \fB\-\-license\fR with the license that the cookbook is distributed under for sharing with other people or posting to the opscode cookbooks site\. be aware of the licenses of files you put inside the cookbook and follow any restrictions they describe\. when using \fBnone\fR (default) or \fBapachev2\fR, comment header text and metadata file are pre\-filled\. the \fBnone\fR license will be treated as non\-redistributable\. -. -.P -specify \fB\-e\fR or \fB\-\-email\fR with the email address of the cookbook\'s maintainer\. if this value is not specified, an all\-caps string \fByour_email\fR is used which can easily be changed with find/replace\. -. -.P -the cookbook copyright, license, email and readme_format settings can be filled in the \fBknife\.rb\fR, for example with default values: -. -.IP "" 4 -. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +After the cookbook is created, it can be uploaded to the server using the \fBknife upload\fP argument. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp .nf - -cookbook_copyright "your_company_name" -cookbook_license "none" -cookbook_email "your_email" -readme_format "md" -. +.ft C +$ knife cookbook create COOKBOOK_NAME (options) +.ft P .fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-C COPYRIGHT_HOLDER\fP, \fB\-\-copyright COPYRIGHT_HOLDER\fP +The name of the copyright holder. This option will place a copyright notice that contains the name of the copyright holder in each of the pre\-created files. If this option is not specified, a copyright name of "your_company_name" will be used instead; it can be easily modified later. +.TP +.B \fB\-I LICENSE\fP, \fB\-\-license LICENSE\fP +The type of license under which a cookbook is distributed: \fBapachev2\fP, \fBgplv2\fP, \fBgplv3\fP, \fBmit\fP, or \fBnone\fP (default). This option will place the appropriate license notice in the pre\-created files. Be aware of the licenses for files inside of a cookbook and be sure to follow any restrictions they describe. +.TP +.B \fB\-m EMAIL\fP, \fB\-\-email EMAIL\fP +The email address for the individual who maintains the cookbook. This option will place an email address in each of the pre\-created files. If this option is not specified, an email name of "your_email" will be used instead; it can be easily modified later. +.TP +.B \fB\-o PATH\fP, \fB\-\-cookbook\-path PATH\fP +The directory in which cookbook are created. This can be a colon\-separated path. +.TP +.B \fB\-r FORMAT\fP, \fB\-\-readme\-format FORMAT\fP +The document format of the readme file: \fBmd\fP (markdown) and \fBrdoc\fP (Ruby docs). +.UNINDENT +.sp +\fBExamples\fP +.sp +To create a cookbook named "my_cookbook" with copyright, email, license, and readme format options specified, enter: +.sp +.nf +.ft C +$ knife cookbook create my_cookbook \-C "My Name" \-m "my@email.com" \-I apachev2 \-r md +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +** Creating cookbook my_cookbook +** Creating README for cookbook: my_cookbook +** Creating metadata for cookbook: my_cookbook +.ft P +.fi +.SH DELETE +.sp +The \fBdelete\fP argument is used to delete a specified cookbook or cookbook version on the server (and not locally). +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook delete COOKBOOK_NAME [COOKBOOK_VERSION] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-all\fP +Indicates that a cookbook and every version of that cookbook will be deleted. +.TP +.B \fBCOOKBOOK_VERSION\fP +The version of a cookbook to be deleted. If a cookbook has only one version, this option does not need to be specified. If a cookbook has more than one version and this option is not specified, Knife will prompt for a version. +.TP +.B \fB\-p\fP, \fB\-\-purge\fP +Indicates that a cookbook (or cookbook version) will be removed entirely from the server. This action should be used carefully because only one copy of any single file is stored on the server. Consequently, purging a cookbook will disable any other cookbook that references one or more files from a cookbook that has been purged. +.UNINDENT +.sp +\fBExamples\fP +.sp +To delete version "0.8" from a cookbook named "smartmon", enter: +.sp +.nf +.ft C +$ knife cookbook delete smartmon 0.8 +.ft P +.fi +.sp +Type \fBY\fP to confirm a deletion. +.SH DOWNLOAD +.sp +The \fBdownload\fP argument is used to download a cookbook from the server to the current working directory. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook download COOKBOOK_NAME [COOKBOOK_VERSION] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-d DOWNLOAD_DIRECTORY\fP, \fB\-\-dir DOWNLOAD_DIRECTORY\fP +The directory into which a cookbook will be downloaded. +.TP +.B \fB\-f\fP, \fB\-\-force\fP +Indicates that an existing directory will be overwritten. +.TP +.B \fB\-N\fP, \fB\-\-latest\fP +Indicates that the most recent version of a cookbook will be downloaded. +.UNINDENT +.sp +\fBExamples\fP +.sp +To download a cookbook named "smartmon", enter: +.sp +.nf +.ft C +$ knife cookbook download smartmon +.ft P +.fi +.SH LIST +.sp +The \fBlist\fP argument is used to view a list of cookbooks that are currently available on the server. The list will contain only the most recent version for each cookbook by default. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook list (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-all\fP +Indicates that all available versions of each cookbook will be returned. +.TP +.B \fB\-w\fP, \fB\-\-with\-uri\fP +Indicates that the corresponding URIs will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +To view a list of cookbooks: +.sp +.nf +.ft C +$ knife cookbook list +.ft P +.fi +.SH METADATA +.sp +The \fBmetadata\fP argument is used to generate the metadata for one or more cookbooks. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook metadata (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-all\fP +Indicates that metadata should be generated for all cookbooks, and not just for a specified cookbook. +.TP +.B \fB\-o PATH:PATH\fP, \fB\-\-cookbook\-path PATH:PATH\fP +The directory in which cookbook are created. This can be a colon\-separated path. +.UNINDENT +.sp +\fBExamples\fP +.sp +To generate metadata for all cookbooks: +.sp +.nf +.ft C +$ knife cookbook metadata \-a +.ft P +.fi +.SH METADATA FROM FILE +.sp +The \fBmetadata from file\fP argument is used to load the metadata for a cookbook from a file. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook metadata from file FILE +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To view cookbook metadata from a JSON file: +.sp +.nf +.ft C +$ knife cookbook metadta from file /path/to/file +.ft P +.fi +.SH SHOW +.sp +The \fBshow\fP argument is used to view information about a cookbook, parts of a cookbook (attributes, definitions, files, libraries, providers, recipes, resources, and templates), or a file that is associated with a cookbook (including attributes such as checksum or specificity). +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook show COOKBOOK_NAME [COOKBOOK_VERSION] [PART...] [FILE_NAME] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fBCOOKBOOK_VERSION\fP +The version of a cookbook to be shown. If a cookbook has only one version, this option does not need to be specified. If a cookbook has more than one version and this option is not specified, a list of cookbook versions will be returned. +.TP +.B \fB\-f FQDN\fP, \fB\-\-fqdn FQDN\fP +The FQDN of the host. +.TP +.B \fBFILE_NAME\fP +The name of a file that is associated with a cookbook. +.TP +.B \fB\-p PLATFORM\fP, \fB\-\-platform PLATFORM\fP +The platform for which a cookbook is designed. +.TP +.B \fBPART\fP +The part of the cookbook to show: \fBattributes\fP, \fBdefinitions\fP, \fBfiles\fP, \fBlibraries\fP, \fBproviders\fP, \fBrecipes\fP, \fBresources\fP, or \fBtemplates\fP. More than one part can be specified. +.TP +.B \fB\-V PLATFORM_VERSION\fP, \fB\-\-platform\-version PLATFORM_VERSION\fP +The version of the platform. +.TP +.B \fB\-w\fP, \fB\-\-with\-uri\fP +Indicates that the corresponding URIs will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +To get the list of available versions of a cookbook named "getting\-started", enter: +.sp +.nf +.ft C +$ knife cookbook show getting\-started +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +getting\-started 0.3.0 0.2.0 +.ft P +.fi +.sp +To show a list of data about a cookbook using the name of the cookbook and the version, enter: +.sp +.nf +.ft C +$ knife cookbook show getting\-started 0.3.0 +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +attributes: + checksum: fa0fc4abf3f6787aeb5c3c5c35de667c + name: default.rb + path: attributes/default.rb + specificity: default + url: https://somelongurlhere.com +chef_type: cookbook_version +cookbook_name: getting\-started +definitions: [] +files: [] +frozen?: false +json_class: Chef::CookbookVersion +libraries: [] +.ft P +.fi +.sp +To only view data about "templates", enter: +.sp +.nf +.ft C +$ knife cookbook show getting\-started 0.3.0 templates +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +checksum: a29d6f254577b830091f140c3a78b1fe +name: chef\-getting\-started.txt.erb +path: templates/default/chef\-getting\-started.txt.erb +specificity: default +url: https://someurlhere.com +.ft P +.fi +.sp +To view information in JSON format, use the \fB\-F\fP common option as part of the command like this: +.sp +.nf +.ft C +$ knife role show devops \-F json +.ft P +.fi +.sp +Other formats available include \fBtext\fP, \fByaml\fP, and \fBpp\fP. +.SH TEST +.sp +The \fBtest\fP argument is used to test a cookbook for syntax errors. This argument uses Ruby syntax checking to verify every file in a cookbook that ends in .rb and erb. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook test COOKBOOK_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-all\fP +Indicates that all cookbooks will be tested. +.TP +.B \fB\-o PATH:PATH\fP, \fB\-\-cookbook\-path PATH:PATH\fP +The directory in which cookbook are created. This can be a colon\-separated path. +.UNINDENT +.sp +\fBExamples\fP +.sp +To test a cookbook named "getting\-started", enter: +.sp +.nf +.ft C +$ knife cookbook test getting\-started +.ft P +.fi +.SH UPLOAD +.sp +The \fBupload\fP argument is used to upload one or more cookbooks (and any files that are associated with those cookbooks) from a local repository to the server. Only files that do not already exist on the server will be uploaded. +.IP Note +Use a chefignore file to prevent the upload of specific files and file types, such as temporary files or files placed in folders by version control systems. The chefignore file must be located in the root of the cookbook repository and must use rules similar to filename globbing (as defined by the Ruby \fBFile.fnmatch\fP syntax). +.RE +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife cookbook upload [COOKBOOK_NAME...] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-all\fP +Indicates that all cookbooks will be uploaded. +.TP +.B \fB\-d\fP, \fB\-\-include\-dependencies\fP +Indicates that when a cookbook has a dependency on one (or more) cookbooks, those cookbooks will also be uploaded. +.TP +.B \fB\-\-force\fP +Indicates that a cookbook should be updated even if the \fB\-\-freeze\fP flag has been set. +.TP +.B \fB\-\-freeze\fP +Indicates that a cookbook cannot be modified; any changes to this cookbook must be included as a new version. Only the \fB\-\-force\fP option can override this setting. +.TP +.B \fB\-o PATH:PATH\fP, \fB\-\-cookbook\-path PATH:PATH\fP +The directory in which cookbook are created. This can be a colon\-separated path. +.UNINDENT +.sp +\fBExamples\fP +.sp +To upload a cookbook named "getting\-started": +.sp +.nf +.ft C +$ knife cookbook upload getting\-started +.ft P +.fi +.sp +To upload a cookbook, and then prevent other users from being able to make changes to it, enter: +.sp +.nf +.ft C +$ knife cookbook upload redis \-\-freeze +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +Uploading redis... +Upload completed +.ft P +.fi +.sp +If a cookbook is frozen and the \fB\-\-force\fP option is not specified, Knife will return an error message similar to the following: +.sp +.nf +.ft C +Uploading redis... +ERROR: Version 0.1.6 of cookbook redis is frozen. Use \-\-force to override. +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.IP "" 0 -. -.SH "METADATA" -\fBknife cookbook metadata cookbook\fR \fI(options)\fR -. -.TP -\fB\-a\fR, \fB\-\-all\fR -generate metadata for all cookbooks, rather than just a single cookbook -. -.TP -\fB\-o\fR, \fB\-\-cookbook\-path path:path\fR -a colon\-separated path to look for cookbooks in -. -.P -generate cookbook metadata for the named \fIcookbook\fR\. the \fIpath\fR used here specifies where the cookbooks directory is located and corresponds to the \fBcookbook_path\fR configuration option\. -. -.SH "METADATA FROM FILE" -\fBknife cookbook metadata from file\fR \fI(options)\fR -. -.P -load the cookbook metadata from a specified file\. -. -.SH "TEST" -\fBknife cookbook test [cookbooks\.\.\.]\fR \fI(options)\fR -. -.TP -\fB\-a\fR, \fB\-\-all\fR -test all cookbooks, rather than just a single cookbook -. -.TP -\fB\-o\fR, \fB\-\-cookbook\-path path:path\fR -a colon\-separated path to look for cookbooks in -. -.P -test the specified cookbooks for syntax errors\. this uses the built\-in ruby syntax checking option for files in the cookbook ending in \fB\.rb\fR, and the erb syntax check for files ending in \fB\.erb\fR (templates)\. -. -.SH "RECIPE LIST" -\fBknife recipe list [PATTERN]\fR -. -.P -List available recipes from the server\. Specify \fIPATTERN\fR as a regular expression to limit the results\. -. -.SH "DESCRIPTION" -Cookbooks are the fundamental unit of distribution in Chef\. They encapsulate all recipes of resources and assets used to configure a particular aspect of the infrastructure\. The following sub\-commands can be used to manipulate the cookbooks stored on the Chef Server\. -. -.P -On disk, cookbooks are directories with a defined structure\. The following directories may appear within a cookbook: -. -.TP -COOKBOOK/attributes/ -Ruby files that define default parameters to be used in recipes -. -.TP -COOKBOOK/definitions/ -Ruby files that contain \fIresource definitions\fR -. -.TP -COOKBOOK/files/SPECIFICITY -Files of arbitrary type\. These files may be downloaded by chef\-client(8) when configuring a host\. -. -.TP -COOKBOOK/libraries/ -Ruby files that contain library code needed for recipes -. -.TP -COOKBOOK/providers/ -Ruby files that contain Lightweight Provider definitions -. -.TP -COOKBOOK/recipes/ -Ruby files that use Chef\'s recipe DSL to describe the desired configuration of a system -. -.TP -COOKBOOK/resources/ -Ruby files that contain Lightweight Resource definitions -. -.TP -COOKBOOK/templates/SPECIFICITY -ERuby (ERb) template files\. These are referenced by \fIrecipes\fR and evaluated to dynamically generate configuration files\. -. -.P -\fBSPECIFICITY\fR is a feature of \fIfiles\fR and \fItemplates\fR that allow you to specify alternate files to be used on a specific OS platform or host\. The default specificity setting is \fIdefault\fR, that is files in \fBCOOKBOOK/files/default\fR will be used when a more specific copy is not available\. Further documentation for this feature is available on the Chef wiki: \fIhttp://wiki\.opscode\.com/display/chef/File+Distribution#FileDistribution\-FileSpecificity\fR -. -.P -Cookbooks also contain a metadata file that defines various properties of the cookbook\. The most important of these are the \fIversion\fR and the \fIdependencies\fR\. The \fIversion\fR is used in combination with environments to select which copy of a given cookbook is distributed to a node\. The \fIdependencies\fR are used by the server to determine which additional cookbooks must be distributed to a given host when it requires a cookbook\. -. -.SH "SEE ALSO" -\fBknife\-environment(1)\fR \fBknife\-cookbook\-site(1)\fR \fIhttp://wiki\.opscode\.com/display/chef/Cookbooks\fR \fIhttp://wiki\.opscode\.com/display/chef/Metadata\fR -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. -. -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-data-bag.1 b/distro/common/man/man1/knife-data-bag.1 index 0f1c0cc0fd..df44979710 100644 --- a/distro/common/man/man1/knife-data-bag.1 +++ b/distro/common/man/man1/knife-data-bag.1 @@ -1,123 +1,488 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "KNIFE\-DATA\-BAG" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" -. -.SH "NAME" -\fBknife\-data\-bag\fR \- Store arbitrary data on a Chef Server -. -.SH "SYNOPSIS" -\fBknife\fR \fBdata bag\fR \fIsub\-command\fR \fI(options)\fR -. -.SH "DESCRIPTION" -Data bags are stores of arbitrary JSON data\. Each data bag is a collection that may contain many items\. Data Bag Items are indexed by the Chef Server and can be searched via \fBknife\-search\fR(1)\. -. -.P -Data bags are available to all nodes configured by \fBchef\-client\fR(8), and are therefore a convenient mechanism to store global information, such as lists of administrative accounts that should be configured on all hosts\. -. -.SH "DATA BAG SUB\-COMMANDS" -. -.SH "CREATE" -\fBknife data bag create\fR \fIbag name\fR [item id] \fI(options)\fR -. +.TH "KNIFE-DATA-BAG" "1" "Chef 11.8" "" "knife data bag" +.SH NAME +knife-data-bag \- The man page for the knife data bag subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +A data bag is a global variable that is stored as JSON data and is accessible from a server. A data bag is indexed for searching and can be loaded by a recipe or accessed during a search. The contents of a data bag can vary, but they often include sensitive information (such as database passwords). +.sp +The contents of a data bag can be encrypted using \fI\%shared secret encryption\fP. This allows a data bag to store confidential information (such as a database password) or to be managed in a source control system (without plain\-text data appearing in revision history). +.sp +The \fBknife data bag\fP subcommand is used to manage arbitrary stores of globally available JSON data. +.sp +This subcommand has the following syntax: +.sp +.nf +.ft C +$ knife data bag [ARGUMENT] (options) +.ft P +.fi +.SH COMMON OPTIONS +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-s\fR, \fB\-\-secret SECRET\fR -A secret key used to encrypt the data bag item\. See \fBencryption support\fR below\. -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-\-secret\-file SECRET_FILE\fR -The path to a file containing the secret key to be used to encrypt the data bag item\. -. -.P -If \fIitem id\fR is given, creates a new, empty data bag item and opens it for editing in your editor\. The data bag will be created if it does not exist\. -. -.P -If \fIitem id\fR is not given, the data bag will be created\. -. -.SH "DELETE" -\fBknife data bag delete\fR \fIbag name\fR [item id] \fI(options)\fR -. -.P -Delete a data bag, or an item from a data bag\. -. -.SH "EDIT" -\fBknife data bag edit\fR \fIbag name\fR \fIitem id\fR \fI(options)\fR -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB\-s\fR, \fB\-\-secret SECRET\fR -A secret key used to encrypt the data bag item\. See \fBencryption support\fR below\. -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -\fB\-\-secret\-file SECRET_FILE\fR -The path to a file containing the secret key to be used to encrypt the data bag item\. -. -.P -Edit an item in a data bag\. -. -.SH "FROM FILE" -\fBknife data bag from file\fR \fIbag name\fR \fIfile\fR \fI(options)\fR -. -.P -\fBknife data bag from file\fR \fIbag name\fR \fIfile1\fR \fIfile2\fR \fIfile3\fR \fI(options)\fR -. -.P -\fBknife data bag from file\fR \fIbag name\fR \fIfolder\fR \fI(options)\fR -. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. .TP -\fB\-s\fR, \fB\-\-secret SECRET\fR -A secret key used to encrypt the data bag item\. See \fBencryption support\fR below\. -. +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. .TP -\fB\-\-secret\-file SECRET_FILE\fR -The path to a file containing the secret key to be used to encrypt the data bag item\. -. -.P -Load a data bag item from a JSON file\. If \fIfile\fR is a relative or absolute path to the file, that file will be used\. Otherwise, the \fIfile\fR parameter is treated as the base name of a data bag file in a Chef repository, and \fBknife\fR will search for the file in \fB\./data_bags/bag_name/file\fR\. For example \fBknife data bag from file users dan\.json\fR would attempt to load the file \fB\./data_bags/users/dan\.json\fR\. -. -.SH "LIST" -\fBknife data bag list\fR \fI(options)\fR -. +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. .TP -\fB\-w\fR, \fB\-\-with\-uri\fR -Show corresponding URIs -. -.P -Lists the data bags that exist on the Chef Server\. -. -.SH "SHOW" -\fBknife data bag show BAG [ITEM]\fR \fI(options)\fR -. +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. .TP -\fB\-s\fR, \fB\-\-secret SECRET\fR -A secret key used to encrypt the data bag item\. See \fBencryption support\fR below\. -. +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. .TP -\fB\-\-secret\-file SECRET_FILE\fR -The path to a file containing the secret key to be used to encrypt the data bag item\. -. -.P -Show a specific data bag or an item in a data bag\. The output will be formatted according to the \-\-format option\. -. -.SH "ENCRYPTION SUPPORT" -Data Bag Items may be encrypted to keep their contents secret\. This may be desireable when storing sensitive information such as database passwords, API keys, etc\. -. -.P -Data Bag Item encryption uses the AES\-256 CBC symmetric key algorithm\. -. -.P -\fBCAVEATS:\fR Keys are not encrypted; only values are encrypted\. The "id" of a Data Bag Item is not encrypted, since it is used by Chef Server to store the item in its database\. For example, given the following data bag item: {"id": "important_passwords", "secret_password": "opensesame"} The key "secret_password" will be visible to an evesdropper, but the value "opensesame" will be protected\. Both the key "id" and its value "important_passwords" will be visible to an evesdropper\. -. -.P -Chef Server does not provide a secure mechanism for distributing encryption keys\. -. -.SH "SEE ALSO" -\fBknife\-search\fR(1) -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.SH CREATE +.sp +The \fBcreate\fP argument is used to add a data bag to the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife data bag create DATA_BAG_NAME [DATA_BAG_ITEM] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fBDATA_BAG_ITEM\fP +The name of a specific item within a data bag. +.TP +.B \fB\-\-secret SECRET\fP +The encryption key that is used for values contained within a data bag. +.TP +.B \fB\-\-secret\-file FILE\fP +The path to the file that contains the encryption key. +.UNINDENT +.IP Note +For encrypted data bag items, use \fIeither\fP \fB\-\-secret\fP or \fB\-\-secret\-file\fP, not both. +.RE +.sp +\fBExamples\fP +.sp +To create a data bag named "admins", enter: +.sp +.nf +.ft C +$ knife data bag create admins +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +Created data_bag[admins] +.ft P +.fi +.SH DELETE +.sp +The \fBdelete\fP argument is used to delete a data bag or a data bag item from a server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife data bag delete DATA_BAG_NAME [DATA_BAG_ITEM] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fBDATA_BAG_ITEM\fP +The name of a specific item within a data bag. +.UNINDENT +.sp +\fBExamples\fP +.sp +To a data bag named "admins", enter: +.sp +.nf +.ft C +$ knife data bag delete admins +.ft P +.fi +.sp +To delete an item named "charlie", enter: +.sp +.nf +.ft C +$ knife data bag delete admins charlie +.ft P +.fi +.sp +Type \fBY\fP to confirm a deletion. +.SH EDIT +.sp +The \fBedit\fP argument is used to edit the data contained in a data bag. If encryption is being used, the data bag will be decrypted, the data will be made available in the $EDITOR, and then encrypted again before saving it to the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife data bag edit DATA_BAG_NAME [DATA_BAG_ITEM] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fBDATA_BAG_ITEM\fP +The name of a specific item within a data bag. +.TP +.B \fB\-\-secret SECRET\fP +The encryption key that is used for values contained within a data bag. +.TP +.B \fB\-\-secret\-file FILE\fP +The path to the file that contains the encryption key. +.UNINDENT +.IP Note +For encrypted data bag items, use \fIeither\fP \fB\-\-secret\fP or \fB\-\-secret\-file\fP, not both. +.RE +.sp +\fBExamples\fP +.sp +To edit the contents of a data bag, enter: +.sp +.nf +.ft C +$ knife data bag edit admins +.ft P +.fi +.sp +To edit an item named "charlie" that is contained in a data bag named "admins", enter: +.sp +.nf +.ft C +$ knife data bag edit admins charlie +.ft P +.fi +.sp +to open the $EDITOR. Once opened, you can update the data before saving it to the server. For example, by changing: +.sp +.nf +.ft C +{ + "id": "charlie" +} +.ft P +.fi +.sp +to: +.sp +.nf +.ft C +{ + "id": "charlie", + "uid": 1005, + "gid":"ops", + "shell":"/bin/zsh", + "comment":"Crazy Charlie" +} +.ft P +.fi +.SH FROM FILE +.sp +The \fBfrom file\fP argument is used to create a data bag on the server from a file. The path to the data bag file must specify one of the following: +.INDENT 0.0 +.IP \(bu 2 +the name of a data bag +.IP \(bu 2 +a relative or absolute path to a file +.UNINDENT +.sp +If the name of a data bag is specified, Knife will search for the data bag in \fB./data_bags/bag_name/file\fP. Once opened, the JSON file should be a hash that contains at least an ID key which represents the name of the data bag item. +.IP Warning +A chef\-client must be version 11.6 (or higher) when using the \fBknife data bag from file\fP argument with the Enterprise Chef or Open Source Chef version 11 servers. +.RE +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife data bag from file DATA_BAG_NAME_or_PATH +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-all\fP +Indicates that all data bags found at the specified path will be uploaded. +.TP +.B \fB\-\-secret SECRET\fP +The encryption key that is used for values contained within a data bag. +.TP +.B \fB\-\-secret\-file FILE\fP +The path to the file that contains the encryption key. +.UNINDENT +.IP Note +For encrypted data bag items, use \fIeither\fP \fB\-\-secret\fP or \fB\-\-secret\-file\fP, not both. +.RE +.sp +\fBExamples\fP +.sp +To create a data bag on the server from a file: +.sp +.nf +.ft C +$ knife data bag from file "path to JSON file" +.ft P +.fi +.sp +To create a data bag named "devops_data" that contains encrypted data, enter: +.sp +.nf +.ft C +$ knife data bag from file devops_data \-\-secret\-file "path to decryption file" +.ft P +.fi +.SH LIST +.sp +The \fBlist\fP argument is used to view a list of data bags that are currently available on the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife data bag list +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-w\fP, \fB\-\-with\-uri\fP +Indicates that the corresponding URIs will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +For example, to view a list of data bags on the server, enter: +.sp +.nf +.ft C +$ knife data bag list +.ft P +.fi +.SH SHOW +.sp +The \fBshow\fP argument is used to view the contents of a data bag. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife data bag show DATA_BAG_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fBDATA_BAG_ITEM\fP +The name of a specific item within a data bag. +.TP +.B \fB\-\-secret SECRET\fP +The encryption key that is used for values contained within a data bag. +.TP +.B \fB\-\-secret\-file FILE\fP +The path to the file that contains the encryption key. +.UNINDENT +.IP Note +For encrypted data bag items, use \fIeither\fP \fB\-\-secret\fP or \fB\-\-secret\-file\fP, not both. +.RE +.sp +\fBExamples\fP +.sp +To show the contents of a data bag, enter: +.sp +.nf +.ft C +$ knife data bag show admins +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +charlie +.ft P +.fi +.sp +To show the contents of a specific item within data bag, enter: +.sp +.nf +.ft C +$ knife data bag show admins charlie +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +comment: Crazy Charlie +gid: ops +id: charlie +shell: /bin/zsh +uid: 1005 +.ft P +.fi +.sp +To show the contents of a data bag named "passwords" with an item that contains encrypted data named "mysql", enter: +.sp +.nf +.ft C +$ knife data bag show passwords mysql +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +## sample: +{ + "id": "mysql", + "pass": "trywgFA6R70NO28PNhMpGhEvKBZuxouemnbnAUQsUyo=\en", + "user": "e/p+8WJYVHY9fHcEgAAReg==\en" +} +.ft P +.fi +.sp +To show the decrypted contents of the same data bag, enter: +.sp +.nf +.ft C +$ knife data bag show \-\-secret\-file /path/to/decryption/file passwords mysql +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +## sample: +{ + "id": "mysql", + "pass": "thesecret123", + "user": "fred" +} +.ft P +.fi +.sp +To view information in JSON format, use the \fB\-F\fP common option as part of the command like this: +.sp +.nf +.ft C +$ knife data bag show admins \-F json +.ft P +.fi +.sp +Other formats available include \fBtext\fP, \fByaml\fP, and \fBpp\fP. +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.SH "CHEF" -Knife is distributed with Chef\. http://wiki\.opscode\.com/display/chef/Home diff --git a/distro/common/man/man1/knife-delete.1 b/distro/common/man/man1/knife-delete.1 new file mode 100644 index 0000000000..9b9bb51dce --- /dev/null +++ b/distro/common/man/man1/knife-delete.1 @@ -0,0 +1,134 @@ +.TH "KNIFE-DELETE" "1" "Chef 11.8" "" "knife delete" +.SH NAME +knife-delete \- The man page for the knife delete subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife delete\fP subcommand is used to delete an object from a server. This subcommand works similar to \fBknife cookbook delete\fP, \fBknife data bag delete\fP, \fBknife environment delete\fP, \fBknife node delete\fP, and \fBknife role delete\fP, but with a single verb (and a single action). +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife delete [PATTERN...] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-both\fP +Indicates that both local and remote copies of an object should be deleted. Default: \fBfalse\fP. +.TP +.B \fB\-\-chef\-repo\-path PATH\fP +The path to the chef\-repo. This setting will override the default path to the chef\-repo. Default: same as specified by \fBchef_repo_path\fP in config.rb. +.TP +.B \fB\-\-concurrency\fP +The number of allowed concurrent connections. Default: \fB10\fP. +.TP +.B \fB\-\-local\fP +Indicates that only the local copy of an object should be deleted. (The remote copy will not be deleted.) Default: \fBfalse\fP. +.TP +.B \fB\-r\fP, \fB\-\-[no\-]recurse\fP +Use \fB\-\-recurse\fP to delete directories recursively. Default: \fB\-\-no\-recurse\fP. +.TP +.B \fB\-\-repo\-mode MODE\fP +The layout of the local chef\-repo. Possible values: \fBstatic\fP, \fBeverything\fP, or \fBhosted_everything\fP. Use \fBstatic\fP for just roles, environments, cookbooks, and data bags. By default, \fBeverything\fP and \fBhosted_everything\fP are dynamically selected depending on the server type. Default: \fBeverything\fP / \fBhosted_everything\fP. +.UNINDENT +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-deps.1 b/distro/common/man/man1/knife-deps.1 new file mode 100644 index 0000000000..8879ed536c --- /dev/null +++ b/distro/common/man/man1/knife-deps.1 @@ -0,0 +1,221 @@ +.TH "KNIFE-DEPS" "1" "Chef 11.8" "" "knife deps" +.SH NAME +knife-deps \- The man page for the knife deps subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife deps\fP subcommand is used to identify dependencies for a node, role, or cookbook. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife deps (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-chef\-repo\-path PATH\fP +The path to the chef\-repo. This setting will override the default path to the chef\-repo. Default: same as specified by \fBchef_repo_path\fP in config.rb. +.TP +.B \fB\-\-concurrency\fP +The number of allowed concurrent connections. Default: \fB10\fP. +.TP +.B \fB\-\-[no\-]recurse\fP +Use \fB\-\-recurse\fP to list dependencies recursively. This option can only be used when \fB\-\-tree\fP is set to \fBtrue\fP. Default: \fB\-\-no\-recurse\fP. +.TP +.B \fB\-\-remote\fP +Indicates that dependencies will be determined from objects located on the server instead of the local chef\-repo. Default: \fBfalse\fP. +.TP +.B \fB\-\-repo\-mode MODE\fP +The layout of the local chef\-repo. Possible values: \fBstatic\fP, \fBeverything\fP, or \fBhosted_everything\fP. Use \fBstatic\fP for just roles, environments, cookbooks, and data bags. By default, \fBeverything\fP and \fBhosted_everything\fP are dynamically selected depending on the server type. Default: \fBeverything\fP / \fBhosted_everything\fP. +.TP +.B \fB\-\-tree\fP +Indicates that dependencies are shown in a visual tree structure (including duplicates, if they exist). Default: \fBfalse\fP. +.UNINDENT +.sp +\fBExamples\fP +.sp +To find the dependencies for a node: +.sp +.nf +.ft C +$ knife deps nodes/node_name.json +.ft P +.fi +.sp +To find the dependencies for a role: +.sp +.nf +.ft C +$ knife deps roles/role_name.json +.ft P +.fi +.sp +To find the dependencies for a cookbook: +.sp +.nf +.ft C +$ knife deps cookbooks/cookbook_name.json +.ft P +.fi +.sp +To find the dependencies for an environment: +.sp +.nf +.ft C +$ knife deps environments/environment_name.json +.ft P +.fi +.sp +To find the dependencies for a combination of nodes, cookbooks, roles, and/or environments: +.sp +.nf +.ft C +$ knife deps cookbooks/git.json cookbooks/github.json roles/base.json environments/desert.json nodes/mynode.json +.ft P +.fi +.sp +To use a wildcard to return all the child nodes: +.sp +.nf +.ft C +$ knife deps environments/*.json +.ft P +.fi +.sp +Use the \fB\-\-tree\fP option to view the results with structure: +.sp +.nf +.ft C +$ knife deps roles/webserver.json +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +roles/webserver.json + roles/base.json + cookbooks/github + cookbooks/git + cookbooks/users + cookbooks/apache2 +.ft P +.fi +.sp +To pass the output of \fBknife deps\fP to \fBknife upload\fP, do something like the following: +.sp +.nf +.ft C +$ knife upload \(gaknife deps nodes/*.json +.ft P +.fi +.sp +To pass the output of \fBknife deps\fP to \fBknife xargs\fP: +.sp +.nf +.ft C +$ knife deps nodes/*.json | xargs knife upload +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-diff.1 b/distro/common/man/man1/knife-diff.1 new file mode 100644 index 0000000000..cc83401863 --- /dev/null +++ b/distro/common/man/man1/knife-diff.1 @@ -0,0 +1,214 @@ +.TH "KNIFE-DIFF" "1" "Chef 11.8" "" "knife diff" +.SH NAME +knife-diff \- The man page for the knife diff subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife diff\fP subcommand is used to compare the differences between files and directories on the server and in the chef\-repo. For example, to compare files on the server prior to an uploading or downloading files using the \fBknife download\fP and \fBknife upload\fP subcommands, or to ensure that certain files in multiple production environments are the same. This subcommand is similar to the \fBgit diff\fP command that can be used to diff what is in the chef\-repo with what is synced to a git repository. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife diff [PATTERN...] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-chef\-repo\-path PATH\fP +The path to the chef\-repo. This setting will override the default path to the chef\-repo. Default: same as specified by \fBchef_repo_path\fP in config.rb. +.TP +.B \fB\-\-concurrency\fP +The number of allowed concurrent connections. Default: \fB10\fP. +.TP +.B \fB\-\-diff\-filter=[(A|D|M|T)...[*]]\fP +Indicates that files will be selected that have been added (\fBA\fP), deleted (\fBD\fP), modified (\fBM\fP), and/or have had their type changed (\fBT\fP). Any combination of filter characters may be used, including no filter characters. Use \fB*\fP to select all paths if a file matches other criteria in the comparison. Default value: \fBnil\fP. +.TP +.B \fB\-\-name\-only\fP +Indicates that only the names of modified files will be shown. +.TP +.B \fB\-\-name\-status\fP +Indicates that only the names of files with a status of \fBAdded\fP, \fBDeleted\fP, \fBModified\fP, or \fBType Changed\fP will be shown. +.TP +.B \fB\-\-no\-recurse\fP +Use \fB\-\-no\-recurse\fP to disable listing a directory recursively. Default: \fB\-\-recurse\fP. +.TP +.B \fB\-\-repo\-mode MODE\fP +The layout of the local chef\-repo. Possible values: \fBstatic\fP, \fBeverything\fP, or \fBhosted_everything\fP. Use \fBstatic\fP for just roles, environments, cookbooks, and data bags. By default, \fBeverything\fP and \fBhosted_everything\fP are dynamically selected depending on the server type. Default: \fBeverything\fP / \fBhosted_everything\fP. +.UNINDENT +.sp +\fBknife.rb File Settings\fP +.sp +In addition to the default settings in a knife.rb file, there are other subcommand\-specific settings that can be added. When a subcommand is run, Knife will use: +.INDENT 0.0 +.IP 1. 3 +A value passed via the command\-line +.IP 2. 3 +A value contained in the knife.rb file +.IP 3. 3 +The default value +.UNINDENT +.sp +A value passed via the command line will override a value in the knife.rb file; a value in a knife.rb file will override a default value. +.sp +The following \fBknife diff\fP settings can be added to the knife.rb file: +.INDENT 0.0 +.TP +.B \fBknife[:chef_repo_path]\fP +Use to add the \fB\-\-chef\-repo\-path\fP option. +.TP +.B \fBknife[:concurrency]\fP +Use to add the \fB\-\-concurrency\fP option. +.TP +.B \fBknife[:name_only]\fP +Use to add the \fB\-\-name\-only\fP option. +.TP +.B \fBknife[:name_status]\fP +Use to add the \fB\-\-name\-status\fP option. +.TP +.B \fBknife[:recurse]\fP +Use to add the \fB\-\-recurse\fP option. +.TP +.B \fBknife[:repo_mode]\fP +Use to add the \fB\-\-repo\-mode\fP option. +.UNINDENT +.sp +\fBExamples\fP +.sp +To compare the "base.json" role to a "webserver.json" role, enter: +.sp +.nf +.ft C +$ knife diff roles/base.json roles/webserver.json +.ft P +.fi +.sp +To compare the differences between the local chef\-repo and the files that are on the server, enter: +.sp +.nf +.ft C +$ knife diff +.ft P +.fi +.sp +To diff a node named \fBnode\-lb\fP and then only return files that have been added, deleted, modified, or changed, enter: +.sp +.nf +.ft C +$ knife diff \-\-name\-status node\-lb +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +node\-lb/recipes/eip.rb +node\-lb/recipes/heartbeat\-int.rb +node\-lb/templates/default/corpsite.conf.erb +node\-lb/files/default/wildcard.node.com.crt +node\-lb/files/default/wildcard.node.com.crt\-2009 +node\-lb/files/default/wildcard.node.com.key +node\-lb/.gitignore +node\-lb/Rakefile +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-download.1 b/distro/common/man/man1/knife-download.1 new file mode 100644 index 0000000000..71eafe15a0 --- /dev/null +++ b/distro/common/man/man1/knife-download.1 @@ -0,0 +1,222 @@ +.TH "KNIFE-DOWNLOAD" "1" "Chef 11.8" "" "knife download" +.SH NAME +knife-download \- The man page for the knife download subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife download\fP subcommand is used to download roles, cookbooks, environments, nodes, and data bags from the server to the current working directory.. It can be used to back up data on the server, inspect the state of one or more files, or to extract out\-of\-process changes users may have made to files on the server, such as if a user made a change that bypassed version source control. This subcommand is often used in conjunction with \fBknife diff\fP, which can be used to see exactly what changes will be downloaded, and then \fBknife upload\fP, which does the opposite of \fBknife download\fP. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife download [PATTERN...] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-chef\-repo\-path PATH\fP +The path to the chef\-repo. This setting will override the default path to the chef\-repo. Default: same as specified by \fBchef_repo_path\fP in config.rb. +.TP +.B \fB\-\-concurrency\fP +The number of allowed concurrent connections. Default: \fB10\fP. +.TP +.B \fB\-\-force\fP +Use \fB\-\-force\fP to download files even when the file on the hard drive is identical to the object on the server (role, cookbook, etc.). By default, files are compared to see if they have equivalent content, and local files are only overwritten if they are different. Default: \fB\-\-no\-force\fP. +.TP +.B \fB\-n\fP, \fB\-\-dry\-run\fP +Indicates that no action is taken and that results are only printed out. Default: \fBfalse\fP. +.TP +.B \fB\-\-[no\-]diff\fP +Indicates that only new and modified files will be downloaded. Set to \fBfalse\fP to download all files. Default: \fB\-\-diff\fP. +.TP +.B \fB\-\-[no\-]recurse\fP +Use \fB\-\-no\-recurse\fP to disable downloading a directory recursively. Default: \fB\-\-recurse\fP. +.TP +.B \fB\-\-purge\fP +Use \fB\-\-purge\fP to delete local files and directories that do not exist on the server. By default, if a role, cookbook, etc. does not exist on the server, the local file for said role will be left alone and NOT deleted. Default: \fB\-\-no\-purge\fP. +.TP +.B \fB\-\-repo\-mode MODE\fP +The layout of the local chef\-repo. Possible values: \fBstatic\fP, \fBeverything\fP, or \fBhosted_everything\fP. Use \fBstatic\fP for just roles, environments, cookbooks, and data bags. By default, \fBeverything\fP and \fBhosted_everything\fP are dynamically selected depending on the server type. Default: \fBeverything\fP / \fBhosted_everything\fP. +.UNINDENT +.sp +\fBExamples\fP +.sp +To download the entire chef\-repo from the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife download / +.ft P +.fi +.sp +To download the \fBcookbooks/\fP directory from the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife download cookbooks +.ft P +.fi +.sp +or from anywhere in the chef\-repo, enter: +.sp +.nf +.ft C +$ knife download /cookbooks +.ft P +.fi +.sp +To download the \fBenvironments/\fP directory from the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife download environments +.ft P +.fi +.sp +or from anywhere in the chef\-repo, enter: +.sp +.nf +.ft C +$ knife download /environments +.ft P +.fi +.sp +To download an environment named "production" from the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife download environments/production.json +.ft P +.fi +.sp +or from the \fBenvironments/\fP directory, enter: +.sp +.nf +.ft C +$ knife download production.json +.ft P +.fi +.sp +To download the \fBroles/\fP directory from the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife download roles +.ft P +.fi +.sp +or from anywhere in the chef\-repo, enter: +.sp +.nf +.ft C +$ knife download /roles +.ft P +.fi +.sp +To download all cookbooks that start with "apache" and belong to the "webserver" role, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife download cookbooks/apache\e* roles/webserver.json +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-edit.1 b/distro/common/man/man1/knife-edit.1 new file mode 100644 index 0000000000..e1a0a45424 --- /dev/null +++ b/distro/common/man/man1/knife-edit.1 @@ -0,0 +1,128 @@ +.TH "KNIFE-EDIT" "1" "Chef 11.8" "" "knife edit" +.SH NAME +knife-edit \- The man page for the knife edit subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife edit\fP subcommand is used to edit objects on the server. This subcommand works similar to \fBknife cookbook edit\fP, \fBknife data bag edit\fP, \fBknife environment edit\fP, \fBknife node edit\fP, and \fBknife role edit\fP, but with a single verb (and a single action). +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife edit (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-chef\-repo\-path PATH\fP +The path to the chef\-repo. This setting will override the default path to the chef\-repo. Default: same as specified by \fBchef_repo_path\fP in config.rb. +.TP +.B \fB\-\-concurrency\fP +The number of allowed concurrent connections. Default: \fB10\fP. +.TP +.B \fB\-\-local\fP +Use to show files in the local chef\-repo instead of a remote location. Default: \fBfalse\fP. +.TP +.B \fB\-\-repo\-mode MODE\fP +The layout of the local chef\-repo. Possible values: \fBstatic\fP, \fBeverything\fP, or \fBhosted_everything\fP. Use \fBstatic\fP for just roles, environments, cookbooks, and data bags. By default, \fBeverything\fP and \fBhosted_everything\fP are dynamically selected depending on the server type. Default: \fBeverything\fP / \fBhosted_everything\fP. +.UNINDENT +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-environment.1 b/distro/common/man/man1/knife-environment.1 index dbb42a9c9e..ed272e3892 100644 --- a/distro/common/man/man1/knife-environment.1 +++ b/distro/common/man/man1/knife-environment.1 @@ -1,168 +1,326 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "KNIFE\-ENVIRONMENT" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" -. -.SH "NAME" -\fBknife\-environment\fR \- Define cookbook policies for the environments in your infrastructure -. -.SH "SYNOPSIS" -\fBknife\fR \fBenvironment\fR \fIsub\-command\fR \fI(options)\fR -. -.SH "SUBCOMMANDS" -Environment subcommands follow a basic create, read, update, delete (CRUD) pattern\. The following subcommands are available: -. -.SH "CREATE" -\fBknife environment create\fR \fIenvironment\fR \fI(options)\fR -. -.TP -\fB\-d\fR, \fB\-\-description DESCRIPTION\fR -The value of the description field\. -. -.P -Create a new environment object on the Chef Server\. The envrionment will be opened in the text editor for editing prior to creation if the \-n option is not present\. -. -.SH "DELETE" -\fBknife environment delete\fR \fIenvironment\fR \fI(options)\fR -. -.P -Destroy an environment on the Chef Server\. A prompt for confirmation will be displayed if the \-y options is not given\. -. -.SH "EDIT" -\fBknife environment edit\fR \fIenvironment\fR \fI(options)\fR -. -.P -Fetch \fIenvironment\fR and display it in the text editor for editing\. The environment will be saved to the Chef Server when the editing session exits\. -. -.SH "FROM FILE" -\fBknife environment from file\fR \fIfile\fR \fI(options)\fR -. -.P -Create or update an environment from the JSON or Ruby format \fIfile\fR\. See \fBformat\fR for the proper format of this file\. -. -.SH "LIST" -\fBknife environment list\fR \fI(options)\fR * \fB\-w\fR, \fB\-\-with\-uri\fR: Show the resource URI for each environment -. -.SH "SHOW" -\fBknife environment show\fR \fIenvironment\fR \fI(options)\fR -. -.SH "DESCRIPTION" -Environments provide a means to apply policies to hosts in your infrastructure based on business function\. For example, you may have a separate copy of your infrastructure called "dev" that runs the latest version of your application and should use the newest versions of your cookbooks when configuring systems, and a production instance of your infrastructure where you wish to update code and cookbooks in a more controlled fashion\. In Chef, this function is implemented with \fIenvironments\fR\. -. -.P -Environments contain two major components: a set of cookbook version constraints and environment attributes\. -. -.SH "SYNTAX" -A cookbook version constraint is comprised of a \fIcookbook name\fR and a \fIversion constraint\fR\. The \fIcookbook name\fR is the name of a cookbook in your system, and the \fIversion constraint\fR is a String describing the version(s) of that cookbook allowed in the environment\. Only one \fIversion constraint\fR is supported for a given \fIcookbook name\fR\. -. -.P -The exact syntax used to define a cookbook version constraint varies depending on whether you use the JSON format or the Ruby format\. In the JSON format, the cookbook version constraints for an environment are represented as a single JSON object, like this: -. -.IP "" 4 -. -.nf - -{"apache2": ">= 1\.5\.0"} -. -.fi -. -.IP "" 0 -. -.P -In the Ruby format, the cookbook version contraints for an environment are represented as a Ruby Hash, like this: -. -.IP "" 4 -. +.TH "KNIFE-ENVIRONMENT" "1" "Chef 11.8" "" "knife environment" +.SH NAME +knife-environment \- The man page for the knife environment subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +An environment is a way to map an organization\(aqs real\-life workflow to what can be configured and managed when using server. Every organization begins with a single environment called the \fB_default\fP environment, which cannot be modified (or deleted). Additional environments can be created to reflect each organization\(aqs patterns and workflow. For example, creating \fBproduction\fP, \fBstaging\fP, \fBtesting\fP, and \fBdevelopment\fP environments. Generally, an environment is also associated with one (or more) cookbook versions. +.sp +The \fBknife environment\fP subcommand is used to manage environments within a single organization on the server. +.sp +This subcommand has the following syntax: +.sp .nf - -{"apache2" => ">= 1\.5\.0"} -. +.ft C +$ knife environment [ARGUMENT] (options) +.ft P .fi -. -.IP "" 0 -. -.P -A \fIversion number\fR is a String comprised of two or three digits separated by a dot (\.) character, or in other words, strings of the form "major\.minor" or "major\.minor\.patch"\. "1\.2" and "1\.2\.3" are examples of valid version numbers\. Version numbers containing more than three digits or alphabetic characters are not supported\. -. -.P -A \fIversion constraint\fR String is composed of an \fIoperator\fR and a \fIversion number\fR\. The following operators are available: -. +.SH COMMON OPTIONS +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB= VERSION\fR -Equality\. Only the exact version specified may be used\. -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB> VERSION\fR -Greater than\. Only versions greater than \fBVERSION\fR may be used\. -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB>= VERSION\fR -Greater than or equal to\. Only versions equal to VERSION or greater may be used\. -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -\fB< VERSION\fR -Less than\. Only versions less than VERSION may be used\. -. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. .TP -\fB<= VERSION\fR -Less than or equal to\. Only versions lesser or equal to VERSION may be used\. -. +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. .TP -\fB~> VERSION\fR -Pessimistic greater than\. Depending on the number of components in the given VERSION, the constraint will be optimistic about future minor or patch revisions only\. For example, \fB~> 1\.1\fR will match any version less than \fB2\.0\fR and greater than or equal to \fB1\.1\.0\fR, whereas \fB~> 2\.0\.5\fR will match any version less than \fB2\.1\.0\fR and greater than or equal to \fB2\.0\.5\fR\. -. -.SH "FORMAT" -The JSON format of an envioronment is as follows: -. -.IP "" 4 -. +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.SH CREATE +.sp +The \fBcreate\fP argument is used to add an environment object to the server. When this argument is run, Knife will open $EDITOR to enable editing of the \fBENVIRONMENT\fP description field (unless a description is specified as part of the command). When finished, Knife will add the environment to the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp .nf - -{ - "name": "dev", - "description": "The development environment", - "cookbook_versions": { - "couchdb": "= 11\.0\.0" - }, - "json_class": "Chef::Environment", - "chef_type": "environment", - "default_attributes": { - "apache2": { "listen_ports": [ "80", "443" ] } - }, - "override_attributes": { - "aws_s3_bucket": "production" - } -} -. +.ft C +$ knife environment create ENVIRONMENT_NAME \-d DESCRIPTION +.ft P .fi -. -.IP "" 0 -. -.P -The Ruby format of an environment is as follows: -. -.IP "" 4 -. +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-d DESCRIPTION\fP, \fB\-\-description DESCRIPTION\fP +The description of the environment. This value will populate the description field for the environment on the server. +.UNINDENT +.sp +\fBExamples\fP +.sp +To create an environment named "dev" with a description of "The development environment.": +.sp +.nf +.ft C +$ knife environment create dev \-d "The development environment." +.ft P +.fi +.SH DELETE +.sp +The \fBdelete\fP argument is used to delete an environment from a server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife environment delete ENVIRONMENT_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To delete an environment named "dev", enter: +.sp +.nf +.ft C +$ knife environment delete dev +.ft P +.fi +.sp +Type \fBY\fP to confirm a deletion. +.SH EDIT +.sp +The \fBedit\fP argument is used to edit the attributes of an environment. When this argument is run, Knife will open $EDITOR to enable editing of \fBENVIRONMENT\fP attributes. When finished, Knife will update the server with those changes. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife environment edit ENVIRONMENT_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To edit an environment named "devops", enter: +.sp +.nf +.ft C +$ knife environment edit devops +.ft P +.fi +.SH FROM FILE +.sp +The \fBfrom file\fP argument is used to add or update an environment using a JSON or Ruby DSL description. It must be run with the \fBcreate\fP or \fBedit\fP arguments. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife environment [create | edit] from file FILE (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-all\fP +Indicates that all environments found at the specified path will be uploaded. +.UNINDENT +.sp +\fBExamples\fP +.sp +To add an environment using data contained in a JSON file: +.sp +.nf +.ft C +$ knife environment create devops from file "path to JSON file" +.ft P +.fi +.sp +or: +.sp +.nf +.ft C +$ knife environment edit devops from file "path to JSON file" +.ft P +.fi +.SH LIST +.sp +The \fBlist\fP argument is used to list all of the environments that are currently available on the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife environment list \-w +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-w\fP, \fB\-\-with\-uri\fP +Indicates that the corresponding URIs will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +To view a list of environments: +.sp +.nf +.ft C +$ knife environment list \-w +.ft P +.fi +.SH SHOW +.sp +The \fBshow\fP argument is used to display information about the specified environment. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife environment show ENVIRONMENT_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To view information about the "dev" environment enter: +.sp .nf +.ft C +$ knife environment show dev +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +% knife environment show dev +chef_type: environment +cookbook_versions: +default_attributes: +description: +json_class: Chef::Environment +name: dev +override_attributes: -name "dev" -description "The development environment" -cookbook_versions "couchdb" => "= 11\.0\.0" -default_attributes "apache2" => { "listen_ports" => [ "80", "443" ] } -override_attributes "aws_s3_bucket" => "production" -. +\e\e +\e\e +\e\e +\e\e +.ft P .fi +.sp +To view information in JSON format, use the \fB\-F\fP common option as part of the command like this: +.sp +.nf +.ft C +$ knife role show devops \-F json +.ft P +.fi +.sp +Other formats available include \fBtext\fP, \fByaml\fP, and \fBpp\fP. +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.IP "" 0 -. -.SH "SEE ALSO" -\fBknife\-node(1)\fR \fBknife\-cookbook(1)\fR \fBknife\-role(1)\fR \fIhttp://wiki\.opscode\.com/display/chef/Environments\fR \fIhttp://wiki\.opscode\.com/display/chef/Version+Constraints\fR -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Daniel DeLeo \fIdan@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. -. -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-exec.1 b/distro/common/man/man1/knife-exec.1 index e8769e69f0..3f9e6fc47b 100644 --- a/distro/common/man/man1/knife-exec.1 +++ b/distro/common/man/man1/knife-exec.1 @@ -1,43 +1,327 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 +.TH "KNIFE-EXEC" "1" "Chef 11.8" "" "knife exec" +.SH NAME +knife-exec \- The man page for the knife exec subcommand. . -.TH "KNIFE\-EXEC" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.nr rst2man-indent-level 0 . -.SH "NAME" -\fBknife\-exec\fR \- Run user scripts using the Chef API DSL -. -.SH "SYNOPSIS" -\fBknife\fR \fBexec\fR \fI(options)\fR +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. . +.sp +The \fBknife exec\fP subcommand uses the Knife configuration file to execute Ruby scripts in the context of a fully configured chef\-client. This subcommand is most often used to run scripts that will only access server one time (or otherwise very infrequently). Use this subcommand any time that an operation does not warrant full usage of the Knife subcommand library. +.sp +For Ruby scripts that will be run using the \fBexec\fP subcommand, note the following: +.INDENT 0.0 +.INDENT 3.5 +.INDENT 0.0 +.IP \(bu 2 +The Ruby script must be located on the system from which Knife is run (and not be located on any of the systems that Knife will be managing). +.IP \(bu 2 +Shell commands will be run from a management workstation. For example, something like \fB%x[ls \-lash /opt/only\-on\-a\-node]\fP would give you the directory listing for the "opt/only\-on\-a\-node" directory or a "No such file or directory" error if the file does not already exist locally. +.IP \(bu 2 +When the chef\-shell DSL is available, the chef\-client DSL will not be (unless the management workstation is also a chef\-client). Without the chef\-client DSL, a bash block cannot be used to run bash commands. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-E\fR, \fB\-\-exec CODE\fR -Provide a snippet of code to evaluate on the command line -. -.SH "DESCRIPTION" -\fBknife exec\fR runs arbitrary ruby scripts in a context similar to that of the chef\-shell(1) DSL\. See the chef\-shell documentation for a description of the commands available\. -. -.SH "EXAMPLES" -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -Make an API call against an arbitrary endpoint -knife exec \-E \'api\.get("nodes/fluke\.localdomain/cookbooks")\' => list of cookbooks for the node \fIfluke\.localdomain\fR -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -Remove the role \fIobsolete\fR from all nodes -knife exec \-E \'nodes\.transform(:all){|n| n\.run_list\.delete("role[obsolete]")}\' -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -Generate the expanded run list for hosts in the \fBwebserver\fR role -knife exec \-E \'nodes\.find(:roles => "webserver") {|n| n\.expand!; n[:recipes]}\' -. -.SH "SEE ALSO" -\fBchef\-shell(1)\fR -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBAuthenticated API Requests\fP +.sp +The \fBknife exec\fP subcommand can be used to make authenticated API requests to the server using the following methods: +.TS +center; +|l|l|. +_ +T{ +Method +T} T{ +Description +T} +_ +T{ +\fBapi.delete\fP +T} T{ +Use to delete an object from the server. +T} +_ +T{ +\fBapi.get\fP +T} T{ +Use to get the details of an object on the server. +T} +_ +T{ +\fBapi.post\fP +T} T{ +Use to add an object to the server. +T} +_ +T{ +\fBapi.put\fP +T} T{ +Use to update an object on the server. +T} +_ +.TE +.sp +These methods are used with the \fB\-E\fP option, which executes that string locally on the workstation using chef\-shell. These methods have the following syntax: +.sp +.nf +.ft C +$ knife exec \-E \(aqapi.method(/endpoint)\(aq +.ft P +.fi +.sp +where: +.INDENT 0.0 +.IP \(bu 2 +\fBapi.method\fP is the corresponding authentication method \-\-\- \fBapi.delete\fP, \fBapi.get\fP, \fBapi.post\fP, or \fBapi.put\fP +.IP \(bu 2 +\fB/endpoint\fP is an endpoint in the Chef Server API +.UNINDENT +.sp +For example, to get the data for a node named "Example_Node": +.sp +.nf +.ft C +$ knife exec \-E \(aqputs api.get("/nodes/Example_Node")\(aq +.ft P +.fi +.sp +and to ensure that the output is visible in the console, add the \fBputs\fP in front of the API authorization request: +.sp +.nf +.ft C +$ knife exec \-E \(aqputs api.get("/nodes/Example_Node")\(aq +.ft P +.fi +.sp +where \fBputs\fP is the shorter version of the \fB$stdout.puts\fP predefined variable in Ruby. +.sp +The following example shows how to add a client named "IBM305RAMAC" and the \fB/clients\fP endpoint, and then return the private key for that user in the console: +.sp +.nf +.ft C +$ client_desc = { + "name" => "IBM305RAMAC", + "admin" => false + } + + new_client = api.post("/clients", client_desc) + puts new_client["private_key"] +.ft P +.fi +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife exec SCRIPT (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-E CODE\fP, \fB\-\-exec CODE\fP +A string of code that will be executed. +.TP +.B \fB\-p PATH:PATH\fP, \fB\-\-script\-path PATH:PATH\fP +A colon\-separated path at which Ruby scripts are located. +.UNINDENT +.sp +\fBExamples\fP +.sp +There are three ways to use \fBknife exec\fP to run Ruby script files. For example: +.sp +.nf +.ft C +$ knife exec /path/to/script_file +.ft P +.fi +.sp +Or: +.sp +.nf +.ft C +$ knife exec \-E \(aqRUBY CODE\(aq +.ft P +.fi +.sp +Or: +.sp +.nf +.ft C +$ knife exec +RUBY CODE +^D +.ft P +.fi +.sp +To check the status of Knife using a Ruby script named "status.rb" (which looks like): +.sp +.nf +.ft C +printf "%\-5s %\-12s %\-8s %s\en", "Check In", "Name", "Ruby", "Recipes" +nodes.all do |n| + checkin = Time.at(n[\(aqohai_time\(aq]).strftime("%F %R") + rubyver = n[\(aqlanguages\(aq][\(aqruby\(aq][\(aqversion\(aq] + recipes = n.run_list.expand(_default).recipes.join(", ") + printf "%\-20s %\-12s %\-8s %s\en", checkin, n.name, rubyver, recipes +end +.ft P +.fi +.sp +and is located in a directory named "scripts", enter: +.sp +.nf +.ft C +$ knife exec scripts/status.rb +.ft P +.fi +.sp +To show the available free memory for all nodes, enter: +.sp +.nf +.ft C +$ knife exec \-E \(aqnodes.all {|n| puts "#{n.name} has #{n.memory.total} free memory"}\(aq +.ft P +.fi +.sp +To list all of the available search indexes, enter: +.sp +.nf +.ft C +$ knife exec \-E \(aqputs api.get("search").keys\(aq +.ft P +.fi +.sp +To query a node for multiple attributes using a Ruby script named \fBsearch_attributes.rb\fP (which looks like): +.sp +.nf +.ft C +% cat scripts/search_attributes.rb +query = ARGV[2] +attributes = ARGV[3].split(",") +puts "Your query: #{query}" +puts "Your attributes: #{attributes.join(" ")}" +results = {} +search(:node, query) do |n| + results[n.name] = {} + attributes.each {|a| results[n.name][a] = n[a]} +end + +puts results +exit 0 +.ft P +.fi +.sp +enter: +.sp +.nf +.ft C +% knife exec scripts/search_attributes.rb "hostname:test_system" ipaddress,fqdn +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +Your query: hostname:test_system +Your attributes: ipaddress fqdn +{"test_system.example.com"=>{"ipaddress"=>"10.1.1.200", "fqdn"=>"test_system.example.com"}} +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-index-rebuild.1 b/distro/common/man/man1/knife-index-rebuild.1 new file mode 100644 index 0000000000..2bacf68619 --- /dev/null +++ b/distro/common/man/man1/knife-index-rebuild.1 @@ -0,0 +1,117 @@ +.TH "KNIFE-INDEX-REBUILD" "1" "Chef 11.8" "" "knife index rebuild" +.SH NAME +knife-index-rebuild \- The man page for the knife index rebuild subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife index rebuild\fP subcommand is used to rebuild the search indexes for the open source server. This operation is destructive and may take some time. +.IP Note +This subcommand ONLY works when run against the open source server version 10.x. This subcommand will NOT run against open source server 11, Enterprise Chef (including hosted Enterprise Chef), or Private Chef. +.RE +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife index rebuild +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-index.1 b/distro/common/man/man1/knife-index.1 index b715619112..ac7c5b2655 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "KNIFE\-INDEX" "1" "July 2013" "Chef 11.8.0.alpha.0" "Chef Manual" . .SH "NAME" \fBknife\-index\fR \- Rebuild the search index on a Chef Server diff --git a/distro/common/man/man1/knife-list.1 b/distro/common/man/man1/knife-list.1 new file mode 100644 index 0000000000..e4cfb6710d --- /dev/null +++ b/distro/common/man/man1/knife-list.1 @@ -0,0 +1,169 @@ +.TH "KNIFE-LIST" "1" "Chef 11.8" "" "knife list" +.SH NAME +knife-list \- The man page for the knife list subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife list\fP subcommand is used to view a list of objects on the server. This subcommand works similar to \fBknife cookbook list\fP, \fBknife data bag list\fP, \fBknife environment list\fP, \fBknife node list\fP, and \fBknife role list\fP, but with a single verb (and a single action). +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife list [PATTERN...] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-chef\-repo\-path PATH\fP +The path to the chef\-repo. This setting will override the default path to the chef\-repo. Default: same as specified by \fBchef_repo_path\fP in config.rb. +.TP +.B \fB\-\-concurrency\fP +The number of allowed concurrent connections. Default: \fB10\fP. +.TP +.B \fB\-d\fP +Indicates that a directory\(aqs children will not be shown when a directory matches a pattern. Default value: \fBfalse\fP. +.TP +.B \fB\-f\fP, \fB\-\-flat\fP +Indicates that a list of file names will be shown. Set to \fBfalse\fP to view ls\-like output. Default: \fBfalse\fP. +.TP +.B \fB\-\-local\fP +Indicates that only contents of the local directory will be returned. Default: \fBfalse\fP. +.TP +.B \fB\-1\fP +Indicates that only one column of results will be shown. Default: \fBfalse\fP. +.TP +.B \fB\-p\fP +Indicates that trailing slashes (/) will be shown for directories. Default: \fBfalse\fP. +.TP +.B \fB\-R\fP +Indicates that directories will be listed recursively. Default: \fBfalse\fP. +.TP +.B \fB\-\-repo\-mode MODE\fP +The layout of the local chef\-repo. Possible values: \fBstatic\fP, \fBeverything\fP, or \fBhosted_everything\fP. Use \fBstatic\fP for just roles, environments, cookbooks, and data bags. By default, \fBeverything\fP and \fBhosted_everything\fP are dynamically selected depending on the server type. Default: \fBeverything\fP / \fBhosted_everything\fP. +.UNINDENT +.sp +\fBExamples\fP +.sp +For example, to view a list of roles on the server: +.sp +.nf +.ft C +$ knife list roles/ +.ft P +.fi +.sp +To view a list of roles and environments on the server: +.sp +.nf +.ft C +$ knife list roles/ environments/ +.ft P +.fi +.sp +To view a list of absolutely everything on the server: +.sp +.nf +.ft C +$ knife list \-R / +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-node.1 b/distro/common/man/man1/knife-node.1 index 145fbd8374..9b36a04228 100644 --- a/distro/common/man/man1/knife-node.1 +++ b/distro/common/man/man1/knife-node.1 @@ -1,134 +1,580 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "KNIFE\-NODE" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" -. -.SH "NAME" -\fBknife\-node\fR \- Manage the hosts in your infrastructure -. -.SH "SYNOPSIS" -\fBknife\fR \fBnode\fR \fIsub\-command\fR \fI(options)\fR -. -.SH "DESCRIPTION" -Nodes are data structures that represent hosts configured with Chef\. Nodes have a \fBname\fR, a String that uniquely identifies the node, \fBattributes\fR, a nested Hash of properties that describe how the host should be configured, a \fBchef_environment\fR, a String representing the environment to which the node belongs, and a \fBrun_list\fR, an ordered list of \fBrecipes\fR or \fBroles\fR that chef\-client should apply when configuring a host\. -. -.P -When a host communicates with a Chef Server, it authenticates using its \fBnode_name\fR for identification and signs its reqests with a private key\. The Server validates the request by looking up a \fBclient\fR object with a name identical to the \fBnode_name\fR submitted with the request and verifes the signature using the public key for that \fBclient\fR object\. \fBNOTE\fR that the \fBclient\fR is a different object in the system\. It is associated with a node by virtue of having a matching name\. -. -.P -By default \fBchef\-client\fR(8) will create a node using the FQDN of the host for the node name, though this may be overridden by configuration settings\. -. -.SH "NODE SUB\-COMMANDS" -The following \fBnode\fR subcommands are available: -. -.SH "BULK DELETE" -\fBknife node bulk delete\fR \fIregex\fR \fI(options)\fR -. -.P -Deletes nodes for which the name matches the regular expression \fIregex\fR on the Chef Server\. The regular expression should be given in quotes, and should not be surrounded with forward slashes (as is typical of regular expression literals in scripting languages)\. -. -.SH "CREATE" -\fBknife node create\fR \fIname\fR \fI(options)\fR -. -.P -Create a new node\. Unless the \-\-disable\-editing option is given, an empty node object will be created and displayed in your text editor\. If the editor exits with a successful exit status, the node data will be posted to the Chef Server to create the node\. -. -.SH "DELETE" -\fBknife node delete\fR \fIname\fR \fI(options)\fR -. -.P -Deletes the node identified by \fIname\fR on the Chef Server\. -. -.SH "EDIT" -\fBknife node edit\fR \fIname\fR \fI(options)\fR -. +.TH "KNIFE-NODE" "1" "Chef 11.8" "" "knife node" +.SH NAME +knife-node \- The man page for the knife node subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +A node is any physical, virtual, or cloud machine that is configured to be maintained by a chef\-client. +.sp +The \fBknife node\fP subcommand is used to manage the nodes that exist on a server. +.sp +This subcommand has the following syntax: +.sp +.nf +.ft C +$ knife node [ARGUMENT] (options) +.ft P +.fi +.SH COMMON OPTIONS +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-a\fR, \fB\-\-all\fR -Display all node data in the editor\. By default, default, override, and automatic attributes are not shown\. -. -.P -Edit the node identified by \fIname\fR\. Like \fBknife node create\fR, the node will be displayed in your text editor unless the \-n option is present\. -. -.SH "FROM FILE" -\fBknife node from file\fR \fIfile\fR \fI(options)\fR -. -.P -Create a node from a JSON format \fIfile\fR\. -. -.SH "LIST" -\fBknife node list\fR \fI(options)\fR -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-w\fR, \fB\-\-with\-uri\fR -Show corresponding URIs -. -.P -List all nodes\. -. -.SH "RUN_LIST ADD" -\fBknife node run_list add\fR \fIname\fR \fIrun list item\fR \fI(options)\fR -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB\-a\fR, \fB\-\-after ITEM\fR -Place the ENTRY in the run list after ITEM -. -.P -Add the \fIrun list item\fR to the node\'s \fBrun_list\fR\. See Run list -. -.SH "RUN_LIST REMOVE" -\fBknife node run_list remove\fR \fInode name\fR \fIrun list item\fR \fI(options)\fR -. -.P -Remove the \fIrun list item\fR from the node\'s \fBrun_list\fR\. -. -.SH "SHOW" -\fBknife node show\fR \fInode name\fR \fI(options)\fR -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -\fB\-a\fR, \fB\-\-attribute [ATTR]\fR -Show only one attribute -. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. .TP -\fB\-r\fR, \fB\-\-run\-list\fR -Show only the run list -. +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. .TP -\fB\-F\fR, \fB\-\-format FORMAT\fR -Display the node in a different format\. -. +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. .TP -\fB\-m\fR, \fB\-\-medium\fR -Display more, but not all, of the node\'s data when using the default \fIsummary\fR format -. -.P -Displays the node identified by \fInode name\fR on stdout\. -. -.SH "RUN LIST ITEM FORMAT" -Run list items may be either roles or recipes\. When adding a role to a run list, the correct syntax is "role[ROLE_NAME]" -. -.P -When adding a recipe to a run list, there are several valid formats: -. +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. .TP -Fully Qualified Format -"recipe[COOKBOOK::RECIPE_NAME]", for example, "recipe[chef::client]" -. +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. .TP -Cookbook Recipe Format -For brevity, the recipe part of the fully qualified format may be omitted, and recipes specified as "COOKBOOK::RECIPE_NAME", e\.g\., "chef::client" -. +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. .TP -Default Recipe Format -When adding the default recipe of a cookbook to a run list, the recipe name may be omitted as well, e\.g\., "chef::default" may be written as just "chef" -. -.SH "SEE ALSO" -\fBknife\-client\fR(1) \fBknife\-search\fR(1) \fBknife\-role\fR(1) -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.SH BULK DELETE +.sp +The \fBbulk delete\fP argument is used to delete one or more nodes that match a pattern defined by a regular expression. The regular expression must be within quotes and not be surrounded by forward slashes (/). +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife node bulk delete REGEX +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To bulk delete many nodes, use a regular expression to define the pattern: +.sp +.nf +.ft C +$ knife node bulk delete "^[0\-9]{3}$" +.ft P +.fi +.sp +Type \fBY\fP to confirm a deletion. +.SH CREATE +.sp +The \fBcreate\fP argument is used to add a node to the server. Node data is stored as JSON on the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife node create NODE_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To add a node, enter: +.sp +.nf +.ft C +$ knife node create node1 +.ft P +.fi +.sp +In the $EDITOR enter the node data in JSON: +.sp +.nf +.ft C +## sample: +{ + "normal": { + }, + "name": "foobar", + "override": { + }, + "default": { + }, + "json_class": "Chef::Node", + "automatic": { + }, + "run_list": [ + "recipe[zsh]", + "role[webserver]" + ], + "chef_type": "node" +} +.ft P +.fi +.sp +When finished, save it. +.SH DELETE +.sp +The \fBdelete\fP argument is used to delete a node from the server. +.IP Note +Deleting a node will not delete any corresponding API clients. +.RE +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife node delete NODE_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To delete a node called "dev", enter: +.sp +.nf +.ft C +$ knife node delete dev +.ft P +.fi +.SH EDIT +.sp +The \fBedit\fP argument is used to edit the details of a node on a server. Node data is stored as JSON on the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife node edit NODE_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-all\fP +Displays a node in the $EDITOR. By default, attributes that are default, override, or automatic are not shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +To edit the data for a node named "node1", enter: +.sp +.nf +.ft C +$ knife node edit node1 \-a +.ft P +.fi +.sp +Update the role data in JSON: +.sp +.nf +.ft C +## sample: +{ + "normal": { + }, + "name": "node1", + "override": { + }, + "default": { + }, + "json_class": "Chef::Node", + "automatic": { + }, + "run_list": [ + "recipe[devops]", + "role[webserver]" + ], + "chef_type": "node" +} +.ft P +.fi +.sp +When finished, save it. +.SH FROM FILE +.sp +The \fBfrom file\fP argument is used to create a node using existing node data as a template. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife node from file FILE +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To add a node using data contained in a JSON file: +.sp +.nf +.ft C +$ knife node from file "path to JSON file" +.ft P +.fi +.SH LIST +.sp +The \fBlist\fP argument is used to view all of the nodes that exist on a server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife node list (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-w\fP, \fB\-\-with\-uri\fP +Indicates that the corresponding URIs will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +To verify the list of nodes that are registered with the server, enter: +.sp +.nf +.ft C +$ knife node list +.ft P +.fi +.sp +to return something similar to: +.sp +.nf +.ft C +i\-12345678 +rs\-123456 +.ft P +.fi +.SH RUN_LIST ADD +.sp +The \fBrun_list add\fP argument is used to add run list items (roles or recipes) to a node. A recipe must be in one of the following formats: fully qualified, cookbook, or default. Both roles and recipes must be in quotes, for example: \fB\(aqrole[ROLE_NAME]\(aq\fP or \fB\(aqrecipe[COOKBOOK::RECIPE_NAME]\(aq\fP. Use a comma to separate roles and recipes when adding more than one, like this: \fB\(aqrecipe[COOKBOOK::RECIPE_NAME],COOKBOOK::RECIPE_NAME,role[ROLE_NAME]\(aq\fP. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife node run_list add NODE_NAME RUN_LIST_ITEM (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a ITEM\fP, \fB\-\-after ITEM\fP +Use this to add the run list item after the specified run list item. +.UNINDENT +.sp +\fBExamples\fP +.sp +To add a role to a run list, enter: +.sp +.nf +.ft C +$ knife node run_list add node \(aqrole[ROLE_NAME]\(aq +.ft P +.fi +.sp +To add roles and recipes to a run list, enter: +.sp +.nf +.ft C +$ knife node run_list add node \(aqrecipe[COOKBOOK::RECIPE_NAME],recipe[COOKBOOK::RECIPE_NAME],role[ROLE_NAME]\(aq +.ft P +.fi +.sp +To add a recipe to a run list using the fully qualified format, enter: +.sp +.nf +.ft C +$ knife node run_list add node \(aqrecipe[COOKBOOK::RECIPE_NAME]\(aq +.ft P +.fi +.sp +To add a recipe to a run list using the cookbook format, enter: +.sp +.nf +.ft C +$ knife node run_list add node \(aqCOOKBOOK::RECIPE_NAME\(aq +.ft P +.fi +.sp +To add the default recipe of a cookbook to a run list, enter: +.sp +.nf +.ft C +$ knife node run_list add node \(aqCOOKBOOK\(aq +.ft P +.fi +.SH RUN_LIST REMOVE +.sp +The \fBrun_list remove\fP argument is used to remove run list items (roles or recipes) from a node. A recipe must be in one of the following formats: fully qualified, cookbook, or default. Both roles and recipes must be in quotes, for example: \fB\(aqrole[ROLE_NAME]\(aq\fP or \fB\(aqrecipe[COOKBOOK::RECIPE_NAME]\(aq\fP. Use a comma to separate roles and recipes when removing more than one, like this: \fB\(aqrecipe[COOKBOOK::RECIPE_NAME],COOKBOOK::RECIPE_NAME,role[ROLE_NAME]\(aq\fP. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife node run_list remove NODE_NAME RUN_LIST_ITEM +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To remove a role from a run list, enter: +.sp +.nf +.ft C +$ knife node run_list remove node \(aqrole[ROLE_NAME]\(aq +.ft P +.fi +.sp +To remove a recipe from a run list using the fully qualified format, enter: +.sp +.nf +.ft C +$ knife node run_list remove node \(aqrecipe[COOKBOOK::RECIPE_NAME]\(aq +.ft P +.fi +.SH SHOW +.sp +The \fBshow\fP argument is used to display information about a node. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife node show NODE_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a ATTR\fP, \fB\-\-attribute ATTR\fP +The attribute (or attributes) to show. +.TP +.B \fB\-l\fP, \fB\-\-long\fP +Display long output when searching nodes while using the default summary format. +.TP +.B \fB\-m\fP, \fB\-\-medium\fP +Display more, but not all, of a node\(aqs data when searching using the default summary format. +.TP +.B \fB\-r\fP, \fB\-\-run\-list\fP +Indicates that only the run\-list will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +To view all data for a node named "build", enter: +.sp +.nf +.ft C +$ knife node show build +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +Node Name: build +Environment: _default +FQDN: +IP: +Run List: +Roles: +Recipes: +Platform: +.ft P +.fi +.sp +To show basic information about a node, truncated and nicely formatted: +.sp +.nf +.ft C +knife node show <node_name> +.ft P +.fi +.sp +To show all information about a node, nicely formatted: +.sp +.nf +.ft C +knife node show \-l <node_name> +.ft P +.fi +.sp +To list a single node attribute: +.sp +.nf +.ft C +knife node show <node_name> \-a <attribute_name> +.ft P +.fi +.sp +where \fB<attribute_name>\fP is something like kernel or platform. (This doesn\(aqt work for nested attributes like \fBnode[kernel][machine]\fP because \fBknife node show\fP doesn\(aqt understand nested attributes.) +.sp +To view the FQDN for a node named "i\-12345678", enter: +.sp +.nf +.ft C +$ knife node show i\-12345678 \-a fqdn +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +fqdn: ip\-10\-251\-75\-20.ec2.internal +.ft P +.fi +.sp +To view the run list for a node named "dev", enter: +.sp +.nf +.ft C +$ knife node show dev \-r +.ft P +.fi +.sp +To view information in JSON format, use the \fB\-F\fP common option as part of the command like this: +.sp +.nf +.ft C +$ knife role show devops \-F json +.ft P +.fi +.sp +Other formats available include \fBtext\fP, \fByaml\fP, and \fBpp\fP. +.sp +To view node information in raw JSON, use the \fB\-l\fP or \fB\-\-long\fP option: +.sp +.nf +.ft C +knife node show \-l \-F json <node_name> +.ft P +.fi +.sp +and/or: +.sp +.nf +.ft C +knife node show \-l \-\-format=json <node_name> +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-raw.1 b/distro/common/man/man1/knife-raw.1 new file mode 100644 index 0000000000..5053006c0b --- /dev/null +++ b/distro/common/man/man1/knife-raw.1 @@ -0,0 +1,172 @@ +.TH "KNIFE-RAW" "1" "Chef 11.8" "" "knife raw" +.SH NAME +knife-raw \- The man page for the knife raw subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife raw\fP subcommand is used to send a REST request to a specified path using the Chef Server API. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife raw REQUEST_PATH (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-chef\-repo\-path PATH\fP +The path to the chef\-repo. This setting will override the default path to the chef\-repo. Default: same as specified by \fBchef_repo_path\fP in config.rb. +.TP +.B \fB\-\-concurrency\fP +The number of allowed concurrent connections. Default: \fB10\fP. +.TP +.B \fB\-i FILE\fP, \fB\-\-input FILE\fP +The name of a file to be used with the \fBPUT\fP or a \fBPOST\fP request. +.TP +.B \fB\-\-[no\-]pretty\fP +Use \fB\-\-no\-pretty\fP to disable pretty\-print output for JSON. Default: \fB\-\-pretty\fP. +.TP +.B \fB\-m METHOD\fP, \fB\-\-method METHOD\fP +The request method: \fBDELETE\fP, \fBGET\fP, \fBPOST\fP, or \fBPUT\fP. Default value: \fBGET\fP. +.TP +.B \fB\-\-repo\-mode MODE\fP +The layout of the local chef\-repo. Possible values: \fBstatic\fP, \fBeverything\fP, or \fBhosted_everything\fP. Use \fBstatic\fP for just roles, environments, cookbooks, and data bags. By default, \fBeverything\fP and \fBhosted_everything\fP are dynamically selected depending on the server type. Default: \fBeverything\fP / \fBhosted_everything\fP. +.UNINDENT +.sp +\fBExamples\fP +.sp +To view information about a client: +.sp +.nf +.ft C +knife raw /clients/<client_name> +.ft P +.fi +.sp +To view information about a node: +.sp +.nf +.ft C +knife raw /nodes/<node_name> +.ft P +.fi +.sp +To delete a data bag, enter a command similar to: +.sp +.nf +.ft C +$ knife raw \-m DELETE /data/foo +.ft P +.fi +.sp +to return something similar to: +.sp +.nf +.ft C +{ + "name":"foo", + "json_class":"Chef::DataBag", + "chef_type":"data_bag" +} +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-recipe-list.1 b/distro/common/man/man1/knife-recipe-list.1 new file mode 100644 index 0000000000..d8cca9edec --- /dev/null +++ b/distro/common/man/man1/knife-recipe-list.1 @@ -0,0 +1,135 @@ +.TH "KNIFE-RECIPE-LIST" "1" "Chef 11.8" "" "knife recipe list" +.SH NAME +knife-recipe-list \- The man page for the knife recipe list subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife recipe list\fP subcommand is used to view all of the recipes that are on a server. A regular expression can be used to limit the results to recipes that match a specific pattern. The regular expression must be within quotes and not be surrounded by forward slashes (/). +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife recipe list REGEX +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To view a list of recipes: +.sp +.nf +.ft C +$ knife recipe list \(aqcouchdb::*\(aq +.ft P +.fi +.sp +to return: +.sp +.nf +.ft C +couchdb::main_monitors +couchdb::master +couchdb::default +couchdb::org_cleanu +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-role.1 b/distro/common/man/man1/knife-role.1 index 57ff2143ad..cbf736ebf7 100644 --- a/distro/common/man/man1/knife-role.1 +++ b/distro/common/man/man1/knife-role.1 @@ -1,88 +1,376 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 +.TH "KNIFE-ROLE" "1" "Chef 11.8" "" "knife role" +.SH NAME +knife-role \- The man page for the knife role subcommand. . -.TH "KNIFE\-ROLE" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.nr rst2man-indent-level 0 . -.SH "NAME" -\fBknife\-role\fR \- Group common configuration settings -. -.SH "SYNOPSIS" -\fBknife\fR \fBrole\fR \fIsub\-command\fR \fI(options)\fR -. -.SH "ROLE SUB\-COMMANDS" -The following \fBrole\fR subcommands are available: -. -.SH "LIST" -\fBknife role list\fR \fI(options)\fR +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. . +.sp +A role is a way to define certain patterns and processes that exist across nodes in an organization as belonging to a single job function. Each role consists of zero (or more) attributes and a run list. Each node can have zero (or more) roles assigned to it. When a role is run against a node, the configuration details of that node are compared against the attributes of the role, and then the contents of that role\(aqs run list are applied to the node\(aqs configuration details. When a chef\-client runs, it merges its own attributes and run lists with those contained within each assigned role. +.sp +The \fBknife role\fP subcommand is used to manage the roles that are associated with one or more nodes on a server. +.sp +This subcommand has the following syntax: +.sp +.nf +.ft C +$ knife role [ARGUMENT] (options) +.ft P +.fi +.IP Note +Use the \fBknife node\fP subcommand (and the \fBrun_list add node\fP argument) to add a role to a node on the server. +.RE +.SH COMMON OPTIONS +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-w\fR, \fB\-\-with\-uri\fR -Show corresponding URIs -. -.P -List roles\. -. -.SH "SHOW" -\fBknife role show ROLE\fR \fI(options)\fR -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-a\fR, \fB\-\-attribute ATTR\fR -Show only one attribute -. -.P -Show a specific role\. -. -.SH "CREATE" -\fBknife role create ROLE\fR \fI(options)\fR -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB\-d\fR, \fB\-\-description\fR -The role description -. -.P -Create a new role\. -. -.SH "EDIT" -\fBknife role edit ROLE\fR \fI(options)\fR -. -.P -Edit a role\. -. -.SH "FROM FILE" -\fBknife role from file FILE\fR \fI(options)\fR -. -.P -Create or update a role from a role Ruby DSL (\fB\.rb\fR) or JSON file\. -. -.SH "DELETE" -\fBknife role delete ROLE\fR \fI(options)\fR -. -.P -Delete a role\. -. -.SH "BULK DELETE" -\fBknife role bulk delete REGEX\fR \fI(options)\fR -. -.P -Delete roles on the Chef Server based on a regular expression\. The regular expression (\fIREGEX\fR) should be in quotes, not in //\'s\. -. -.SH "DESCRIPTION" -Roles provide a mechanism to group repeated configuration settings\. Roles are data structures that contain \fBdefault_attributes\fR, and \fBoverride_attributes\fR, which are nested hashes of configuration settings, and a \fBrun_list\fR, which is an ordered list of recipes and roles that should be applied to a host by chef\-client\. -. -.P -\fBdefault_attributes\fR will be overridden if they conflict with a value on a node that includes the role\. Conversely, \fBoverride_attributes\fR will override any values set on nodes that apply them\. -. -.P -When \fBchef\-client\fR(8) configures a host, it will "expand" the \fBrun_list\fR included in that host\'s node data\. The expansion process will recursively replace any roles in the run_list with that role\'s run_list\. -. -.SH "SEE ALSO" -\fBknife\-node(1)\fR \fBknife\-environment(1)\fR \fIhttp://wiki\.opscode\.com/display/chef/Roles\fR \fIhttp://wiki\.opscode\.com/display/chef/Attributes\fR -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.SH BULK DELETE +.sp +The \fBbulk delete\fP argument is used to delete one or more roles that match a pattern defined by a regular expression. The regular expression must be within quotes and not be surrounded by forward slashes (/). +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife role bulk delete REGEX +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To bulk delete roles using a regular expression: +.sp +.nf +.ft C +$ knife role bulk delete "^[0\-9]{3}$" +.ft P +.fi +.SH CREATE +.sp +The \fBcreate\fP argument is used to add a role to the server. To add a role to a node, you must use the \fBnode\fP sub\-command and the \fBrun\-list add\fP argument. Role data is saved as JSON on the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife role create ROLE_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-d DESCRIPTION\fP, \fB\-\-description DESCRIPTION\fP +The description of the role. This value will populate the description field for the role on the server. +.UNINDENT +.sp +\fBExamples\fP +.sp +To add a role named "role1", enter: +.sp +.nf +.ft C +$ knife role create role1 +.ft P +.fi +.sp +In the $EDITOR enter the role data in JSON: +.sp +.nf +.ft C +## sample: +{ + "name": "role1", + "default_attributes": { + }, + "json_class": "Chef::Role", + "run_list": [ + + ], + "description": "", + "chef_type": "role", + "override_attributes": { + } +} +.ft P +.fi +.sp +When finished, save it. +.SH DELETE +.sp +The \fBdelete\fP argument is used to delete a role from the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife role delete ROLE_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To delete a role: +.sp +.nf +.ft C +$ knife role delete devops +.ft P +.fi +.sp +Type \fBY\fP to confirm a deletion. +.SH EDIT +.sp +The \fBedit\fP argument is used to edit role details on the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife role edit ROLE_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To edit the data for a role named "role1", enter: +.sp +.nf +.ft C +$ knife role edit role1 +.ft P +.fi +.sp +Update the role data in JSON: +.sp +.nf +.ft C +## sample: +{ + "name": "role1", + "default_attributes": { + }, + "json_class": "Chef::Role", + "run_list": [ + + ], + "description": "This is the description for the role1 role.", + "chef_type": "role", + "override_attributes": { + } +} +.ft P +.fi +.sp +When finished, save it. +.SH FROM FILE +.sp +The \fBfrom file\fP argument is used to create a role using existing JSON data as a template. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife role from file FILE +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To view role details based on the values contained in a JSON file: +.sp +.nf +.ft C +$ knife role from file "path to JSON file" +.ft P +.fi +.SH LIST +.sp +The \fBlist\fP argument is used to view a list of roles that are currently available on the server. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife role list +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-w\fP, \fB\-\-with\-uri\fP +Indicates that the corresponding URIs will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +To view a list of roles on the server and display the URI for each role returned, enter: +.sp +.nf +.ft C +$ knife role list \-w +.ft P +.fi +.SH SHOW +.sp +The \fBshow\fP argument is used to view the details of a role. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife role show ROLE_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a ATTR\fP, \fB\-\-attribute ATTR\fP +The attribute (or attributes) to show. +.UNINDENT +.sp +\fBExamples\fP +.sp +To view information in JSON format, use the \fB\-F\fP common option as part of the command like this: +.sp +.nf +.ft C +$ knife role show devops \-F json +.ft P +.fi +.sp +Other formats available include \fBtext\fP, \fByaml\fP, and \fBpp\fP. +.sp +To view information in JSON format, use the \fB\-F\fP common option as part of the command like this: +.sp +.nf +.ft C +$ knife role show devops \-F json +.ft P +.fi +.sp +Other formats available include \fBtext\fP, \fByaml\fP, and \fBpp\fP. +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-search.1 b/distro/common/man/man1/knife-search.1 index c8ea316d8c..6f4edebe1f 100644 --- a/distro/common/man/man1/knife-search.1 +++ b/distro/common/man/man1/knife-search.1 @@ -1,280 +1,306 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 -. -.TH "KNIFE\-SEARCH" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" -. -.SH "NAME" -\fBknife\-search\fR \- Find objects on a Chef Server by query -. -.SH "SYNOPSIS" -\fBknife\fR \fBsearch INDEX QUERY\fR \fI(options)\fR -. +.TH "KNIFE-SEARCH" "1" "Chef 11.8" "" "knife search" +.SH NAME +knife-search \- The man page for the knife search subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +Search indexes allow queries to be made for any type of data that is indexed by the server, including data bags (and data bag items), environments, nodes, and roles. A defined query syntax is used to support search patterns like exact, wildcard, range, and fuzzy. A search is a full\-text query that can be done from several locations, including from within a recipe, by using the \fBsearch\fP subcommand in Knife, by using the search functionality in the Management Console, or by using the \fB/search\fP or \fB/search/INDEX\fP endpoints in the Chef Server API. The search engine is based on Apache Solr and is run from the server. +.sp +The \fBknife search\fP subcommand is used run a search query for information that is indexed on a server. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-a\fR, \fB\-\-attribute ATTR\fR -Show only one attribute -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-i\fR, \fB\-\-id\-only\fR -Show only the ID of matching objects -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB\-q\fR, \fB\-\-query QUERY\fR -The search query; useful to protect queries starting with \- -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -\fB\-R\fR, \fB\-\-rows INT\fR -The number of rows to return -. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. .TP -\fB\-r\fR, \fB\-\-run\-list\fR -Show only the run list -. +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. .TP -\fB\-o\fR, \fB\-\-sort SORT\fR -The order to sort the results in -. +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. .TP -\fB\-b\fR, \fB\-\-start ROW\fR -The row to start returning results at -. +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. .TP -\fB\-m\fR, \fB\-\-medium\fR -Display medium sized output when searching nodes using the default summary format -. +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. .TP -\fB\-l\fR, \fB\-\-long\fR -Display long output when searching nodes using the default summary format -. -.SH "DESCRIPTION" -Search is a feature of the Chef Server that allows you to use a full\-text search engine to query information about your infrastructure and applications\. You can utilize this service via search calls in a recipe or the knife search command\. The search syntax is based on Lucene\. -. -.SH "INDEXES" -Search indexes are a feature of the Chef Server and the search sub\-command allows querying any of the available indexes using SOLR query syntax\. The following data types are indexed for search: -. -.IP "\(bu" 4 -\fInode\fR -. -.IP "\(bu" 4 -\fIrole\fR -. -.IP "\(bu" 4 -\fIenvironment\fR -. -.IP "\(bu" 4 -\fIclients\fR -. -.IP "\(bu" 4 -\fIdata bag\fR -. -.IP "" 0 -. -.P -Data bags are indexed by the data bag\'s name\. For example, to search a data bag named "admins": -. -.IP "" 4 -. +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp .nf - -knife search admins "field:search_pattern" -. +.ft C +$ knife search INDEX SEARCH_QUERY +.ft P .fi -. -.IP "" 0 -. -.SH "QUERY SYNTAX" -Queries have the form \fBfield:search_pattern\fR where \fBfield\fR is a key in the JSON description of the relevant objects (nodes, roles, environments, or data bags)\. Both \fBfield\fR and \fBsearch_pattern\fR are case\-sensitive\. \fBsearch_pattern\fR can be an exact, wildcard, range, or fuzzy match (see below)\. The \fBfield\fR supports exact matching and limited wildcard matching\. -. -.P -Searches will return the relevant objects (nodes, roles, environments, or data bags) where the \fBsearch_pattern\fR matches the object\'s value of \fBfield\fR\. -. -.SS "FIELD NAMES" -Field names are the keys within the JSON description of the object being searched\. Nested Keys can be searched by placing an underscore ("_") between key names\. -. -.SS "WILDCARD MATCHING FOR FIELD NAMES" -The field name also has limited support for wildcard matching\. Both the "*" and "?" wildcards (see below) can be used within a field name; however, they cannot be the first character of the field name\. -. -.SS "EXACT MATCHES" -Without any search modifiers, a search returns those fields for which the \fBsearch_pattern\fR exactly matches the value of \fBfield\fR in the JSON description of the object\. -. -.SS "WILDCARD MATCHES" -Search support both single\- and multi\-character wildcard searches within a search pattern\. -. -.P -\'?\' matches exactly one character\. -. -.P -\'*\' matches zero or more characters\. -. -.SS "RANGE MATCHES" -Range searches allows one to match values between two given values\. To match values between X and Y, inclusively, use square brackets: -. -.IP "" 4 -. +.sp +where \fBINDEX\fP is one of \fBclient\fP, \fBenvironment\fP, \fBnode\fP, \fBrole\fP, or the name of a data bag and \fBSEARCH_QUERY\fP is the search query syntax for the query that will be executed. +.sp +\fBINDEX\fP is implied if omitted, and will default to \fBnode\fP. For example: +.sp .nf - -knife search INDEX \'field:[X TO Y] -. +.ft C +$ knife search \(aq*:*\(aq \-i +.ft P .fi -. -.IP "" 0 -. -.P -To match values between X and Y, exclusively, use curly brackets: -. -.IP "" 4 -. +.sp +will return something similar to: +.sp .nf +.ft C +8 items found -knife search INDEX \'field:{X TO Y}\' -. +centos\-62\-dev +opensuse\-1203 +ubuntu\-1304\-dev +ubuntu\-1304\-orgtest +ubuntu\-1204\-ohai\-test +ubuntu\-1304\-ifcfg\-test +ohai\-test +win2k8\-dev +.ft P .fi -. -.IP "" 0 -. -.P -Values are sorted in lexicographic order\. -. -.SS "FUZZY MATCHES" -Fuzzy searches allows one to match values based on the Levenshtein Distance algorithm\. To perform a fuzzy match, append a tilda (~) to the search term: -. -.IP "" 4 -. +.sp +and is the same search as: +.sp .nf - -knife search INDEX \'field:term~\' -. +.ft C +$ knife node search \(aq*:*" \-i +.ft P .fi -. -.IP "" 0 -. -.P -This search would return nodes whose \fBfield\fR was \'perm\' or \'germ\'\. -. -.SS "BOOLEAN OPERATORS" -The boolean operators NOT, AND, and OR are supported\. To find values of \fBfield\fR that are not X: -. -.IP "" 4 -. +.sp +If the \fBSEARCH_QUERY\fP does not contain a colon character (\fB:\fP), then the default query pattern is \fBtags:*#{@query}* OR roles:*#{@query}* OR fqdn:*#{@query}* OR addresses:*#{@query}*\fP, which means the following two search queries are effectively the same: +.sp .nf - -knife search INDEX \'field:(NOT X)\' -. +.ft C +$ knife search ubuntu +.ft P .fi -. -.IP "" 0 -. -.P -To find records where \fBfield1\fR is X and \fBfield2\fR is Y: -. -.IP "" 4 -. +.sp +or: +.sp .nf - -knife search INDEX \'field1:X AND field2:Y\' -. +.ft C +$ knife search node "tags:*ubuntu* OR roles:*ubuntu* OR fqdn:*ubuntu* (etc.)" +.ft P .fi -. -.IP "" 0 -. -.P -To find records where \fBfield\fR is X or Y: -. -.IP "" 4 -. +.sp +\fBOptions\fP +.sp +This sub\-command has the following options: +.INDENT 0.0 +.TP +.B \fB\-a ATTR\fP, \fB\-\-attribute ATTR\fP +The attribute (or attributes) to show. +.TP +.B \fB\-b ROW\fP, \fB\-\-start ROW\fP +The row at which return results will begin. +.TP +.B \fB\-i\fP, \fB\-\-id\-only\fP +Indicates that only matching object IDs will be shown. +.TP +.B \fBINDEX\fP +The name of the index to be queried: \fBclient\fP, \fBenvironment\fP, \fBnode\fP, \fBrole\fP, or \fBDATA_BAG_NAME\fP. Default index: \fBnode\fP. +.TP +.B \fB\-l\fP, \fB\-\-long\fP +Display long output when searching nodes while using the default summary format. +.TP +.B \fB\-m\fP, \fB\-\-medium\fP +Display more, but not all, of a node\(aqs data when searching using the default summary format. +.TP +.B \fB\-o SORT\fP, \fB\-\-sort SORT\fP +The order in which search results will be sorted. +.TP +.B \fB\-q SEARCH_QUERY\fP, \fB\-\-query SEARCH_QUERY\fP +Use to protect search queries that start with a hyphen (\-). A \fB\-q\fP query may be specified as an argument or an option, but not both. +.TP +.B \fB\-r\fP, \fB\-\-run\-list\fP +Indicates that only the run\-list will be shown. +.TP +.B \fB\-R INT\fP, \fB\-\-rows INT\fP +The number of rows to be returned. +.TP +.B \fBSEARCH_QUERY\fP +The search query used to identify a a list of items on a server. This option uses the same syntax as the \fBsearch\fP sub\-command. +.UNINDENT +.sp +\fBExamples\fP +.sp +To search for the IDs of all nodes running on the Amazon EC2 platform, enter: +.sp .nf - -knife search INDEX \'field:X OR field:Y\' -. +.ft C +$ knife search node \(aqec2:*\(aq \-i +.ft P .fi -. -.IP "" 0 -. -.SS "QUOTING AND SPECIAL CHARACTERS" -In order to avoid having special characters and escape sequences within your search term interpreted by either Ruby or the shell, enclose them in single quotes\. -. -.P -Search terms that include spaces should be enclosed in double\-quotes: -. -.IP "" 4 -. +.sp +to return something like: +.sp .nf +.ft C +4 items found -knife search INDEX \'field:"term with spaces"\' -. +ip\-0A7CA19F.ec2.internal + +ip\-0A58CF8E.ec2.internal + +ip\-0A58E134.ec2.internal + +ip\-0A7CFFD5.ec2.internal +.ft P .fi -. -.IP "" 0 -. -.P -The following characters must be escaped: -. -.IP "" 4 -. +.sp +To search for the instance type (flavor) of all nodes running on the Amazon EC2 platform, enter: +.sp .nf - -+ \- && || ! ( ) { } [ ] ^ " ~ * ? : \e -. +.ft C +$ knife search node \(aqec2:*\(aq \-a ec2.instance_type +.ft P .fi -. -.IP "" 0 -. -.SH "EXAMPLES" -Find the nodes with the fully\-qualified domain name (FQDN) www\.example\.com: -. -.IP "" 4 -. +.sp +to return something like: +.sp .nf +.ft C +4 items found -knife search node \'fqdn:www\.example\.com\' -. +ec2.instance_type: m1.large +id: ip\-0A7CA19F.ec2.internal + +ec2.instance_type: m1.large +id: ip\-0A58CF8E.ec2.internal + +ec2.instance_type: m1.large +id: ip\-0A58E134.ec2.internal + +ec2.instance_type: m1.large +id: ip\-0A7CFFD5.ec2.internal +.ft P .fi -. -.IP "" 0 -. -.P -Find the nodes running a version of Ubuntu: -. -.IP "" 4 -. +.sp +To search for all nodes running Ubuntu, enter: +.sp .nf - -knife search node \'platform:ubuntu*\' -. +.ft C +$ knife search node \(aqplatform:ubuntu\(aq +.ft P .fi -. -.IP "" 0 -. -.P -Find all nodes running CentOS in the production environment: -. -.IP "" 4 -. +.sp +To search for all nodes running CentOS in the production environment, enter: +.sp .nf - -knife search node \'chef_environment:production AND platform:centos\' -. +.ft C +$ knife search node \(aqchef_environment:production AND platform:centos\(aq +.ft P .fi +.sp +To find a nested attribute, use a pattern similar to the following: +.sp +.nf +.ft C +$ knife search node <query_to_run> \-a <main_attribute>.<nested_attribute> +.ft P +.fi +.sp +To build a search query to use more than one attribute, use an underscore ( _ ) to separate each attribute. For example, the following query will search for all nodes running a specific version of Ruby: +.sp +.nf +.ft C +$ knife search node "languages_ruby_version:1.9.3" +.ft P +.fi +.sp +To build a search query that can find a nested attribute: +.sp +.nf +.ft C +$ knife search node name:<node_name> \-a kernel.machine +.ft P +.fi +.sp +To test a search query that will be used in a \fBknife ssh\fP command: +.sp +.nf +.ft C +$ knife search node "role:web AND NOT name:web03" +.ft P +.fi +.sp +where the query in the previous example will search all servers that have the \fBweb\fP role, but not on the server named \fBweb03\fP. +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.IP "" 0 -. -.SH "KNOWN BUGS" -. -.IP "\(bu" 4 -Searches against the client index return no results in most cases\. (CHEF\-2477) -. -.IP "\(bu" 4 -Searches using the fuzzy match operator (~) produce an error\. (CHEF\-2478) -. -.IP "" 0 -. -.SH "SEE ALSO" -\fBknife\-ssh\fR(1) \fIhttp://wiki\.opscode\.com/display/chef/Attributes\fR Lucene Query Parser Syntax \fIhttp://lucene\.apache\.org/java/2_3_2/queryparsersyntax\.html\fR -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. -. -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-show.1 b/distro/common/man/man1/knife-show.1 new file mode 100644 index 0000000000..da0aff8511 --- /dev/null +++ b/distro/common/man/man1/knife-show.1 @@ -0,0 +1,140 @@ +.TH "KNIFE-SHOW" "1" "Chef 11.8" "" "knife show" +.SH NAME +knife-show \- The man page for the knife show subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife show\fP subcommand is used to view the details of one (or more) objects on the server. This subcommand works similar to \fBknife cookbook show\fP, \fBknife data bag show\fP, \fBknife environment show\fP, \fBknife node show\fP, and \fBknife role show\fP, but with a single verb (and a single action). +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife show [PATTERN...] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To show all cookbooks in the \fBcookbooks/\fP directory: +.sp +.nf +.ft C +$ knife show cookbooks/ +.ft P +.fi +.sp +or, (if already in the \fBcookbooks/\fP directory in the local chef\-repo): +.sp +.nf +.ft C +$ knife show +.ft P +.fi +.sp +To show roles and environments: +.sp +.nf +.ft C +$ knife show roles/ environments/ +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-ssh.1 b/distro/common/man/man1/knife-ssh.1 index af41e3ccf5..ea755c9769 100644 --- a/distro/common/man/man1/knife-ssh.1 +++ b/distro/common/man/man1/knife-ssh.1 @@ -1,79 +1,256 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 +.TH "KNIFE-SSH" "1" "Chef 11.8" "" "knife ssh" +.SH NAME +knife-ssh \- The man page for the knife ssh subcommand. . -.TH "KNIFE\-SSH" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.nr rst2man-indent-level 0 . -.SH "NAME" -\fBknife\-ssh\fR \- Run a command or interactive session on multiple remote hosts -. -.SH "SYNOPSIS" -\fBknife\fR \fBssh QUERY COMMAND\fR \fI(options)\fR +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. . +.sp +The \fBknife ssh\fP subcommand is used to invoke SSH commands (in parallel) on a subset of nodes within an organization, based on the results of a search query. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-a\fR, \fB\-\-attribute ATTR\fR -The attribute to use for opening the connection \- default is fqdn -. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. .TP -\fB\-C\fR, \fB\-\-concurrency NUM\fR -The number of concurrent connections -. +.B \fB\-\-color\fP +Indicates that colored output will be used. .TP -\fB\-m\fR, \fB\-\-manual\-list\fR -QUERY is a space separated list of servers -. +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. .TP -\fB\-P\fR, \fB\-\-ssh\-password PASSWORD\fR -The ssh password -. +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. .TP -\fB\-x\fR, \fB\-\-ssh\-user USERNAME\fR -The ssh username -. +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. .TP -\fB\-i\fR, \fB\-\-identity\-file IDENTITY_FILE\fR -The SSH identity file used for authentication -. +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. .TP -\fB\-p\fR, \fB\-\-ssh\-port PORT\fR -The ssh port -. +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. .TP -\fB\-\-[no\-]host\-key\-verify\fR -Verify host key, enabled by default\. -. -.SH "DESCRIPTION" -The \fIssh\fR sub\-command opens an ssh session to each of the nodes in the search results of the \fIQUERY\fR\. This sub\-command requires that the net\-ssh\-multi and highline Ruby libraries are installed\. On Debian systems, these are the libnet\-ssh\-multi\-ruby and libhighline\-ruby packages\. They can also be installed as RubyGems (net\-ssh\-multi and highline, respectively)\. -. -.SH "TERMINAL MULTIPLEXING AND TERMINAL TAB SUPPORT" -\fBknife ssh\fR integrates with several terminal multiplexer programs to provide a more convenient means of managing multiple ssh sessions\. When the \fICOMMAND\fR option matches one of these, \fBknife ssh\fR will create multiple interactive ssh sessions running locally in the terminal multiplexer instead of invoking the command on the remote host\. -. -.P -The available multiplexers are: -. +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. .TP -\fBinteractive\fR -A built\-in multiplexer\. \fBinteractive\fR supports running commands on a subset of the connected hosts in parallel -. +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. .TP -\fBscreen\fR(1) -Runs ssh interactively inside \fBscreen\fR\. ~/\.screenrc will be sourced if it exists\. -. +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. .TP -\fBtmux\fR(1) -Runs ssh interactively inside tmux\. -. +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. .TP -\fBmacterm\fR (Mac OS X only) -Opens a Terminal\.app window and creates a tab for each ssh session\. You must install the rb\-appscript gem before you can use this option\. -. -.SH "SEE ALSO" -\fBknife\-search\fR(1) -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife ssh SEARCH_QUERY SSH_COMMAND (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-a SSH_ATTR\fP, \fB\-\-attribute SSH_ATTR\fP +The attribute that is used when opening the SSH connection. The default attribute is the FQDN of the host. Other possible values include a public IP address, a private IP address, or a hostname. +.TP +.B \fB\-C NUM\fP, \fB\-\-concurrency NUM\fP +The number of allowed concurrent connections. +.TP +.B \fB\-G GATEWAY\fP, \fB\-\-ssh\-gateway GATEWAY\fP +The SSH tunnel or gateway that is used to run a bootstrap action on a machine that is not accessible from the workstation. +.TP +.B \fB\-i IDENTITY_FILE\fP, \fB\-\-identity\-file IDENTIFY_FILE\fP +The SSH identity file used for authentication. Key\-based authentication is recommended. +.TP +.B \fB\-m\fP, \fB\-\-manual\-list\fP +Indicates that a search query is a space\-separated list of servers. If there is more than one item in the list, put quotes around the entire list. For example: \fB\-\-manual\-list "server01 server 02 server 03"\fP +.TP +.B \fB\-\-[no\-]host\-key\-verify\fP +Use \fB\-\-no\-host\-key\-verify\fP to disable host key verification. Default setting: \fB\-\-host\-key\-verify\fP. +.TP +.B \fBOTHER\fP +The shell type. Possible values: \fBinteractive\fP, \fBscreen\fP, \fBtmux\fP, \fBmacterm\fP, or \fBcssh\fP. (\fBcsshx\fP is deprecated in favor of \fBcssh\fP.) +.TP +.B \fB\-p PORT\fP, \fB\-\-ssh\-port PORT\fP +The SSH port. +.TP +.B \fB\-P PASSWORD\fP, \fB\-\-ssh\-password PASSWORD\fP +The SSH password. This can be used to pass the password directly on the command line. If this option is not specified (and a password is required) Knife will prompt for the password. +.TP +.B \fBSEARCH_QUERY\fP +The search query used to return a list of servers to be accessed using SSH and the specified \fBSSH_COMMAND\fP. This option uses the same syntax as the search sub\-command. +.TP +.B \fBSSH_COMMAND\fP +The command that will be run against the results of a search query. +.TP +.B \fB\-x USER_NAME\fP, \fB\-\-ssh\-user USER_NAME\fP +The SSH user name. +.UNINDENT +.sp +\fBExamples\fP +.sp +To find the uptime of all of web servers running Ubuntu on the Amazon EC2 platform, enter: +.sp +.nf +.ft C +$ knife ssh "role:web" "uptime" \-x ubuntu \-a ec2.public_hostname +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +ec2\-174\-129\-127\-206.compute\-1.amazonaws.com 13:50:47 up 1 day, 23:26, 1 user, load average: 0.25, 0.18, 0.11 +ec2\-67\-202\-63\-102.compute\-1.amazonaws.com 13:50:47 up 1 day, 23:33, 1 user, load average: 0.12, 0.13, 0.10 +ec2\-184\-73\-9\-250.compute\-1.amazonaws.com 13:50:48 up 16:45, 1 user, load average: 0.30, 0.22, 0.13 +ec2\-75\-101\-240\-230.compute\-1.amazonaws.com 13:50:48 up 1 day, 22:59, 1 user, load average: 0.24, 0.17, 0.11 +ec2\-184\-73\-60\-141.compute\-1.amazonaws.com 13:50:48 up 1 day, 23:30, 1 user, load average: 0.32, 0.17, 0.15 +.ft P +.fi +.sp +To run the chef\-client on all nodes, enter: +.sp +.nf +.ft C +$ knife ssh \(aqname:*\(aq \(aqsudo chef\-client\(aq +.ft P +.fi +.sp +To force a chef\-client run on all of the web servers running Ubuntu on the Amazon EC2 platform, enter: +.sp +.nf +.ft C +$ knife ssh "role:web" "sudo chef\-client" \-x ubuntu \-a ec2.public_hostname +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +ec2\-67\-202\-63\-102.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:37 +0000] INFO: Starting Chef Run (Version 0.9.10) +ec2\-174\-129\-127\-206.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:37 +0000] INFO: Starting Chef Run (Version 0.9.10) +ec2\-184\-73\-9\-250.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:38 +0000] INFO: Starting Chef Run (Version 0.9.10) +ec2\-75\-101\-240\-230.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:38 +0000] INFO: Starting Chef Run (Version 0.9.10) +ec2\-184\-73\-60\-141.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:38 +0000] INFO: Starting Chef Run (Version 0.9.10) +ec2\-174\-129\-127\-206.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:39 +0000] INFO: Chef Run complete in 1.419243 seconds +ec2\-174\-129\-127\-206.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:39 +0000] INFO: cleaning the checksum cache +ec2\-174\-129\-127\-206.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:39 +0000] INFO: Running report handlers +ec2\-174\-129\-127\-206.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:39 +0000] INFO: Report handlers complete +ec2\-67\-202\-63\-102.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:39 +0000] INFO: Chef Run complete in 1.578265 seconds +ec2\-67\-202\-63\-102.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:39 +0000] INFO: cleaning the checksum cache +ec2\-67\-202\-63\-102.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:39 +0000] INFO: Running report handlers +ec2\-67\-202\-63\-102.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:39 +0000] INFO: Report handlers complete +ec2\-184\-73\-9\-250.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: Chef Run complete in 1.638884 seconds +ec2\-184\-73\-9\-250.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: cleaning the checksum cache +ec2\-184\-73\-9\-250.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: Running report handlers +ec2\-184\-73\-9\-250.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: Report handlers complete +ec2\-75\-101\-240\-230.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: Chef Run complete in 1.540257 seconds +ec2\-75\-101\-240\-230.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: cleaning the checksum cache +ec2\-75\-101\-240\-230.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: Running report handlers +ec2\-75\-101\-240\-230.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: Report handlers complete +ec2\-184\-73\-60\-141.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: Chef Run complete in 1.502489 seconds +ec2\-184\-73\-60\-141.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: cleaning the checksum cache +ec2\-184\-73\-60\-141.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: Running report handlers +ec2\-184\-73\-60\-141.compute\-1.amazonaws.com [Fri, 22 Oct 2010 14:18:40 +0000] INFO: Report handlers complete +.ft P +.fi +.sp +To query for all nodes that have the "webserver" role and then use SSH to run the command "sudo chef\-client", enter: +.sp +.nf +.ft C +$ knife ssh "role:webserver" "sudo chef\-client" +.ft P +.fi +.sp +To upgrade all nodes, enter: +.sp +.nf +.ft C +$ knife ssh name:* "sudo aptitude upgrade \-y" +.ft P +.fi +.sp +To specify the shell type used on the nodes returned by a search query: +.sp +.nf +.ft C +$ knife ssh roles:opscode\-omnitruck macterm +.ft P +.fi +.sp +where \fBscreen\fP is one of the following values: \fBcssh\fP, \fBinteractive\fP, \fBmacterm\fP, \fBscreen\fP, or \fBtmux\fP. If the node does not have the shell type installed, Knife will return an error similar to the following: +.sp +.nf +.ft C +you need the rb\-appscript gem to use knife ssh macterm. +\(ga(sudo) gem install rb\-appscript\(ga to install +ERROR: LoadError: cannot load such file \-\- appscript +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-status.1 b/distro/common/man/man1/knife-status.1 index e658e6179a..b61f877b71 100644 --- a/distro/common/man/man1/knife-status.1 +++ b/distro/common/man/man1/knife-status.1 @@ -1,29 +1,209 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 +.TH "KNIFE-STATUS" "1" "Chef 11.8" "" "knife status" +.SH NAME +knife-status \- The man page for the knife status subcommand. . -.TH "KNIFE\-STATUS" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.nr rst2man-indent-level 0 . -.SH "NAME" -\fBknife\-status\fR \- Display status information for the nodes in your infrastructure -. -.SH "SYNOPSIS" -\fBknife\fR \fBstatus\fR \fI(options)\fR +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. . +.sp +The \fBknife status\fP subcommand is used to display a brief summary of the nodes on a server, including the time of the most recent successful chef\-client run. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 .TP -\fB\-r\fR, \fB\-\-run\-list RUN_LIST\fR -Show the run list -. -.SH "DESCRIPTION" -The \fIstatus\fR sub\-command searches the Chef Server for all nodes and displays information about the last time the node checked into the server and executed a \fBnode\.save\fR\. The fields displayed are the relative checkin time, the node name, it\'s operating system platform and version, the fully\-qualified domain name and the default IP address\. If the \fB\-r\fR option is given, the node\'s run list will also be displayed\. Note that depending on the configuration of the nodes, the FQDN and IP displayed may not be publicly reachable\. -. -.SH "SEE ALSO" -\fBknife\-search\fR(1) -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Joshua Timberman \fIjoshua@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife status (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fBQUERY\fP +The search query used to identify a a list of items on a server. This option uses the same syntax as the \fBsearch\fP sub\-command. +.TP +.B \fB\-H\fP, \fB\-\-hide\-healthy\fP +Indicates that nodes on which a chef\-client run has occurred within the previous hour will be hidden. +.TP +.B \fB\-r RUN_LIST\fP, \fB\-\-run\-list RUN_LIST\fP +A comma\-separated list of roles and/or recipes to be applied. +.TP +.B \fB\-s\fP, \fB\-\-sort\-reverse\fP +Indicates that the list will be sorted by last run time, descending. +.UNINDENT +.sp +\fBExamples\fP +.sp +To include run lists in the status, enter: +.sp +.nf +.ft C +$ knife status \-\-run\-list +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +20 hours ago, dev\-vm.chisamore.com, ubuntu 10.04, dev\-vm.chisamore.com, 10.66.44.126, role[lb]. +3 hours ago, i\-225f954f, ubuntu 10.04, ec2\-67\-202\-63\-102.compute\-1.amazonaws.com, 67.202.63.102, role[web]. +3 hours ago, i\-a45298c9, ubuntu 10.04, ec2\-174\-129\-127\-206.compute\-1.amazonaws.com, 174.129.127.206, role[web]. +3 hours ago, i\-5272a43f, ubuntu 10.04, ec2\-184\-73\-9\-250.compute\-1.amazonaws.com, 184.73.9.250, role[web]. +3 hours ago, i\-226ca64f, ubuntu 10.04, ec2\-75\-101\-240\-230.compute\-1.amazonaws.com, 75.101.240.230, role[web]. +3 hours ago, i\-f65c969b, ubuntu 10.04, ec2\-184\-73\-60\-141.compute\-1.amazonaws.com, 184.73.60.141, role[web]. +.ft P +.fi +.sp +To show only the status nodes on which the chef\-client ran within the past hour, enter: +.sp +.nf +.ft C +$ knife status \-\-hide\-healthy +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +1 hour ago, i\-256f884f, ubuntu 12.04, ec2\-67\-202\-63\-102.compute\-1.amazonaws.com, 67.202.63.102, role[web]. +1 hour ago, i\-a47823c9, ubuntu 10.04, ec2\-174\-129\-127\-206.compute\-1.amazonaws.com, 184.129.143.111, role[lb]. +.ft P +.fi +.sp +To show the status of a subset of nodes that are returned by a specific query, enter: +.sp +.nf +.ft C +$ knife status "role:web" \-\-run\-list +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +3 hours ago, i\-225f954f, ubuntu 10.04, ec2\-67\-202\-63\-102.compute\-1.amazonaws.com, 67.202.63.102, role[web]. +3 hours ago, i\-a45298c9, ubuntu 10.04, ec2\-174\-129\-127\-206.compute\-1.amazonaws.com, 174.129.127.206, role[web]. +3 hours ago, i\-5272a43f, ubuntu 10.04, ec2\-184\-73\-9\-250.compute\-1.amazonaws.com, 184.73.9.250, role[web]. +3 hours ago, i\-226ca64f, ubuntu 10.04, ec2\-75\-101\-240\-230.compute\-1.amazonaws.com, 75.101.240.230, role[web]. +3 hours ago, i\-f65c969b, ubuntu 10.04, ec2\-184\-73\-60\-141.compute\-1.amazonaws.com, 184.73.60.141, role[web]. +.ft P +.fi +.sp +To view the status of all nodes in the organization, enter: +.sp +.nf +.ft C +$ knife status +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +20 hours ago, dev\-vm.chisamore.com, ubuntu 10.04, dev\-vm.chisamore.com, 10.66.44.126 +3 hours ago, i\-225f954f, ubuntu 10.04, ec2\-67\-202\-63\-102.compute\-1.amazonaws.com, 67.202.63.102 +3 hours ago, i\-a45298c9, ubuntu 10.04, ec2\-174\-129\-127\-206.compute\-1.amazonaws.com, 174.129.127.206 +3 hours ago, i\-5272a43f, ubuntu 10.04, ec2\-184\-73\-9\-250.compute\-1.amazonaws.com, 184.73.9.250 +3 hours ago, i\-226ca64f, ubuntu 10.04, ec2\-75\-101\-240\-230.compute\-1.amazonaws.com, 75.101.240.230 +3 hours ago, i\-f65c969b, ubuntu 10.04, ec2\-184\-73\-60\-141.compute\-1.amazonaws.com, 184.73.60.141 +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-tag.1 b/distro/common/man/man1/knife-tag.1 index eccccaeb26..135969b393 100644 --- a/distro/common/man/man1/knife-tag.1 +++ b/distro/common/man/man1/knife-tag.1 @@ -1,43 +1,182 @@ -.\" generated with Ronn/v0.7.3 -.\" http://github.com/rtomayko/ronn/tree/0.7.3 +.TH "KNIFE-TAG" "1" "Chef 11.8" "" "knife tag" +.SH NAME +knife-tag \- The man page for the knife tag subcommand. . -.TH "KNIFE\-TAG" "1" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.nr rst2man-indent-level 0 . -.SH "NAME" -\fBknife\-tag\fR \- Apply tags to nodes on a Chef Server +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. . -.SH "SYNOPSIS" -\fBknife\fR \fBtag\fR \fIsubcommand\fR \fI(options)\fR +.sp +A tag is a custom description that is applied to a node. A tag, once applied, can be helpful when managing nodes using Knife or when building recipes by providing alternate methods of grouping similar types of information. +.sp +The \fBknife tag\fP subcommand is used to apply tags to nodes on a server. +.sp +This subcommand has the following syntax: +.sp +.nf +.ft C +$ knife tag [ARGUMENT] +.ft P +.fi +.SH COMMON OPTIONS +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.SH CREATE +.sp +The \fBcreate\fP argument is used to add one or more tags to a node. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife tag create NODE_NAME [TAG...] +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To create tags named "seattle", "portland", and "vancouver", enter: +.sp +.nf +.ft C +$ knife tag create node seattle portland vancouver +.ft P +.fi +.SH DELETE +.sp +The \fBdelete\fP argument is used to delete one or more tags from a node. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife tag delete NODE_NAME [TAG...] +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To delete tags named "denver" and "phoenix", enter: +.sp +.nf +.ft C +$ knife tag delete node denver phoenix +.ft P +.fi +.sp +Type \fBY\fP to confirm a deletion. +.SH LIST +.sp +The \fBlist\fP argument is used to list all of the tags that have been applied to a node. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife tag list [NODE_NAME...] +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. . -.SH "TAG SUBCOMMANDS" -The following \fBtag\fR subcommands are available: -. -.SH "CREATE" -\fBknife tag create\fR \fInode\fR \fItag\fR [\fI\.\.\.\fR] -. -.P -Adds one or more tags to \fInode\fR -. -.SH "DELETE" -\fBknife tag delete\fR \fInode\fR \fItag\fR [\fI\.\.\.\fR] -. -.P -Removes one or more tags from \fInode\fR -. -.SH "LIST" -\fBknife tag list\fR \fInode\fR -. -.P -Lists the tags applied to \fInode\fR -. -.SH "SEE ALSO" -\fBknife\-node(1)\fR -. -.SH "AUTHOR" -Chef was written by Adam Jacob \fIadam@opscode\.com\fR with many contributions from the community\. -. -.SH "DOCUMENTATION" -This manual page was written by Daniel DeLeo \fIdan@opscode\.com\fR\. Permission is granted to copy, distribute and / or modify this document under the terms of the Apache 2\.0 License\. -. -.SH "CHEF" -Knife is distributed with Chef\. \fIhttp://wiki\.opscode\.com/display/chef/Home\fR diff --git a/distro/common/man/man1/knife-upload.1 b/distro/common/man/man1/knife-upload.1 new file mode 100644 index 0000000000..91ebb198d5 --- /dev/null +++ b/distro/common/man/man1/knife-upload.1 @@ -0,0 +1,241 @@ +.TH "KNIFE-UPLOAD" "1" "Chef 11.8" "" "knife upload" +.SH NAME +knife-upload \- The man page for the knife upload subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife upload\fP subcommand is used to upload roles, cookbooks, environments, and data bags to the server from the current working directory in the chef\-repo. This subcommand is often used in conjunction with \fBknife diff\fP, which can be used to see exactly what changes will be uploaded, and then \fBknife download\fP, which does the opposite of \fBknife upload\fP. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife upload [PATTERN...] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-chef\-repo\-path PATH\fP +The path to the chef\-repo. This setting will override the default path to the chef\-repo. Default: same as specified by \fBchef_repo_path\fP in config.rb. +.TP +.B \fB\-\-concurrency\fP +The number of allowed concurrent connections. Default: \fB10\fP. +.TP +.B \fB\-\-[no\-]force\fP +Use \fB\-\-force\fP to upload roles, cookbooks, etc. even if the file in the directory is identical (by default, no \fBPOST\fP or \fBPUT\fP is performed unless an actual change would be made). Default: \fB\-\-no\-force\fP. +.TP +.B \fB\-n\fP, \fB\-\-dry\-run\fP +Indicates that no action is taken and that results are only printed out. Default: \fBfalse\fP. +.TP +.B \fB\-\-[no\-]diff\fP +Indicates that only new and modified files will be uploaded. Set to \fBfalse\fP to upload all files. Default: \fBtrue\fP. +.TP +.B \fB\-\-[no\-]freeze\fP +Indicates that a cookbook cannot be modified; any changes to this cookbook must be included as a new version. Only the \fB\-\-force\fP option can override this setting. Default: \fBfalse\fP. +.TP +.B \fB\-\-[no\-]purge\fP +Use \fB\-\-purge\fP to delete roles, cookbooks, etc. from the server if their corresponding files do not exist in the chef\-repo. By default, such objects are left alone and NOT purged. Default: \fB\-\-no\-purge\fP. +.TP +.B \fB\-\-[no\-]recurse\fP +Use \fB\-\-no\-recurse\fP to disable uploading a directory recursively. Default: \fB\-\-recurse\fP. +.TP +.B \fB\-\-repo\-mode MODE\fP +The layout of the local chef\-repo. Possible values: \fBstatic\fP, \fBeverything\fP, or \fBhosted_everything\fP. Use \fBstatic\fP for just roles, environments, cookbooks, and data bags. By default, \fBeverything\fP and \fBhosted_everything\fP are dynamically selected depending on the server type. Default: \fBeverything\fP / \fBhosted_everything\fP. +.UNINDENT +.sp +\fBExamples\fP +.sp +To upload the entire chef\-repo to the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife upload +.ft P +.fi +.sp +or from anywhere in the chef\-repo, enter: +.sp +.nf +.ft C +$ knife upload / +.ft P +.fi +.sp +To upload the \fBcookbooks/\fP directory to the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife upload cookbooks +.ft P +.fi +.sp +or from anywhere in the chef\-repo, enter: +.sp +.nf +.ft C +$ knife upload /cookbooks +.ft P +.fi +.sp +To upload the \fBenvironments/\fP directory to the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife upload environments +.ft P +.fi +.sp +or from anywhere in the chef\-repo, enter: +.sp +.nf +.ft C +$ knife upload /environments +.ft P +.fi +.sp +To upload an environment named "production" to the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife upload environments/production.json +.ft P +.fi +.sp +or from the \fBenvironments/\fP directory, enter: +.sp +.nf +.ft C +$ knife upload production.json +.ft P +.fi +.sp +To upload the \fBroles/\fP directory to the server, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife upload roles +.ft P +.fi +.sp +or from anywhere in the chef\-repo, enter: +.sp +.nf +.ft C +$ knife upload /roles +.ft P +.fi +.sp +To upload all cookbooks that start with "apache" and belong to the "webserver" role, browse to the top level of the chef\-repo and enter: +.sp +.nf +.ft C +$ knife upload cookbooks/apache\e* roles/webserver.json +.ft P +.fi +.sp +Use the output of \fBknife deps\fP to pass a command to \fBknife upload\fP. For example: +.sp +.nf +.ft C +$ knife upload \(gaknife deps nodes/*.json\(ga +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-user.1 b/distro/common/man/man1/knife-user.1 new file mode 100644 index 0000000000..7d6fada5ce --- /dev/null +++ b/distro/common/man/man1/knife-user.1 @@ -0,0 +1,319 @@ +.TH "KNIFE-USER" "1" "Chef 11.8" "" "knife user" +.SH NAME +knife-user \- The man page for the knife user subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife user\fP subcommand is used to manage the list of users and their associated RSA public key\-pairs. +.IP Note +This subcommand ONLY works when run against the open source server and will not run against Enterprise Chef (including hosted Enterprise Chef), or Private Chef. +.RE +.sp +This subcommand has the following syntax: +.sp +.nf +.ft C +$ knife user [ARGUMENT] (options) +.ft P +.fi +.SH COMMON OPTIONS +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.SH CREATE +.sp +The \fBcreate\fP argument is used to create a user. This process will generate an RSA key pair for the named user. The public key will be stored on the server and the private key will be displayed on \fBSTDOUT\fP or written to a named file. +.INDENT 0.0 +.IP \(bu 2 +For the user, the private key should be copied to the system as /etc/chef/client.pem. +.IP \(bu 2 +For Knife, the private key is typically copied to ~/.chef/client_name.pem and referenced in the knife.rb configuration file. +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife user create USER_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a\fP, \fB\-\-admin\fP +Indicates that a client will be created as an admin client. This is required when users of the open source server need to access the Chef Server API as an administrator. This option only works when used with the open source server and will have no effect when used with Hosted Chef or Private Chef. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-user\-key FILE_NAME\fP +All users are assigned a public key. Use to write the public key to a file. +.UNINDENT +.sp +\fBExamples\fP +.sp +To create a new user named "Radio Birdman" with a private key saved to "/keys/user_name", enter: +.sp +.nf +.ft C +$ knife user create "Radio Birdman" \-f /keys/user_name +.ft P +.fi +.SH DELETE +.sp +The \fBdelete\fP argument is used to delete a registered user. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife user delete USER_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +To delete a user named "Steve Danno", enter: +.sp +.nf +.ft C +$ knife user delete "Steve Danno" +.ft P +.fi +.SH EDIT +.sp +The \fBedit\fP argument is used to edit the details of a user. When this argument is run, Knife will open $EDITOR. When finished, Knife will update the server with those changes. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife user edit USER_NAME +.ft P +.fi +.sp +\fBOptions\fP +.sp +This command does not have any specific options. +.sp +\fBExamples\fP +.sp +None. +.SH LIST +.sp +The \fBlist\fP argument is used to view a list of registered users. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife user list (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-w\fP, \fB\-\-with\-uri\fP +Indicates that the corresponding URIs will be shown. +.UNINDENT +.sp +\fBExamples\fP +.sp +None. +.SH REREGISTER +.sp +The \fBreregister\fP argument is used to regenerate an RSA key pair for a user. The public key will be stored on the server and the private key will be displayed on \fBSTDOUT\fP or written to a named file. +.IP Note +Running this argument will invalidate the previous RSA key pair, making it unusable during authentication to the server. +.RE +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife user reregister USER_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.UNINDENT +.sp +\fBExamples\fP +.sp +To regenerate the RSA key pair for a user named "Robert Younger", enter: +.sp +.nf +.ft C +$ knife user reregister "Robert Younger" +.ft P +.fi +.SH SHOW +.sp +The \fBshow\fP argument is used to show the details of a user. +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife user show USER_NAME (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This argument has the following options: +.INDENT 0.0 +.TP +.B \fB\-a ATTR\fP, \fB\-\-attribute ATTR\fP +The attribute (or attributes) to show. +.UNINDENT +.sp +\fBExamples\fP +.sp +To view a user named "Dennis Teck", enter: +.sp +.nf +.ft C +$ knife user show "Dennis Teck" +.ft P +.fi +.sp +to return something like: +.sp +.nf +.ft C +chef_type: user +json_class: Chef::User +name: Dennis Teck +public_key: +.ft P +.fi +.sp +To view information in JSON format, use the \fB\-F\fP common option as part of the command like this: +.sp +.nf +.ft C +$ knife user show "Dennis Teck" \-F json +.ft P +.fi +.sp +Other formats available include \fBtext\fP, \fByaml\fP, and \fBpp\fP. +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife-xargs.1 b/distro/common/man/man1/knife-xargs.1 new file mode 100644 index 0000000000..68710a19df --- /dev/null +++ b/distro/common/man/man1/knife-xargs.1 @@ -0,0 +1,168 @@ +.TH "KNIFE-XARGS" "1" "Chef 11.8" "" "knife xargs" +.SH NAME +knife-xargs \- The man page for the knife xargs subcommand. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.\" Man page generated from reStructuredText. +. +.sp +The \fBknife xargs\fP subcommand is used to build and execute command lines against objects on a server using standard input. +.sp +\fBCommon Options\fP +.sp +The following options can be run with all Knife sub\-commands and plug\-ins: +.INDENT 0.0 +.TP +.B \fB\-c CONFIG\fP, \fB\-\-config CONFIG\fP +The configuration file to use. +.TP +.B \fB\-\-color\fP +Indicates that colored output will be used. +.TP +.B \fB\-d\fP, \fB\-\-disable\-editing\fP +Indicates that $EDITOR will not be opened; data will be accepted as\-is. +.TP +.B \fB\-\-defaults\fP +Indicates that Knife will use the default value, instead of asking a user to provide one. +.TP +.B \fB\-e EDITOR\fP, \fB\-\-editor EDITOR\fP +The $EDITOR that is used for all interactive commands. +.TP +.B \fB\-E ENVIRONMENT\fP, \fB\-\-environment ENVIRONMENT\fP +The name of the environment. When this option is added to a command, the command will run only against the named environment. +.TP +.B \fB\-f FILE_NAME\fP, \fB\-\-file FILE_NAME\fP +Indicates that the private key will be saved to a specified file name. +.TP +.B \fB\-F FORMAT\fP, \fB\-\-format FORMAT\fP +The output format: \fBsummary\fP (default), \fBtext\fP, \fBjson\fP, \fByaml\fP, and \fBpp\fP. +.TP +.B \fB\-h\fP, \fB\-\-help\fP +Shows help for the command. +.TP +.B \fB\-k KEY\fP, \fB\-\-key KEY\fP +The private key that Knife will use to sign requests made by the API client to the server. +.TP +.B \fB\-\-no\-color\fP +Indicates that color will not be used in the output. +.TP +.B \fB\-p PASSWORD\fP, \fB\-\-password PASSWORD\fP +The user password. +.TP +.B \fB\-\-print\-after\fP +Indicates that data will be shown after a destructive operation. +.TP +.B \fB\-s URL\fP, \fB\-\-server\-url URL\fP +The URL for the server. +.TP +.B \fB\-u USER\fP, \fB\-\-user USER\fP +The user name used by Knife to sign requests made by the API client to the server. Authentication will fail if the user name does not match the private key. +.TP +.B \fB\-v\fP, \fB\-\-version\fP +The version of the chef\-client. +.TP +.B \fB\-V\fP, \fB\-\-verbose\fP +Set for more verbose outputs. Use \fB\-VV\fP for maximum verbosity. +.TP +.B \fB\-y\fP, \fB\-\-yes\fP +Indicates that the response to all confirmation prompts will be "Yes" (and that Knife will not ask for confirmation). +.UNINDENT +.sp +\fBSyntax\fP +.sp +This argument has the following syntax: +.sp +.nf +.ft C +$ knife xargs [PATTERN...] (options) +.ft P +.fi +.sp +\fBOptions\fP +.sp +This subcommand has the following options: +.INDENT 0.0 +.TP +.B \fB\-\-chef\-repo\-path PATH\fP +The path to the chef\-repo. This setting will override the default path to the chef\-repo. Default: same as specified by \fBchef_repo_path\fP in config.rb. +.TP +.B \fB\-\-concurrency\fP +The number of allowed concurrent connections. Default: \fB10\fP. +.TP +.B \fB\-\-[no\-]diff\fP +Use to show a diff when a file changes. Default: \fB\-\-diff\fP. +.TP +.B \fB\-\-dry\-run\fP +Use to prevent changes from being uploaded to the server. Default: \fBfalse\fP. +.TP +.B \fB\-\-[no\-]force\fP +Use to force the upload of files even if they haven\(aqt been changed. Default: \fB\-\-no\-force\fP. +.TP +.B \fB\-\-local\fP +Indicates that a command line will be built or executed against a local file. Set to \fBfalse\fP to build or execute against a remote file. Default: \fBfalse\fP. +.TP +.B \fB\-n MAX_ARGS\fP, \fB\-\-max\-args MAX_ARGS\fP +The maximum number of arguments per command line. Default: \fBnil\fP. +.TP +.B \fB\-s LENGTH\fP, \fB\-\-max\-chars LENGTH\fP +The maximum size (in characters) for a command line. Default: \fBnil\fP. +.TP +.B \fB\-0\fP +Indicates that a \fBNULL\fP character (\fB\e0\fP) will be used as a separator, instead of white space. Default: \fBfalse\fP. +.TP +.B \fB\-p [PATTERN...]\fP, \fB\-\-pattern [PATTERN...]\fP +One (or more) patterns for a command line. If this option is not specified, a list of patterns may be expected on standard input. Default: \fBnil\fP. +.TP +.B \fB\-I REPLACE_STRING\fP, \fB\-\-replace REPLACE_STRING\fP +Use to define a string that will be used to replace all occurrences of a file name. Default: \fBnil\fP. +.TP +.B \fB\-J REPLACE_STRING\fP, \fB\-\-replace\-first REPLACE_STRING\fP +Use to define a string that will be used to replace the first occurrence of a file name. Default: \fBnil\fP. +.TP +.B \fB\-\-repo\-mode MODE\fP +The layout of the local chef\-repo. Possible values: \fBstatic\fP, \fBeverything\fP, or \fBhosted_everything\fP. Use \fBstatic\fP for just roles, environments, cookbooks, and data bags. By default, \fBeverything\fP and \fBhosted_everything\fP are dynamically selected depending on the server type. Default value: \fBdefault\fP. +.TP +.B \fB\-t\fP +Indicates that the print command will be run on the command line. Default: \fBnil\fP. +.UNINDENT +.sp +\fBExamples\fP +.sp +To use the output of \fBknife deps\fP to pass a command to \fBknife xargs\fP. For example: +.sp +.nf +.ft C +$ knife deps nodes/*.json | xargs knife upload +.ft P +.fi +.SH AUTHOR +Opscode +.SH COPYRIGHT +This work is licensed under a Creative Commons Attribution 3.0 Unported License +.\" Generated by docutils manpage writer. +. diff --git a/distro/common/man/man1/knife.1 b/distro/common/man/man1/knife.1 index 5a84ef966c..a8ce1c10fd 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "KNIFE" "1" "July 2013" "Chef 11.8.0.alpha.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 1a36e88260..b0e8eac533 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "CHEF\-CLIENT" "8" "July 2013" "Chef 11.8.0.alpha.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 10bc7a635d..6ab31d46c4 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "CHEF\-EXPANDER" "8" "July 2013" "Chef 11.8.0.alpha.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 50d2938e08..f2e88a426f 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "CHEF\-EXPANDERCTL" "8" "July 2013" "Chef 11.8.0.alpha.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 d6a29454dc..3f2157216c 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "CHEF\-SERVER\-WEBUI" "8" "July 2013" "Chef 11.8.0.alpha.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 d83e9797be..ce928d6f63 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "CHEF\-SERVER" "8" "July 2013" "Chef 11.8.0.alpha.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 b239963372..30c5956825 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "CHEF\-SOLO" "8" "July 2013" "Chef 11.8.0.alpha.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 ee7208c9de..28c8e92cf3 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" "August 2013" "Chef 11.6.0.hotfix.1" "Chef Manual" +.TH "CHEF\-SOLR" "8" "July 2013" "Chef 11.8.0.alpha.0" "Chef Manual" . .SH "NAME" \fBchef\-solr\fR \- Runs as Chef\'s search server diff --git a/distro/common/markdown/man1/knife-bootstrap.mkd b/distro/common/markdown/man1/knife-bootstrap.mkd index c466fc7f7f..5c5e456023 100644 --- a/distro/common/markdown/man1/knife-bootstrap.mkd +++ b/distro/common/markdown/man1/knife-bootstrap.mkd @@ -32,7 +32,7 @@ __knife__ __bootstrap__ _(options)_ * `--[no-]host-key-verify`: Enable host key verification, which is the default behavior. * `--hint HINT_NAME[=HINT_FILE]`: - Provide the name of a hint (with option JSON file) to set for use by + Provide the name of a hint (with option JSON file) to set for use by Ohai plugins. ## DESCRIPTION diff --git a/distro/common/markdown/man1/knife-configure.mkd b/distro/common/markdown/man1/knife-configure.mkd index cc7dd1d96e..507d30db4e 100644 --- a/distro/common/markdown/man1/knife-configure.mkd +++ b/distro/common/markdown/man1/knife-configure.mkd @@ -35,17 +35,17 @@ the specified _directory_. field blank to accept the default value. On most systems, the default values are acceptable. - user@host$ knife configure -i - Please enter the chef server URL: [http://localhost:4000] - Please enter a clientname for the new client: [username] - Please enter the existing admin clientname: [chef-webui] - Please enter the location of the existing admin client's private key: [/etc/chef/webui.pem] - Please enter the validation clientname: [chef-validator] - Please enter the location of the validation key: [/etc/chef/validation.pem] - Please enter the path to a chef repository (or leave blank): - Creating initial API user... - Created (or updated) client[username] - Configuration file written to /home/username/.chef/knife.rb + user@host$ knife configure -i + Please enter the chef server URL: [http://localhost:4000] + Please enter a clientname for the new client: [username] + Please enter the existing admin clientname: [chef-webui] + Please enter the location of the existing admin client's private key: [/etc/chef/webui.pem] + Please enter the validation clientname: [chef-validator] + Please enter the location of the validation key: [/etc/chef/validation.pem] + Please enter the path to a chef repository (or leave blank): + Creating initial API user... + Created (or updated) client[username] + Configuration file written to /home/username/.chef/knife.rb This creates a new administrator client named _username_, writes a configuration file to _/home/username/.chef/knife.rb_, and the diff --git a/distro/common/markdown/man1/knife-cookbook.mkd b/distro/common/markdown/man1/knife-cookbook.mkd index 4f714c52f6..deaf00447a 100644 --- a/distro/common/markdown/man1/knife-cookbook.mkd +++ b/distro/common/markdown/man1/knife-cookbook.mkd @@ -117,11 +117,11 @@ __knife cookbook create cookbook__ _(options)_ the directory where the cookbook will be created * `-r`, `--readme-format format`: format of the readme file md, mkd, txt, rdoc - * `-c`, `--copyright copyright`: + * `-C`, `--copyright copyright`: name of copyright holder * `-i`, `--license license`: license for cookbook, apachev2 or none - * `-e`, `--email email`: + * `-m`, `--email email`: email address of cookbook maintainer this is a helper command that creates a new cookbook directory in the @@ -143,7 +143,7 @@ supported readme formats are 'md' (default), 'mkd', 'txt', 'rdoc'. the readme file will be written with the specified extension and a set of helpful starting headers. -specify `-c` or `--copyright` with the name of the copyright holder as +specify `-C` or `--copyright` with the name of the copyright holder as your name or your company/organization name in a quoted string. if this value is not specified an all-caps string `your_company_name` is used which can be easily changed with find/replace. @@ -156,7 +156,7 @@ the cookbook and follow any restrictions they describe. when using are pre-filled. the `none` license will be treated as non-redistributable. -specify `-e` or `--email` with the email address of the cookbook's +specify `-m` or `--email` with the email address of the cookbook's maintainer. if this value is not specified, an all-caps string `your_email` is used which can easily be changed with find/replace. diff --git a/distro/common/markdown/man8/chef-expander.mkd b/distro/common/markdown/man8/chef-expander.mkd index d72ee1df9f..9190a9aebb 100644 --- a/distro/common/markdown/man8/chef-expander.mkd +++ b/distro/common/markdown/man8/chef-expander.mkd @@ -79,4 +79,4 @@ granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License. On Debian systems, the complete text of the Apache 2.0 License can be -found in /usr/share/common-licenses/Apache-2.0.
\ No newline at end of file +found in /usr/share/common-licenses/Apache-2.0. diff --git a/distro/common/markdown/man8/chef-expanderctl.mkd b/distro/common/markdown/man8/chef-expanderctl.mkd index 00b34e7734..03ce6af8ac 100644 --- a/distro/common/markdown/man8/chef-expanderctl.mkd +++ b/distro/common/markdown/man8/chef-expanderctl.mkd @@ -55,4 +55,4 @@ granted to copy, distribute and / or modify this document under the terms of the Apache 2.0 License. On Debian systems, the complete text of the Apache 2.0 License can be -found in /usr/share/common-licenses/Apache-2.0.
\ No newline at end of file +found in /usr/share/common-licenses/Apache-2.0. diff --git a/distro/debian/etc/init.d/chef-client b/distro/debian/etc/init.d/chef-client index c5dfea06fb..b74f6d914b 100755 --- a/distro/debian/etc/init.d/chef-client +++ b/distro/debian/etc/init.d/chef-client @@ -20,7 +20,7 @@ NAME=chef-client DESC=chef-client PIDFILE=/var/run/chef/client.pid -test -x $DAEMON || exit 0 +test -x $DAEMON || exit 1 . /lib/lsb/init-functions diff --git a/distro/debian/etc/init.d/chef-expander b/distro/debian/etc/init.d/chef-expander index 7fea0e9118..fdf6e40678 100755 --- a/distro/debian/etc/init.d/chef-expander +++ b/distro/debian/etc/init.d/chef-expander @@ -20,7 +20,7 @@ NAME=chef-expander DESC=chef-expander PIDFILE=/var/run/chef/expander.pid -test -x $DAEMON || exit 0 +test -x $DAEMON || exit 1 . /lib/lsb/init-functions diff --git a/distro/debian/etc/init.d/chef-server b/distro/debian/etc/init.d/chef-server index f7c1ede583..0b94fc7fc7 100755 --- a/distro/debian/etc/init.d/chef-server +++ b/distro/debian/etc/init.d/chef-server @@ -21,7 +21,7 @@ MAINPID=/var/run/chef/server.main.pid NAME=chef-server DESC=chef-server -test -x $DAEMON || exit 0 +test -x $DAEMON || exit 1 . /lib/lsb/init-functions diff --git a/distro/debian/etc/init.d/chef-server-webui b/distro/debian/etc/init.d/chef-server-webui index c82171cedb..e2db8a49b7 100755 --- a/distro/debian/etc/init.d/chef-server-webui +++ b/distro/debian/etc/init.d/chef-server-webui @@ -21,7 +21,7 @@ MAINPID=/var/run/chef/server-webui.main.pid NAME=chef-server-webui DESC=chef-server-webui -test -x $DAEMON || exit 0 +test -x $DAEMON || exit 1 . /lib/lsb/init-functions diff --git a/distro/debian/etc/init.d/chef-solr b/distro/debian/etc/init.d/chef-solr index 1e4c0b8b51..2cc93b5fd2 100755 --- a/distro/debian/etc/init.d/chef-solr +++ b/distro/debian/etc/init.d/chef-solr @@ -21,7 +21,7 @@ NAME=chef-solr DESC=chef-solr PIDFILE=/var/run/chef/solr.pid -test -x $DAEMON || exit 0 +test -x $DAEMON || exit 1 . /lib/lsb/init-functions diff --git a/distro/debian/etc/init/chef-client.conf b/distro/debian/etc/init/chef-client.conf index 1f8c6d0d9b..5f246b140c 100644 --- a/distro/debian/etc/init/chef-client.conf +++ b/distro/debian/etc/init/chef-client.conf @@ -11,7 +11,7 @@ respawn respawn limit 5 30 pre-start script - test -x /usr/bin/chef-client || { stop; exit 0; } + test -x /usr/bin/chef-client || { stop; exit 1; } end script exec /usr/bin/chef-client -i 1800 -L /var/log/chef/client.log diff --git a/distro/debian/etc/init/chef-expander.conf b/distro/debian/etc/init/chef-expander.conf index 21ff246307..2c08f6cecc 100644 --- a/distro/debian/etc/init/chef-expander.conf +++ b/distro/debian/etc/init/chef-expander.conf @@ -11,7 +11,7 @@ respawn respawn limit 5 30 pre-start script - test -x /usr/bin/chef-expander || { stop; exit 0; } + test -x /usr/bin/chef-expander || { stop; exit 1; } end script exec /usr/bin/chef-expander -c /etc/chef/solr.rb -L /var/log/chef/expander.log -n 1 -i 1 diff --git a/distro/debian/etc/init/chef-server-webui.conf b/distro/debian/etc/init/chef-server-webui.conf index 8b443c51f5..8ba25877e4 100644 --- a/distro/debian/etc/init/chef-server-webui.conf +++ b/distro/debian/etc/init/chef-server-webui.conf @@ -11,7 +11,7 @@ respawn respawn limit 5 30 pre-start script - test -x /usr/bin/chef-server-webui || { stop; exit 0; } + test -x /usr/bin/chef-server-webui || { stop; exit 1; } end script exec /usr/bin/chef-server-webui -e production -p 4040 -L /var/log/chef/server-webui.log diff --git a/distro/debian/etc/init/chef-server.conf b/distro/debian/etc/init/chef-server.conf index 1eebd8f0cb..a372e50ea3 100644 --- a/distro/debian/etc/init/chef-server.conf +++ b/distro/debian/etc/init/chef-server.conf @@ -11,7 +11,7 @@ respawn respawn limit 5 30 pre-start script - test -x /usr/bin/chef-server || { stop; exit 0; } + test -x /usr/bin/chef-server || { stop; exit 1; } end script exec /usr/bin/chef-server -e production -p 4000 -L /var/log/chef/server.log diff --git a/distro/debian/etc/init/chef-solr.conf b/distro/debian/etc/init/chef-solr.conf index 4ca885e28d..edca5e3f80 100644 --- a/distro/debian/etc/init/chef-solr.conf +++ b/distro/debian/etc/init/chef-solr.conf @@ -11,7 +11,7 @@ respawn respawn limit 5 30 pre-start script - test -x /usr/bin/chef-solr || { stop; exit 0; } + test -x /usr/bin/chef-solr || { stop; exit 1; } end script exec /usr/bin/chef-solr -c /etc/chef/solr.rb -L /var/log/chef/solr.log diff --git a/distro/redhat/etc/init.d/chef-client b/distro/redhat/etc/init.d/chef-client index fbeaa395c0..b41150e7a1 100644 --- a/distro/redhat/etc/init.d/chef-client +++ b/distro/redhat/etc/init.d/chef-client @@ -61,7 +61,7 @@ reload() { killproc -p $pidfile chef-client -HUP retval=$? echo - return $retval + return $retval } run() { diff --git a/distro/redhat/etc/init.d/chef-server b/distro/redhat/etc/init.d/chef-server index 44247178b5..f956dd4e45 100644 --- a/distro/redhat/etc/init.d/chef-server +++ b/distro/redhat/etc/init.d/chef-server @@ -11,7 +11,7 @@ # Required-Stop: $local_fs $network $remote_fs chef-solr chef-expander # Should-Start: $named $time # Should-Stop: $named $time -# Short-Description: Startup script for chef-server +# Short-Description: Startup script for chef-server # Description: Server component of the Chef systems integration framework. ### END INIT INFO @@ -50,7 +50,7 @@ start() { stop() { echo -n $"Stopping $prog: " - killproc -p $pidfile $prog + killproc -p $pidfile $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile diff --git a/distro/redhat/etc/init.d/chef-server-webui b/distro/redhat/etc/init.d/chef-server-webui index f26f9c1f9a..65498bf723 100644 --- a/distro/redhat/etc/init.d/chef-server-webui +++ b/distro/redhat/etc/init.d/chef-server-webui @@ -11,7 +11,7 @@ # Required-Stop: $local_fs $network $remote_fs chef-server # Should-Start: $named $time # Should-Stop: $named $time -# Short-Description: Startup script for chef-server-webui +# Short-Description: Startup script for chef-server-webui # Description: Server WebUI component of the Chef systems integration framework. ### END INIT INFO @@ -50,7 +50,7 @@ start() { stop() { echo -n $"Stopping $prog: " - killproc -p $pidfile $prog + killproc -p $pidfile $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile diff --git a/distro/redhat/etc/init.d/chef-solr b/distro/redhat/etc/init.d/chef-solr index b75c40f53f..9223173276 100644 --- a/distro/redhat/etc/init.d/chef-solr +++ b/distro/redhat/etc/init.d/chef-solr @@ -1,5 +1,5 @@ #!/bin/bash -# +# # chef-solr Startup script for the SOLR search engine # # chkconfig: - 94 06 @@ -42,7 +42,7 @@ start() { stop() { echo -n $"Stopping $prog: " - killproc -p $pidfile $prog + killproc -p $pidfile $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile diff --git a/lib/chef/api_client.rb b/lib/chef/api_client.rb index 32e1eee017..66cbd3f30e 100644 --- a/lib/chef/api_client.rb +++ b/lib/chef/api_client.rb @@ -36,6 +36,7 @@ class Chef @public_key = nil @private_key = nil @admin = false + @validator = false end # Gets or sets the client name. @@ -74,6 +75,19 @@ class Chef ) end + # Gets or sets whether this client is a validator. + # + # @params [Boolean] whether or not the client is a validator. If + # `nil`, retrieves the already-set value. + # @return [Boolean] The current value + def validator(arg=nil) + set_or_return( + :validator, + arg, + :kind_of => [TrueClass, FalseClass] + ) + end + # Gets or sets the private key. # # @params [Optional String] The string representation of the private key. @@ -94,6 +108,7 @@ class Chef result = { "name" => @name, "public_key" => @public_key, + "validator" => @validator, "admin" => @admin, 'json_class' => self.class.name, "chef_type" => "client" @@ -115,6 +130,7 @@ class Chef client.private_key(o["private_key"]) if o.key?("private_key") client.public_key(o["public_key"]) client.admin(o["admin"]) + client.validator(o["validator"]) client end @@ -160,11 +176,11 @@ class Chef # Save this client via the REST API, returns a hash including the private key def save begin - http_api.put("clients/#{name}", { :name => self.name, :admin => self.admin}) + http_api.put("clients/#{name}", { :name => self.name, :admin => self.admin, :validator => self.validator}) rescue Net::HTTPServerException => e # If that fails, go ahead and try and update it if e.response.code == "404" - http_api.post("clients", {:name => self.name, :admin => self.admin }) + http_api.post("clients", {:name => self.name, :admin => self.admin, :validator => self.validator }) else raise e end @@ -172,7 +188,7 @@ class Chef end def reregister - reregistered_self = http_api.put("clients/#{name}", { :name => name, :admin => admin, :private_key => true }) + reregistered_self = http_api.put("clients/#{name}", { :name => name, :admin => admin, :validator => validator, :private_key => true }) if reregistered_self.respond_to?(:[]) private_key(reregistered_self["private_key"]) else @@ -192,7 +208,7 @@ class Chef end def inspect - "Chef::ApiClient name:'#{name}' admin:'#{admin.inspect}' " + + "Chef::ApiClient name:'#{name}' admin:'#{admin.inspect}' validator:'#{validator}' " + "public_key:'#{public_key}' private_key:'#{private_key}'" end @@ -202,4 +218,3 @@ class Chef end end - diff --git a/lib/chef/application.rb b/lib/chef/application.rb index 6522ba6e64..c1fc3a78a4 100644 --- a/lib/chef/application.rb +++ b/lib/chef/application.rb @@ -66,31 +66,26 @@ class Chef::Application run_application end - # Parse the configuration file + # Parse configuration (options and config file) def configure_chef parse_options + load_config_file + end - begin - case config[:config_file] - when /^(http|https):\/\// - Chef::REST.new("", nil, nil).fetch(config[:config_file]) { |f| apply_config(f.path) } - else - ::File::open(config[:config_file]) { |f| apply_config(f.path) } - end - rescue Errno::ENOENT => error + # Parse the config file + def load_config_file + config_fetcher = Chef::ConfigFetcher.new(config[:config_file], Chef::Config.config_file_jail) + if config[:config_file].nil? + Chef::Log.warn("No config file found or specified on command line, using command line options.") + elsif config_fetcher.config_missing? Chef::Log.warn("*****************************************") Chef::Log.warn("Did not find config file: #{config[:config_file]}, using command line options.") Chef::Log.warn("*****************************************") - - Chef::Config.merge!(config) - rescue SocketError => error - Chef::Application.fatal!("Error getting config file #{config[:config_file]}", 2) - rescue Chef::Exceptions::ConfigurationError => error - Chef::Application.fatal!("Error processing config file #{config[:config_file]} with error #{error.message}", 2) - rescue Exception => error - Chef::Application.fatal!("Unknown error processing config file #{config[:config_file]} with error #{error.message}", 2) + else + config_content = config_fetcher.read_config + apply_config(config_content, config[:config_file]) end - + Chef::Config.merge!(config) end # Initialize and configure the logger. @@ -172,23 +167,59 @@ class Chef::Application raise Chef::Exceptions::Application, "#{self.to_s}: you must override run_application" end + def self.setup_server_connectivity + if Chef::Config.chef_zero.enabled + destroy_server_connectivity + + require 'chef_zero/server' + require 'chef/chef_fs/chef_fs_data_store' + require 'chef/chef_fs/config' + + chef_fs = Chef::ChefFS::Config.new.local_fs + chef_fs.write_pretty_json = true + server_options = {} + server_options[:data_store] = Chef::ChefFS::ChefFSDataStore.new(chef_fs) + server_options[:log_level] = Chef::Log.level + server_options[:port] = Chef::Config.chef_zero.port + Chef::Log.info("Starting chef-zero on port #{Chef::Config.chef_zero.port} with repository at #{server_options[:data_store].chef_fs.fs_description}") + @chef_zero_server = ChefZero::Server.new(server_options) + @chef_zero_server.start_background + Chef::Config.chef_server_url = @chef_zero_server.url + end + end + + def self.destroy_server_connectivity + if @chef_zero_server + @chef_zero_server.stop + @chef_zero_server = nil + end + end + # Initializes Chef::Client instance and runs it def run_chef_client + Chef::Application.setup_server_connectivity + @chef_client = Chef::Client.new( - @chef_client_json, + @chef_client_json, :override_runlist => config[:override_runlist] ) @chef_client_json = nil @chef_client.run @chef_client = nil + + Chef::Application.destroy_server_connectivity end private - def apply_config(config_file_path) - Chef::Config.from_file(config_file_path) - Chef::Config.merge!(config) + def apply_config(config_content, config_file_path) + Chef::Config.from_string(config_content, config_file_path) + rescue Exception => error + Chef::Log.fatal("Configuration error #{error.class}: #{error.message}") + filtered_trace = error.backtrace.grep(/#{Regexp.escape(config_file_path)}/) + filtered_trace.each {|line| Chef::Log.fatal(" " + line )} + Chef::Application.fatal!("Aborting due to error in '#{config_file_path}'", 2) end class << self diff --git a/lib/chef/application/agent.rb b/lib/chef/application/agent.rb index 353d45252e..66b0c25cbf 100644 --- a/lib/chef/application/agent.rb +++ b/lib/chef/application/agent.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb index b08a795697..a04b4f1cf6 100644 --- a/lib/chef/application/client.rb +++ b/lib/chef/application/client.rb @@ -22,7 +22,7 @@ require 'chef/client' require 'chef/config' require 'chef/daemon' require 'chef/log' -require 'chef/rest' +require 'chef/config_fetcher' require 'chef/handler/error_report' @@ -34,7 +34,6 @@ class Chef::Application::Client < Chef::Application option :config_file, :short => "-c CONFIG", :long => "--config CONFIG", - :default => Chef::Config.platform_specific_path("/etc/chef/client.rb"), :description => "The configuration file to use" option :formatter, @@ -197,6 +196,20 @@ class Chef::Application::Client < Chef::Application :description => "Enable reporting data collection for chef runs", :boolean => true + option :local_mode, + :short => "-z", + :long => "--local-mode", + :description => "Point chef-client at local repository", + :boolean => true + + option :chef_zero_port, + :long => "--chef-zero-port PORT", + :description => "Port to start chef-zero on" + + option :config_file_jail, + :long => "--config-file-jail PATH", + :description => "Directory under which config files are allowed to be loaded (no client.rb or knife.rb outside this path will be loaded)." + if Chef::Platform.windows? option :fatal_windows_admin_check, :short => "-A", @@ -219,6 +232,12 @@ class Chef::Application::Client < Chef::Application Chef::Config[:chef_server_url] = config[:chef_server_url] if config.has_key? :chef_server_url + Chef::Config.local_mode = config[:local_mode] if config.has_key?(:local_mode) + if Chef::Config.local_mode && !Chef::Config.has_key?(:cookbook_path) && !Chef::Config.has_key?(:chef_repo_path) + Chef::Config.chef_repo_path = Chef::Config.find_chef_repo_path(Dir.pwd) + end + Chef::Config.chef_zero.port = config[:chef_zero_port] if config[:chef_zero_port] + if Chef::Config[:daemonize] Chef::Config[:interval] ||= 1800 end @@ -229,31 +248,22 @@ class Chef::Application::Client < Chef::Application end if Chef::Config[:json_attribs] - begin - json_io = case Chef::Config[:json_attribs] - when /^(http|https):\/\// - @rest = Chef::REST.new(Chef::Config[:json_attribs], nil, nil) - @rest.get_rest(Chef::Config[:json_attribs], true).open - else - open(Chef::Config[:json_attribs]) - end - rescue SocketError => error - Chef::Application.fatal!("I cannot connect to #{Chef::Config[:json_attribs]}", 2) - rescue Errno::ENOENT => error - Chef::Application.fatal!("I cannot find #{Chef::Config[:json_attribs]}", 2) - rescue Errno::EACCES => error - Chef::Application.fatal!("Permissions are incorrect on #{Chef::Config[:json_attribs]}. Please chmod a+r #{Chef::Config[:json_attribs]}", 2) - rescue Exception => error - Chef::Application.fatal!("Got an unexpected error reading #{Chef::Config[:json_attribs]}: #{error.message}", 2) - end + config_fetcher = Chef::ConfigFetcher.new(Chef::Config[:json_attribs]) + @chef_client_json = config_fetcher.fetch_json + end + end - begin - @chef_client_json = Chef::JSONCompat.from_json(json_io.read) - json_io.close unless json_io.closed? - rescue JSON::ParserError => error - Chef::Application.fatal!("Could not parse the provided JSON file (#{Chef::Config[:json_attribs]})!: " + error.message, 2) + def load_config_file + Chef::Config.config_file_jail = config[:config_file_jail] if config[:config_file_jail] + if !config.has_key?(:config_file) + if config[:local_mode] + require 'chef/knife' + config[:config_file] = Chef::Knife.locate_config_file + else + config[:config_file] = Chef::Config.platform_specific_path("/etc/chef/client.rb") end end + super end def configure_logging diff --git a/lib/chef/application/knife.rb b/lib/chef/application/knife.rb index 13612a4bf3..3a9cd4e870 100644 --- a/lib/chef/application/knife.rb +++ b/lib/chef/application/knife.rb @@ -106,6 +106,16 @@ class Chef::Application::Knife < Chef::Application :description => "Which format to use for output", :default => "summary" + option :local_mode, + :short => "-z", + :long => "--local-mode", + :description => "Point knife commands at local repository instead of server", + :boolean => true + + option :chef_zero_port, + :long => "--chef-zero-port PORT", + :description => "Port to start chef-zero on" + option :version, :short => "-v", :long => "--version", diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb index 5e3fe90607..ba563ce3a8 100644 --- a/lib/chef/application/solo.rb +++ b/lib/chef/application/solo.rb @@ -23,7 +23,7 @@ require 'chef/config' require 'chef/daemon' require 'chef/log' require 'chef/rest' -require 'open-uri' +require 'chef/config_fetcher' require 'fileutils' class Chef::Application::Solo < Chef::Application @@ -31,7 +31,7 @@ class Chef::Application::Solo < Chef::Application option :config_file, :short => "-c CONFIG", :long => "--config CONFIG", - :default => Chef::Config.platform_specfic_path('/etc/chef/solo.rb'), + :default => Chef::Config.platform_specific_path('/etc/chef/solo.rb'), :description => "The configuration file to use" option :formatter, @@ -160,6 +160,11 @@ class Chef::Application::Solo < Chef::Application :description => 'Enable whyrun mode', :boolean => true + option :environment, + :short => '-E ENVIRONMENT', + :long => '--environment ENVIRONMENT', + :description => 'Set the Chef Environment on the node' + attr_reader :chef_solo_json def initialize @@ -176,36 +181,13 @@ class Chef::Application::Solo < Chef::Application end if Chef::Config[:json_attribs] - begin - json_io = case Chef::Config[:json_attribs] - when /^(http|https):\/\// - @rest = Chef::REST.new(Chef::Config[:json_attribs], nil, nil) - @rest.get_rest(Chef::Config[:json_attribs], true).open - else - open(Chef::Config[:json_attribs]) - end - rescue SocketError => error - Chef::Application.fatal!("I cannot connect to #{Chef::Config[:json_attribs]}", 2) - rescue Errno::ENOENT => error - Chef::Application.fatal!("I cannot find #{Chef::Config[:json_attribs]}", 2) - rescue Errno::EACCES => error - Chef::Application.fatal!("Permissions are incorrect on #{Chef::Config[:json_attribs]}. Please chmod a+r #{Chef::Config[:json_attribs]}", 2) - rescue Exception => error - Chef::Application.fatal!("Got an unexpected error reading #{Chef::Config[:json_attribs]}: #{error.message}", 2) - end - - begin - @chef_client_json = Chef::JSONCompat.from_json(json_io.read) - json_io.close unless json_io.closed? - rescue JSON::ParserError => error - Chef::Application.fatal!("Could not parse the provided JSON file (#{Chef::Config[:json_attribs]})!: " + error.message, 2) - end + config_fetcher = Chef::ConfigFetcher.new(Chef::Config[:json_attribs]) + @chef_solo_json = config_fetcher.fetch_json end if Chef::Config[:recipe_url] cookbooks_path = Array(Chef::Config[:cookbook_path]).detect{|e| e =~ /\/cookbooks\/*$/ } recipes_path = File.expand_path(File.join(cookbooks_path, '..')) - target_file = File.join(recipes_path, 'recipes.tgz') Chef::Log.debug "Creating path #{recipes_path} to extract recipes into" FileUtils.mkdir_p recipes_path diff --git a/lib/chef/application/windows_service.rb b/lib/chef/application/windows_service.rb index 85a18c7a17..08403c7aa2 100644 --- a/lib/chef/application/windows_service.rb +++ b/lib/chef/application/windows_service.rb @@ -27,11 +27,13 @@ require 'chef/rest' require 'mixlib/cli' require 'socket' require 'win32/daemon' +require 'chef/mixin/shell_out' class Chef class Application class WindowsService < ::Win32::Daemon include Mixlib::CLI + include Chef::Mixin::ShellOut option :config_file, :short => "-c CONFIG", @@ -160,17 +162,29 @@ class Chef # 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 + # The chef client will be started in a new process. We have used shell_out to start the chef-client. + # The log_location and config_file of the parent process is passed to the new chef-client process. + # We need to add the --no-fork, as by default it is set to fork=true. + begin + Chef::Log.info "Starting chef-client in a new process" + # Pass config params to the new process + config_params = " --no-fork" + config_params += " -c #{Chef::Config[:config_file]}" unless Chef::Config[:config_file].nil? + config_params += " -L #{Chef::Config[:log_location]}" unless Chef::Config[:log_location] == STDOUT + # Starts a new process and waits till the process exits + result = shell_out("chef-client #{config_params}") + Chef::Log.debug "#{result.stdout}" + Chef::Log.debug "#{result.stderr}" + rescue Mixlib::ShellOut::ShellCommandFailed => e + Chef::Log.warn "Not able to start chef-client in new process (#{e})" + rescue => e + Chef::Log.error e + ensure + # Once process exits, we log the current process' pid + Chef::Log.info "Child process exited (pid: #{Process.pid})" + end end - def apply_config(config_file_path) Chef::Config.from_file(config_file_path) Chef::Config.merge!(config) @@ -241,7 +255,7 @@ class Chef def configure_chef(startup_parameters) # Bit of a hack ahead: # It is possible to specify a service's binary_path_name with arguments, like "foo.exe -x argX". - # It is also possible to specify startup parameters separately, either via the the Services manager + # It is also possible to specify startup parameters separately, either via the Services manager # or by using the registry (I think). # In order to accommodate all possible sources of parameterization, we first parse any command line diff --git a/lib/chef/application/windows_service_manager.rb b/lib/chef/application/windows_service_manager.rb index 13bd2c5cd6..493f0dfc62 100644 --- a/lib/chef/application/windows_service_manager.rb +++ b/lib/chef/application/windows_service_manager.rb @@ -61,6 +61,14 @@ class Chef :show_options => true, :exit => 0 + option :version, + :short => "-v", + :long => "--version", + :description => "Show chef version", + :boolean => true, + :proc => lambda {|v| puts "Chef: #{::Chef::VERSION}"}, + :exit => 0 + def initialize(service_options) # having to call super in initialize is the most annoying # anti-pattern :( diff --git a/lib/chef/checksum/storage.rb b/lib/chef/checksum/storage.rb index 90aef57081..4a1b3d38df 100644 --- a/lib/chef/checksum/storage.rb +++ b/lib/chef/checksum/storage.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/checksum/storage/filesystem.rb b/lib/chef/checksum/storage/filesystem.rb index 7500a5ad85..94257f518b 100644 --- a/lib/chef/checksum/storage/filesystem.rb +++ b/lib/chef/checksum/storage/filesystem.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/chef_fs/chef_fs_data_store.rb b/lib/chef/chef_fs/chef_fs_data_store.rb index c1c5a81e04..1fedc98380 100644 --- a/lib/chef/chef_fs/chef_fs_data_store.rb +++ b/lib/chef/chef_fs/chef_fs_data_store.rb @@ -135,7 +135,7 @@ class Chef if path[0] == 'cookbooks' && path.length >= 3 entry.delete(true) else - entry.delete + entry.delete(false) end end end diff --git a/lib/chef/chef_fs/command_line.rb b/lib/chef/chef_fs/command_line.rb index dd5e62b755..d0183a5a2a 100644 --- a/lib/chef/chef_fs/command_line.rb +++ b/lib/chef/chef_fs/command_line.rb @@ -19,6 +19,7 @@ require 'chef/chef_fs/file_system' require 'chef/chef_fs/file_system/operation_failed_error' require 'chef/chef_fs/file_system/operation_not_allowed_error' +require 'chef/util/diff' class Chef module ChefFS @@ -268,7 +269,7 @@ class Chef old_tempfile.write(old_value) old_tempfile.close - result = `diff -u #{old_tempfile.path} #{new_tempfile.path}` + result = Chef::Util::Diff.new.udiff(old_tempfile.path, new_tempfile.path) result = result.gsub(/^--- #{old_tempfile.path}/, "--- #{old_path}") result = result.gsub(/^\+\+\+ #{new_tempfile.path}/, "+++ #{new_path}") result diff --git a/lib/chef/chef_fs/config.rb b/lib/chef/chef_fs/config.rb index ab4cea89f2..e08b976961 100644 --- a/lib/chef/chef_fs/config.rb +++ b/lib/chef/chef_fs/config.rb @@ -25,13 +25,24 @@ class Chef # Helpers to take Chef::Config and create chef_fs and local_fs from it # class Config - def initialize(chef_config = Chef::Config, cwd = Dir.pwd) + def initialize(chef_config = Chef::Config, cwd = Dir.pwd, options = {}) @chef_config = chef_config @cwd = cwd - configure_repo_paths + @cookbook_version = options[:cookbook_version] + + # Default to getting *everything* from the server. + if !@chef_config[:repo_mode] + if @chef_config[:chef_server_url] =~ /\/+organizations\/.+/ + @chef_config[:repo_mode] = 'hosted_everything' + else + @chef_config[:repo_mode] = 'everything' + end + end end - PATH_VARIABLES = %w(acl_path client_path cookbook_path container_path data_bag_path environment_path group_path node_path role_path user_path) + attr_reader :chef_config + attr_reader :cwd + attr_reader :cookbook_version def chef_fs @chef_fs ||= create_chef_fs @@ -39,7 +50,7 @@ class Chef def create_chef_fs require 'chef/chef_fs/file_system/chef_server_root_dir' - Chef::ChefFS::FileSystem::ChefServerRootDir.new("remote", @chef_config) + Chef::ChefFS::FileSystem::ChefServerRootDir.new("remote", @chef_config, :cookbook_version => @cookbook_version) end def local_fs @@ -73,16 +84,14 @@ class Chef # If the path does not reach into ANY specified directory, nil is returned. def server_path(file_path) pwd = File.expand_path(Dir.pwd) - absolute_path = Chef::ChefFS::PathUtils.realest_path(File.expand_path(file_path, pwd)) + absolute_pwd = Chef::ChefFS::PathUtils.realest_path(File.expand_path(file_path, pwd)) # Check all object paths (cookbooks_dir, data_bags_dir, etc.) object_paths.each_pair do |name, paths| paths.each do |path| realest_path = Chef::ChefFS::PathUtils.realest_path(path) - if absolute_path[0,realest_path.length] == realest_path && - (absolute_path.length == realest_path.length || - absolute_path[realest_path.length,1] =~ /#{PathUtils.regexp_path_separator}/) - relative_path = Chef::ChefFS::PathUtils::relative_to(absolute_path, realest_path) + if PathUtils.descendant_of?(absolute_pwd, realest_path) + relative_path = Chef::ChefFS::PathUtils::relative_to(absolute_pwd, realest_path) return relative_path == '.' ? "/#{name}" : "/#{name}/#{relative_path}" end end @@ -91,7 +100,7 @@ class Chef # Check chef_repo_path Array(@chef_config[:chef_repo_path]).flatten.each do |chef_repo_path| realest_chef_repo_path = Chef::ChefFS::PathUtils.realest_path(chef_repo_path) - if absolute_path == realest_chef_repo_path + if absolute_pwd == realest_chef_repo_path return '/' end end @@ -125,19 +134,10 @@ class Chef server_path end - def require_chef_repo_path - if !@chef_config[:chef_repo_path] - Chef::Log.error("Must specify either chef_repo_path or cookbook_path in Chef config file") - exit(1) - end - end - private def object_paths @object_paths ||= begin - require_chef_repo_path - result = {} case @chef_config[:repo_mode] when 'static' @@ -155,51 +155,6 @@ class Chef result end end - - def configure_repo_paths - # Smooth out some (for now) inappropriate defaults set by Chef - if @chef_config[:cookbook_path] == [ @chef_config.platform_specific_path("/var/chef/cookbooks"), - @chef_config.platform_specific_path("/var/chef/site-cookbooks") ] - @chef_config[:cookbook_path] = nil - end - if @chef_config[:data_bag_path] == @chef_config.platform_specific_path('/var/chef/data_bags') - @chef_config[:data_bag_path] = nil - end - if @chef_config[:node_path] == '/var/chef/node' - @chef_config[:node_path] = nil - end - if @chef_config[:role_path] == @chef_config.platform_specific_path('/var/chef/roles') - @chef_config[:role_path] = nil - end - - # Infer chef_repo_path from cookbook_path if not speciifed - if !@chef_config[:chef_repo_path] - if @chef_config[:cookbook_path] - @chef_config[:chef_repo_path] = Array(@chef_config[:cookbook_path]).flatten.map { |path| File.expand_path('..', path) } - end - end - - # Default to getting *everything* from the server. - if !@chef_config[:repo_mode] - if @chef_config[:chef_server_url] =~ /\/+organizations\/.+/ - @chef_config[:repo_mode] = 'hosted_everything' - else - @chef_config[:repo_mode] = 'everything' - end - end - - # Infer any *_path variables that are not specified - if @chef_config[:chef_repo_path] - PATH_VARIABLES.each do |variable_name| - chef_repo_paths = Array(@chef_config[:chef_repo_path]).flatten - variable = variable_name.to_sym - if !@chef_config[variable] - # cookbook_path -> cookbooks - @chef_config[variable] = chef_repo_paths.map { |path| File.join(path, "#{variable_name[0..-6]}s") } - end - end - end - end end end end diff --git a/lib/chef/chef_fs/data_handler/client_data_handler.rb b/lib/chef/chef_fs/data_handler/client_data_handler.rb index 2db3fa897f..4b6b8f5c79 100644 --- a/lib/chef/chef_fs/data_handler/client_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/client_data_handler.rb @@ -9,12 +9,11 @@ class Chef defaults = { 'name' => remove_dot_json(entry.name), 'clientname' => remove_dot_json(entry.name), - 'orgname' => entry.org, 'admin' => false, 'validator' => false, 'chef_type' => 'client' } - if entry.org + if entry.respond_to?(:org) && entry.org defaults['orgname'] = entry.org end result = normalize_hash(client, defaults) diff --git a/lib/chef/chef_fs/file_system.rb b/lib/chef/chef_fs/file_system.rb index a6e14e548c..f2478c4680 100644 --- a/lib/chef/chef_fs/file_system.rb +++ b/lib/chef/chef_fs/file_system.rb @@ -289,7 +289,7 @@ class Chef ui.output "Deleted extra entry #{dest_path} (purge is on)" if ui end else - Chef::Log.info("Not deleting extra entry #{dest_path} (purge is off)") if ui + ui.output ("Not deleting extra entry #{dest_path} (purge is off)") if ui end end @@ -407,7 +407,7 @@ class Chef parent = entry.parent if parent && !parent.exists? parent_path = format_path.call(parent) if ui - parent_parent = get_or_create_parent(entry.parent, options, ui, format_path) + parent_parent = get_or_create_parent(parent, options, ui, format_path) if options[:dry_run] ui.output "Would create #{parent_path}" if ui else diff --git a/lib/chef/chef_fs/file_system/acl_entry.rb b/lib/chef/chef_fs/file_system/acl_entry.rb index 0be9076038..8edc02d5c5 100644 --- a/lib/chef/chef_fs/file_system/acl_entry.rb +++ b/lib/chef/chef_fs/file_system/acl_entry.rb @@ -40,7 +40,7 @@ class Chef acls = data_handler.normalize(JSON.parse(file_contents, :create_additions => false), self) PERMISSIONS.each do |permission| begin - rest.put_rest("#{api_path}/#{permission}", { permission => acls[permission] }) + rest.put("#{api_path}/#{permission}", { permission => acls[permission] }) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:write, self, e), "Timeout writing: #{e}" rescue Net::HTTPServerException => e diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_acls_dir.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_acls_dir.rb new file mode 100644 index 0000000000..7d2a930633 --- /dev/null +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_acls_dir.rb @@ -0,0 +1,37 @@ +# +# Author:: John Keiser (<jkeiser@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/chef_fs/file_system/chef_repository_file_system_entry' +require 'chef/chef_fs/file_system/acls_dir' +require 'chef/chef_fs/data_handler/acl_data_handler' + +class Chef + module ChefFS + module FileSystem + class ChefRepositoryFileSystemAclsDir < ChefRepositoryFileSystemEntry + def initialize(name, parent, path = nil) + super(name, parent, path, Chef::ChefFS::DataHandler::AclDataHandler.new) + end + + def can_have_child?(name, is_dir) + is_dir ? Chef::ChefFS::FileSystem::AclsDir::ENTITY_TYPES.include?(name) : name == 'organization.json' + end + end + end + end +end
\ No newline at end of file diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb index e3d8e47cf2..5203637012 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb @@ -18,6 +18,7 @@ require 'chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry' require 'chef/chef_fs/file_system/cookbook_dir' +require 'chef/chef_fs/file_system/not_found_error' require 'chef/cookbook/chefignore' require 'chef/cookbook/cookbook_version_loader' @@ -51,13 +52,14 @@ class Chef end def children - Dir.entries(file_path).sort. - select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. - map do |child_name| - segment_info = CookbookDir::COOKBOOK_SEGMENT_INFO[child_name.to_sym] || {} - ChefRepositoryFileSystemCookbookEntry.new(child_name, self, nil, segment_info[:ruby_only], segment_info[:recursive]) - end. - select { |entry| !(entry.dir? && entry.children.size == 0) } + begin + Dir.entries(file_path).sort. + select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. + map { |child_name| make_child(child_name) }. + select { |entry| !(entry.dir? && entry.children.size == 0) } + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) + end end def can_have_child?(name, is_dir) @@ -65,7 +67,6 @@ class Chef # Only the given directories will be uploaded. return CookbookDir::COOKBOOK_SEGMENT_INFO.keys.include?(name.to_sym) && name != 'root_files' end - super(name, is_dir) end @@ -79,6 +80,13 @@ class Chef def canonical_cookbook_name(entry_name) self.class.canonical_cookbook_name(entry_name) end + + protected + + def make_child(child_name) + segment_info = CookbookDir::COOKBOOK_SEGMENT_INFO[child_name.to_sym] || {} + ChefRepositoryFileSystemCookbookEntry.new(child_name, self, nil, segment_info[:ruby_only], segment_info[:recursive]) + end end end end diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry.rb index d2fe3ed5f6..6541b07065 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry.rb @@ -18,6 +18,7 @@ require 'chef/chef_fs/file_system/chef_repository_file_system_entry' require 'chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir' +require 'chef/chef_fs/file_system/not_found_error' class Chef module ChefFS @@ -33,10 +34,14 @@ class Chef attr_reader :recursive def children - Dir.entries(file_path).sort. - select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. - map { |child_name| ChefRepositoryFileSystemCookbookEntry.new(child_name, self, nil, ruby_only, recursive) }. - select { |entry| !(entry.dir? && entry.children.size == 0) } + begin + Dir.entries(file_path).sort. + select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. + map { |child_name| make_child(child_name) }. + select { |entry| !(entry.dir? && entry.children.size == 0) } + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) + end end def can_have_child?(name, is_dir) @@ -65,6 +70,16 @@ class Chef true end + + def write_pretty_json + false + end + + protected + + def make_child(child_name) + ChefRepositoryFileSystemCookbookEntry.new(child_name, self, nil, ruby_only, recursive) + end end end end diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb index ba4ea0bd1f..6e16f18f24 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb @@ -26,29 +26,44 @@ class Chef class ChefRepositoryFileSystemCookbooksDir < ChefRepositoryFileSystemEntry def initialize(name, parent, file_path) super(name, parent, file_path) - @chefignore = Chef::Cookbook::Chefignore.new(self.file_path) + begin + @chefignore = Chef::Cookbook::Chefignore.new(self.file_path) + rescue Errno::EISDIR + rescue Errno::EACCES + # Work around a bug in Chefignore when chefignore is a directory + end end attr_reader :chefignore def children - Dir.entries(file_path).sort. - select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. - map { |child_name| ChefRepositoryFileSystemCookbookDir.new(child_name, self) }. - select do |entry| - # empty cookbooks and cookbook directories are ignored - if entry.children.size == 0 - Chef::Log.warn("Cookbook '#{entry.name}' is empty or entirely chefignored at #{entry.path_for_printing}") - false - else - true + begin + Dir.entries(file_path).sort. + select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. + map { |child_name| make_child(child_name) }. + select do |entry| + # empty cookbooks and cookbook directories are ignored + if entry.children.size == 0 + Chef::Log.warn("Cookbook '#{entry.name}' is empty or entirely chefignored at #{entry.path_for_printing}") + false + else + true + end end - end + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) + end end def can_have_child?(name, is_dir) is_dir && !name.start_with?('.') end + + protected + + def make_child(child_name) + ChefRepositoryFileSystemCookbookDir.new(child_name, self) + end end end end diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb index fa4fda4eb6..3d3f58201e 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb @@ -18,6 +18,7 @@ # require 'chef/chef_fs/file_system/file_system_entry' +require 'chef/chef_fs/file_system/not_found_error' class Chef module ChefFS @@ -30,6 +31,10 @@ class Chef @data_handler = data_handler end + def write_pretty_json + root.write_pretty_json + end + def data_handler @data_handler || parent.data_handler end @@ -47,13 +52,36 @@ class Chef !is_dir && name[-5..-1] == '.json' end + def write(file_contents) + if file_contents && write_pretty_json && name[-5..-1] == '.json' + file_contents = minimize(file_contents, self) + end + super(file_contents) + end + + def minimize(file_contents, entry) + object = JSONCompat.from_json(file_contents, :create_additions => false) + object = data_handler.normalize(object, entry) + object = data_handler.minimize(object, entry) + JSONCompat.to_json_pretty(object) + end + def children # Except cookbooks and data bag dirs, all things must be json files - Dir.entries(file_path).sort. - select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. - map { |child_name| ChefRepositoryFileSystemEntry.new(child_name, self) } + begin + Dir.entries(file_path).sort. + select { |child_name| can_have_child?(child_name, File.directory?(File.join(file_path, child_name))) }. + map { |child_name| make_child(child_name) } + rescue Errno::ENOENT + raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) + end end + protected + + def make_child(child_name) + ChefRepositoryFileSystemEntry.new(child_name, self) + end end end end diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb index 3523d85a4e..d615e0f415 100644 --- a/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb @@ -18,6 +18,7 @@ require 'chef/chef_fs/file_system/base_fs_dir' require 'chef/chef_fs/file_system/chef_repository_file_system_entry' +require 'chef/chef_fs/file_system/chef_repository_file_system_acls_dir' require 'chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir' require 'chef/chef_fs/file_system/chef_repository_file_system_data_bags_dir' require 'chef/chef_fs/file_system/multiplexed_dir' @@ -28,7 +29,6 @@ require 'chef/chef_fs/data_handler/role_data_handler' require 'chef/chef_fs/data_handler/user_data_handler' require 'chef/chef_fs/data_handler/group_data_handler' require 'chef/chef_fs/data_handler/container_data_handler' -require 'chef/chef_fs/data_handler/acl_data_handler' class Chef module ChefFS @@ -39,6 +39,8 @@ class Chef @child_paths = child_paths end + attr_accessor :write_pretty_json + attr_reader :child_paths def children @@ -51,9 +53,14 @@ class Chef def create_child(name, file_contents = nil) child_paths[name].each do |path| - Dir.mkdir(path) + begin + Dir.mkdir(path) + rescue Errno::EEXIST + end end - make_child_entry(name) + child = make_child_entry(name) + @children = nil + child end def json_class @@ -90,6 +97,8 @@ class Chef dirs = paths.map { |path| ChefRepositoryFileSystemCookbooksDir.new(name, self, path) } elsif name == 'data_bags' dirs = paths.map { |path| ChefRepositoryFileSystemDataBagsDir.new(name, self, path) } + elsif name == 'acls' + dirs = paths.map { |path| ChefRepositoryFileSystemAclsDir.new(name, self, path) } else data_handler = case name when 'clients' @@ -106,8 +115,6 @@ class Chef Chef::ChefFS::DataHandler::GroupDataHandler.new when 'containers' Chef::ChefFS::DataHandler::ContainerDataHandler.new - when 'acls' - Chef::ChefFS::DataHandler::AclDataHandler.new else raise "Unknown top level path #{name}" end diff --git a/lib/chef/chef_fs/file_system/chef_server_root_dir.rb b/lib/chef/chef_fs/file_system/chef_server_root_dir.rb index 5eb72657c5..0083ee4cfa 100644 --- a/lib/chef/chef_fs/file_system/chef_server_root_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server_root_dir.rb @@ -16,6 +16,7 @@ # limitations under the License. # +require 'chef/server_api' require 'chef/chef_fs/file_system/acls_dir' require 'chef/chef_fs/file_system/base_fs_dir' require 'chef/chef_fs/file_system/rest_list_dir' @@ -23,7 +24,6 @@ require 'chef/chef_fs/file_system/cookbooks_dir' require 'chef/chef_fs/file_system/data_bags_dir' require 'chef/chef_fs/file_system/nodes_dir' require 'chef/chef_fs/file_system/environments_dir' -require 'chef/rest' require 'chef/chef_fs/data_handler/client_data_handler' require 'chef/chef_fs/data_handler/role_data_handler' require 'chef/chef_fs/data_handler/user_data_handler' @@ -34,7 +34,7 @@ class Chef module ChefFS module FileSystem class ChefServerRootDir < BaseFSDir - def initialize(root_name, chef_config) + def initialize(root_name, chef_config, options = {}) super("", nil) @chef_server_url = chef_config[:chef_server_url] @chef_username = chef_config[:node_name] @@ -42,6 +42,7 @@ class Chef @environment = chef_config[:environment] @repo_mode = chef_config[:repo_mode] @root_name = root_name + @cookbook_version = options[:cookbook_version] # Used in knife diff and download for server cookbook version end attr_reader :chef_server_url @@ -49,12 +50,21 @@ class Chef attr_reader :chef_private_key attr_reader :environment attr_reader :repo_mode + attr_reader :cookbook_version def fs_description "Chef server at #{chef_server_url} (user #{chef_username}), repo_mode = #{repo_mode}" end def rest + Chef::ServerAPI.new(chef_server_url, :client_name => chef_username, :signing_key_filename => chef_private_key, :raw_output => true) + end + + def get_json(path) + Chef::ServerAPI.new(chef_server_url, :client_name => chef_username, :signing_key_filename => chef_private_key).get(path) + end + + def chef_rest Chef::REST.new(chef_server_url, chef_username, chef_private_key) end diff --git a/lib/chef/chef_fs/file_system/cookbook_dir.rb b/lib/chef/chef_fs/file_system/cookbook_dir.rb index cae29a1690..d7411e1c74 100644 --- a/lib/chef/chef_fs/file_system/cookbook_dir.rb +++ b/lib/chef/chef_fs/file_system/cookbook_dir.rb @@ -41,6 +41,7 @@ class Chef end else @cookbook_name = name + @version = root.cookbook_version # nil unless --cookbook-version specified in download/diff end end @@ -125,7 +126,7 @@ class Chef def delete(recurse) if recurse begin - rest.delete_rest(api_path) + rest.delete(api_path) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:delete, self, e), "Timeout deleting: #{e}" rescue Net::HTTPServerException @@ -190,7 +191,7 @@ class Chef old_retry_count = Chef::Config[:http_retry_count] begin Chef::Config[:http_retry_count] = 0 - @chef_object ||= Chef::CookbookVersion.json_create(Chef::ChefFS::RawRequest.raw_json(rest, api_path)) + @chef_object ||= Chef::CookbookVersion.json_create(root.get_json(api_path)) ensure Chef::Config[:http_retry_count] = old_retry_count end diff --git a/lib/chef/chef_fs/file_system/cookbook_file.rb b/lib/chef/chef_fs/file_system/cookbook_file.rb index e05c4aa614..7868322590 100644 --- a/lib/chef/chef_fs/file_system/cookbook_file.rb +++ b/lib/chef/chef_fs/file_system/cookbook_file.rb @@ -17,6 +17,7 @@ # require 'chef/chef_fs/file_system/base_fs_object' +require 'chef/http/simple' require 'digest/md5' class Chef @@ -35,16 +36,12 @@ class Chef end def read - old_sign_on_redirect = rest.sign_on_redirect - rest.sign_on_redirect = false begin - tmpfile = rest.get_rest(file[:url], true) + tmpfile = rest.streaming_request(file[:url]) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e), "Timeout reading #{file[:url]}: #{e}" rescue Net::HTTPServerException => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e), "#{e.message} retrieving #{file[:url]}" - ensure - rest.sign_on_redirect = old_sign_on_redirect end begin diff --git a/lib/chef/chef_fs/file_system/cookbooks_dir.rb b/lib/chef/chef_fs/file_system/cookbooks_dir.rb index c6af933290..a58bfdd1f2 100644 --- a/lib/chef/chef_fs/file_system/cookbooks_dir.rb +++ b/lib/chef/chef_fs/file_system/cookbooks_dir.rb @@ -18,10 +18,10 @@ require 'chef/chef_fs/file_system/rest_list_dir' require 'chef/chef_fs/file_system/cookbook_dir' -require 'chef/chef_fs/raw_request' require 'chef/chef_fs/file_system/operation_failed_error' require 'chef/chef_fs/file_system/cookbook_frozen_error' require 'chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir' +require 'chef/mixin/file_class' require 'tmpdir' @@ -29,6 +29,9 @@ class Chef module ChefFS module FileSystem class CookbooksDir < RestListDir + + include Chef::Mixin::FileClass + def initialize(parent) super("cookbooks", parent) end @@ -50,19 +53,20 @@ class Chef @children ||= begin if Chef::Config[:versioned_cookbooks] result = [] - Chef::ChefFS::RawRequest.raw_json(rest, "#{api_path}/?num_versions=all").each_pair do |cookbook_name, cookbooks| + root.get_json("#{api_path}/?num_versions=all").each_pair do |cookbook_name, cookbooks| cookbooks['versions'].each do |cookbook_version| result << CookbookDir.new("#{cookbook_name}-#{cookbook_version['version']}", self, :exists => true) end end else - result = Chef::ChefFS::RawRequest.raw_json(rest, api_path).keys.map { |cookbook_name| CookbookDir.new(cookbook_name, self, :exists => true) } + result = root.get_json(api_path).keys.map { |cookbook_name| CookbookDir.new(cookbook_name, self, :exists => true) } end result.sort_by(&:name) end end def create_child_from(other, options = {}) + @children = nil upload_cookbook_from(other, options) end @@ -92,7 +96,7 @@ class Chef proxy_cookbook_path = "#{temp_cookbooks_path}/#{cookbook_name}" # Make a symlink - File.symlink other.file_path, proxy_cookbook_path + file_class.symlink other.file_path, proxy_cookbook_path # Instantiate a proxy loader using the temporary symlink proxy_loader = Chef::Cookbook::CookbookVersionLoader.new(proxy_cookbook_path, other.parent.chefignore) @@ -102,18 +106,29 @@ class Chef cookbook_to_upload.freeze_version if options[:freeze] # Instantiate a new uploader based on the proxy loader - uploader = Chef::CookbookUploader.new(cookbook_to_upload, proxy_cookbook_path, :force => options[:force], :rest => rest) + uploader = Chef::CookbookUploader.new(cookbook_to_upload, proxy_cookbook_path, :force => options[:force], :rest => root.chef_rest) with_actual_cookbooks_dir(temp_cookbooks_path) do upload_cookbook!(uploader) end + + # + # When the temporary directory is being deleted on + # windows, the contents of the symlink under that + # directory is also deleted. So explicitly remove + # the symlink without removing the original contents if we + # are running on windows + # + if Chef::Platform.windows? + Dir.rmdir proxy_cookbook_path + end end end def upload_unversioned_cookbook(other, options) cookbook_to_upload = other.chef_object cookbook_to_upload.freeze_version if options[:freeze] - uploader = Chef::CookbookUploader.new(cookbook_to_upload, other.parent.file_path, :force => options[:force], :rest => rest) + uploader = Chef::CookbookUploader.new(cookbook_to_upload, other.parent.file_path, :force => options[:force], :rest => root.chef_rest) with_actual_cookbooks_dir(other.parent.file_path) do upload_cookbook!(uploader) diff --git a/lib/chef/chef_fs/file_system/data_bag_dir.rb b/lib/chef/chef_fs/file_system/data_bag_dir.rb index 3814b94fac..212f76fdb9 100644 --- a/lib/chef/chef_fs/file_system/data_bag_dir.rb +++ b/lib/chef/chef_fs/file_system/data_bag_dir.rb @@ -52,7 +52,7 @@ class Chef raise MustDeleteRecursivelyError.new(self), "#{path_for_printing} must be deleted recursively" end begin - rest.delete_rest(api_path) + rest.delete(api_path) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:delete, self, e), "Timeout deleting: #{e}" rescue Net::HTTPServerException => e diff --git a/lib/chef/chef_fs/file_system/data_bags_dir.rb b/lib/chef/chef_fs/file_system/data_bags_dir.rb index 46c3c21cf6..6d0685d3b7 100644 --- a/lib/chef/chef_fs/file_system/data_bags_dir.rb +++ b/lib/chef/chef_fs/file_system/data_bags_dir.rb @@ -34,7 +34,7 @@ class Chef def children begin - @children ||= Chef::ChefFS::RawRequest.raw_json(rest, api_path).keys.sort.map do |entry| + @children ||= root.get_json(api_path).keys.sort.map do |entry| DataBagDir.new(entry, self, true) end rescue Timeout::Error => e @@ -54,7 +54,7 @@ class Chef def create_child(name, file_contents) begin - rest.post_rest(api_path, { 'name' => name }) + rest.post(api_path, { 'name' => name }) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:create_child, self, e), "Timeout creating child '#{name}': #{e}" rescue Net::HTTPServerException => e @@ -64,6 +64,7 @@ class Chef raise Chef::ChefFS::FileSystem::OperationFailedError.new(:create_child, self, e), "HTTP error creating child '#{name}': #{e}" end end + @children = nil DataBagDir.new(name, self, true) end end diff --git a/lib/chef/chef_fs/file_system/file_system_entry.rb b/lib/chef/chef_fs/file_system/file_system_entry.rb index 82c52deae8..46d4eb5538 100644 --- a/lib/chef/chef_fs/file_system/file_system_entry.rb +++ b/lib/chef/chef_fs/file_system/file_system_entry.rb @@ -40,20 +40,24 @@ class Chef def children begin - @children ||= Dir.entries(file_path).sort.select { |entry| entry != '.' && entry != '..' }.map { |entry| FileSystemEntry.new(entry, self) } + Dir.entries(file_path).sort.select { |entry| entry != '.' && entry != '..' }.map { |entry| make_child(entry) } rescue Errno::ENOENT raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!) end end def create_child(child_name, file_contents=nil) - result = FileSystemEntry.new(child_name, self) + child = make_child(child_name) if file_contents - result.write(file_contents) + child.write(file_contents) else - Dir.mkdir(result.file_path) + begin + Dir.mkdir(child.file_path) + rescue Errno::EEXIST + end end - result + @children = nil + child end def dir? @@ -84,6 +88,12 @@ class Chef file.write(content) end end + + protected + + def make_child(child_name) + FileSystemEntry.new(child_name, self) + end end end end diff --git a/lib/chef/chef_fs/file_system/multiplexed_dir.rb b/lib/chef/chef_fs/file_system/multiplexed_dir.rb index a7a901e304..06d4af705d 100644 --- a/lib/chef/chef_fs/file_system/multiplexed_dir.rb +++ b/lib/chef/chef_fs/file_system/multiplexed_dir.rb @@ -17,7 +17,7 @@ class Chef end def children - @children ||= begin + begin result = [] seen = {} # If multiple things have the same name, the first one wins. @@ -40,6 +40,7 @@ class Chef end def create_child(name, file_contents = nil) + @children = nil write_dir.create_child(name, file_contents) end end diff --git a/lib/chef/chef_fs/file_system/nodes_dir.rb b/lib/chef/chef_fs/file_system/nodes_dir.rb index 82683e81ac..c3c48377cd 100644 --- a/lib/chef/chef_fs/file_system/nodes_dir.rb +++ b/lib/chef/chef_fs/file_system/nodes_dir.rb @@ -32,7 +32,7 @@ class Chef # Identical to RestListDir.children, except supports environments def children begin - @children ||= Chef::ChefFS::RawRequest.raw_json(rest, env_api_path).keys.sort.map do |key| + @children ||= root.get_json(env_api_path).keys.sort.map do |key| _make_child_entry("#{key}.json", true) end rescue Timeout::Error => e diff --git a/lib/chef/chef_fs/file_system/operation_failed_error.rb b/lib/chef/chef_fs/file_system/operation_failed_error.rb index 1af2d2dcff..28d170d628 100644 --- a/lib/chef/chef_fs/file_system/operation_failed_error.rb +++ b/lib/chef/chef_fs/file_system/operation_failed_error.rb @@ -27,6 +27,14 @@ class Chef @operation = operation end + def message + if cause && cause.is_a?(Net::HTTPExceptions) && cause.response.code == "400" + "#{super} cause: #{cause.response.body}" + else + super + end + end + attr_reader :operation end end diff --git a/lib/chef/chef_fs/file_system/rest_list_dir.rb b/lib/chef/chef_fs/file_system/rest_list_dir.rb index 594fec8ab6..b7ee51d284 100644 --- a/lib/chef/chef_fs/file_system/rest_list_dir.rb +++ b/lib/chef/chef_fs/file_system/rest_list_dir.rb @@ -45,7 +45,7 @@ class Chef def children begin - @children ||= Chef::ChefFS::RawRequest.raw_json(rest, api_path).keys.sort.map do |key| + @children ||= root.get_json(api_path).keys.sort.map do |key| _make_child_entry("#{key}.json", true) end rescue Timeout::Error => e @@ -76,7 +76,7 @@ class Chef end begin - rest.post_rest(api_path, object) + rest.post(api_path, object) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:create_child, self, e), "Timeout creating '#{name}': #{e}" rescue Net::HTTPServerException => e @@ -89,6 +89,8 @@ class Chef end end + @children = nil + result end diff --git a/lib/chef/chef_fs/file_system/rest_list_entry.rb b/lib/chef/chef_fs/file_system/rest_list_entry.rb index 6e6ad12438..0d5557de1d 100644 --- a/lib/chef/chef_fs/file_system/rest_list_entry.rb +++ b/lib/chef/chef_fs/file_system/rest_list_entry.rb @@ -19,7 +19,6 @@ require 'chef/chef_fs/file_system/base_fs_object' require 'chef/chef_fs/file_system/not_found_error' require 'chef/chef_fs/file_system/operation_failed_error' -require 'chef/chef_fs/raw_request' require 'chef/role' require 'chef/node' @@ -68,7 +67,7 @@ class Chef def delete(recurse) begin - rest.delete_rest(api_path) + rest.delete(api_path) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:delete, self, e), "Timeout deleting: #{e}" rescue Net::HTTPServerException => e @@ -86,7 +85,8 @@ class Chef def _read_hash begin - json = Chef::ChefFS::RawRequest.raw_request(rest, api_path) + # Minimize the value (get rid of defaults) so the results don't look terrible + minimize_value(root.get_json(api_path)) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e), "Timeout reading: #{e}" rescue Net::HTTPServerException => e @@ -96,8 +96,6 @@ class Chef raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e), "HTTP error reading: #{e}" end end - # Minimize the value (get rid of defaults) so the results don't look terrible - minimize_value(JSON.parse(json, :create_additions => false)) end def chef_object @@ -160,7 +158,7 @@ class Chef end begin - rest.put_rest(api_path, object) + rest.put(api_path, object) rescue Timeout::Error => e raise Chef::ChefFS::FileSystem::OperationFailedError.new(:write, self, e), "Timeout writing: #{e}" rescue Net::HTTPServerException => e diff --git a/lib/chef/chef_fs/knife.rb b/lib/chef/chef_fs/knife.rb index 5900c29f61..652c728550 100644 --- a/lib/chef/chef_fs/knife.rb +++ b/lib/chef/chef_fs/knife.rb @@ -35,37 +35,40 @@ class Chef def self.inherited(c) super + # Ensure we always get to do our includes, whether subclass calls deps or not c.deps do end - option :repo_mode, - :long => '--repo-mode MODE', - :description => "Specifies the local repository layout. Values: static, everything, hosted_everything. Default: everything/hosted_everything" + c.options.merge!(options) + end - option :chef_repo_path, - :long => '--chef-repo-path PATH', - :description => 'Overrides the location of chef repo. Default is specified by chef_repo_path in the config' + option :repo_mode, + :long => '--repo-mode MODE', + :description => "Specifies the local repository layout. Values: static, everything, hosted_everything. Default: everything/hosted_everything" - option :concurrency, - :long => '--concurrency THREADS', - :description => 'Maximum number of simultaneous requests to send (default: 10)' - end + option :chef_repo_path, + :long => '--chef-repo-path PATH', + :description => 'Overrides the location of chef repo. Default is specified by chef_repo_path in the config' + + option :concurrency, + :long => '--concurrency THREADS', + :description => 'Maximum number of simultaneous requests to send (default: 10)' def configure_chef super Chef::Config[:repo_mode] = config[:repo_mode] if config[:repo_mode] Chef::Config[:concurrency] = config[:concurrency].to_i if config[:concurrency] - # --chef-repo-path overrides all other paths + # --chef-repo-path forcibly overrides all other paths if config[:chef_repo_path] Chef::Config[:chef_repo_path] = config[:chef_repo_path] - Chef::ChefFS::Config::PATH_VARIABLES.each do |variable_name| - Chef::Config[variable_name.to_sym] = chef_repo_paths.map { |path| File.join(path, "#{variable_name[0..-6]}s") } + %w(acl client cookbook container data_bag environment group node role user).each do |variable_name| + Chef::Config.delete("#{variable_name}_path".to_sym) end end - @chef_fs_config = Chef::ChefFS::Config.new(Chef::Config) + @chef_fs_config = Chef::ChefFS::Config.new(Chef::Config, Dir.pwd, config) Chef::ChefFS::Parallelizer.threads = (Chef::Config[:concurrency] || 10) - 1 end @@ -91,17 +94,18 @@ class Chef end def pattern_args_from(args) + args.map { |arg| pattern_arg_from(arg) } + end + + def pattern_arg_from(arg) # TODO support absolute file paths and not just patterns? Too much? # Could be super useful in a world with multiple repo paths - args.map do |arg| - if !@chef_fs_config.base_path && !Chef::ChefFS::PathUtils.is_absolute?(arg) - # Check if chef repo path is specified to give a better error message - @chef_fs_config.require_chef_repo_path - ui.error("Attempt to use relative path '#{arg}' when current directory is outside the repository path") - exit(1) - end - Chef::ChefFS::FilePattern.relative_to(@chef_fs_config.base_path, arg) + if !@chef_fs_config.base_path && !Chef::ChefFS::PathUtils.is_absolute?(arg) + # Check if chef repo path is specified to give a better error message + ui.error("Attempt to use relative path '#{arg}' when current directory is outside the repository path") + exit(1) end + Chef::ChefFS::FilePattern.relative_to(@chef_fs_config.base_path, arg) end def format_path(entry) @@ -111,6 +115,19 @@ class Chef def parallelize(inputs, options = {}, &block) Chef::ChefFS::Parallelizer.parallelize(inputs, options, &block) end + + def discover_repo_dir(dir) + %w(.chef cookbooks data_bags environments roles).each do |subdir| + return dir if File.directory?(File.join(dir, subdir)) + end + # If this isn't it, check the parent + parent = File.dirname(dir) + if parent && parent != dir + discover_repo_dir(parent) + else + nil + end + end end end end diff --git a/lib/chef/chef_fs/path_utils.rb b/lib/chef/chef_fs/path_utils.rb index 805b092b3a..9ef75ce2e5 100644 --- a/lib/chef/chef_fs/path_utils.rb +++ b/lib/chef/chef_fs/path_utils.rb @@ -82,6 +82,11 @@ class Chef end end + def self.descendant_of?(path, ancestor) + path[0,ancestor.length] == ancestor && + (ancestor.length == path.length || path[ancestor.length,1] =~ /#{PathUtils.regexp_path_separator}/) + end + def self.is_absolute?(path) path =~ /^#{regexp_path_separator}/ end diff --git a/lib/chef/chef_fs/raw_request.rb b/lib/chef/chef_fs/raw_request.rb deleted file mode 100644 index 43907282f6..0000000000 --- a/lib/chef/chef_fs/raw_request.rb +++ /dev/null @@ -1,79 +0,0 @@ -class Chef - module ChefFS - module RawRequest - def self.raw_json(chef_rest, api_path) - JSON.parse(raw_request(chef_rest, api_path), :create_additions => false) - end - - def self.raw_request(chef_rest, api_path) - api_request(chef_rest, :GET, chef_rest.create_url(api_path), {}, false) - end - - def self.api_request(chef_rest, method, url, headers={}, data=false) - json_body = data - # json_body = data ? Chef::JSONCompat.to_json(data) : nil - # Force encoding to binary to fix SSL related EOFErrors - # cf. http://tickets.opscode.com/browse/CHEF-2363 - # http://redmine.ruby-lang.org/issues/5233 - # json_body.force_encoding(Encoding::BINARY) if json_body.respond_to?(:force_encoding) - headers = build_headers(chef_rest, method, url, headers, json_body) - - chef_rest.retriable_rest_request(method, url, json_body, headers) do |rest_request| - response = rest_request.call {|r| r.read_body} - - response_body = chef_rest.decompress_body(response) - - if response.kind_of?(Net::HTTPSuccess) - response_body - elsif redirect_location = redirected_to(response) - if [:GET, :HEAD].include?(method) - chef_rest.follow_redirect do - api_request(chef_rest, method, chef_rest.create_url(redirect_location)) - end - else - raise Exceptions::InvalidRedirect, "#{method} request was redirected from #{url} to #{redirect_location}. Only GET and HEAD support redirects." - end - else - # have to decompress the body before making an exception for it. But the body could be nil. - response.body.replace(chef_rest.decompress_body(response)) if response.body.respond_to?(:replace) - - if response['content-type'] =~ /json/ - exception = response_body - msg = "HTTP Request Returned #{response.code} #{response.message}: " - msg << (exception["error"].respond_to?(:join) ? exception["error"].join(", ") : exception["error"].to_s) - Chef::Log.info(msg) - end - response.error! - end - end - end - - private - - # Copied so that it does not automatically inflate an object - # This is also used by knife raw_essentials - - ACCEPT_ENCODING = "Accept-Encoding".freeze - ENCODING_GZIP_DEFLATE = "gzip;q=1.0,deflate;q=0.6,identity;q=0.3".freeze - - def self.redirected_to(response) - return nil unless response.kind_of?(Net::HTTPRedirection) - # Net::HTTPNotModified is undesired subclass of Net::HTTPRedirection so test for this - return nil if response.kind_of?(Net::HTTPNotModified) - response['location'] - end - - def self.build_headers(chef_rest, method, url, headers={}, json_body=false, raw=false) - # headers = @default_headers.merge(headers) - #headers['Accept'] = "application/json" unless raw - headers['Accept'] = "application/json" unless raw - headers["Content-Type"] = 'application/json' if json_body - headers['Content-Length'] = json_body.bytesize.to_s if json_body - headers[Chef::REST::RESTRequest::ACCEPT_ENCODING] = Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE - headers.merge!(chef_rest.authentication_headers(method, url, json_body)) if chef_rest.sign_requests? - headers.merge!(Chef::Config[:custom_http_headers]) if Chef::Config[:custom_http_headers] - headers - end - end - end -end diff --git a/lib/chef/client.rb b/lib/chef/client.rb index ceb0873079..04d6799988 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -198,6 +198,7 @@ class Chef Chef::Log.debug "Forked instance now converging" do_run rescue Exception + Chef::Log.error $! exit 1 else exit 0 @@ -206,7 +207,7 @@ class Chef Chef::Log.debug "Fork successful. Waiting for new chef pid: #{pid}" result = Process.waitpid2(pid) handle_child_exit(result) - Chef::Log.debug "Forked child successfully reaped (pid: #{pid})" + Chef::Log.debug "Forked instance successfully reaped (pid: #{pid})" true else do_run @@ -367,7 +368,10 @@ class Chef # === Returns # rest<Chef::REST>:: returns Chef::REST connection object def register(client_name=node_name, config=Chef::Config) - if File.exists?(config[:client_key]) + if !config[:client_key] + @events.skipping_registration(client_name, config) + Chef::Log.debug("Client key is unspecified - skipping registration") + elsif File.exists?(config[:client_key]) @events.skipping_registration(client_name, config) Chef::Log.debug("Client key #{config[:client_key]} is present - skipping registration") else @@ -467,13 +471,15 @@ class Chef # === Returns # true:: Always returns true. def do_run - runlock = RunLock.new(Chef::Config) + runlock = RunLock.new(Chef::Config.lockfile) runlock.acquire # don't add code that may fail before entering this section to be sure to release lock begin + runlock.save_pid run_context = nil @events.run_start(Chef::VERSION) Chef::Log.info("*** Chef #{Chef::VERSION} ***") + Chef::Log.info "Chef-client pid: #{Process.pid}" enforce_path_sanity run_ohai @events.ohai_completed(node) diff --git a/lib/chef/config.rb b/lib/chef/config.rb index e3211d232e..feb7e4ea94 100644 --- a/lib/chef/config.rb +++ b/lib/chef/config.rb @@ -29,6 +29,13 @@ class Chef extend Mixlib::Config + # Evaluates the given string as config. + # + # +filename+ is used for context in stacktraces, but doesn't need to be the name of an actual file. + def self.from_string(string, filename) + self.instance_eval(string, filename, 1) + end + # Manages the chef secret session key # === Returns # <newkey>:: A new or retrieved session key @@ -50,8 +57,32 @@ class Chef configuration.inspect end + def self.on_windows? + RUBY_PLATFORM =~ /mswin|mingw|windows/ + end + + BACKSLASH = '\\'.freeze + + def self.platform_path_separator + if on_windows? + File::ALT_SEPARATOR || BACKSLASH + else + File::SEPARATOR + end + end + + def self.path_join(*args) + args = args.flatten + args.inject do |joined_path, component| + unless joined_path[-1,1] == platform_path_separator + joined_path += platform_path_separator + end + joined_path += component + end + end + def self.platform_specific_path(path) - if RUBY_PLATFORM =~ /mswin|mingw|windows/ + if on_windows? # turns /etc/chef/client.rb into C:/chef/client.rb system_drive = ENV['SYSTEMDRIVE'] ? ENV['SYSTEMDRIVE'] : "" path = File.join(system_drive, path.split('/')[2..-1]) @@ -65,32 +96,35 @@ class Chef formatters << [name, file_path] end - def self.formatters - @formatters ||= [] + # Config file to load (client.rb, knife.rb, etc. defaults set differently in knife, chef-client, etc.) + configurable(:config_file) + + default(:config_dir) do + if local_mode + path_join(user_home, ".chef#{platform_path_separator}") + else + config_file && ::File.dirname(config_file) + end end + # No config file (client.rb / knife.rb / etc.) will be loaded outside this path. + # Major use case is tests, where we don't want to load the user's config files. + configurable(:config_file_jail) + + default :formatters, [] + # Override the config dispatch to set the value of multiple server options simultaneously # # === Parameters # url<String>:: String to be set for all of the chef-server-api URL's # - config_attr_writer :chef_server_url do |url| - url = url.strip - configure do |c| - c[:chef_server_url] = url - end - url - end + configurable(:chef_server_url).writes_value { |url| url.strip } # When you are using ActiveSupport, they monkey-patch 'daemonize' into Kernel. # So while this is basically identical to what method_missing would do, we pull # it up here and get a real method written so that things get dispatched # properly. - config_attr_writer :daemonize do |v| - configure do |c| - c[:daemonize] = v - end - end + configurable(:daemonize).writes_value { |v| v } # Override the config dispatch to set the value of log_location configuration option # @@ -108,50 +142,148 @@ class Chef rescue Errno::ENOENT raise Chef::Exceptions::ConfigurationError, "Failed to open or create log file at #{location.to_str}" end - f + f + end + end + + # The root where all local chef object data is stored. cookbooks, data bags, + # environments are all assumed to be in separate directories under this. + # chef-solo uses these directories for input data. knife commands + # that upload or download files (such as knife upload, knife role from file, + # etc.) work. + default :chef_repo_path do + if self.configuration[:cookbook_path] + if self.configuration[:cookbook_path].kind_of?(String) + File.expand_path('..', self.configuration[:cookbook_path]) + else + self.configuration[:cookbook_path].map do |path| + File.expand_path('..', path) + end + end + else + platform_specific_path("/var/chef") + end + end + + def self.find_chef_repo_path(cwd) + # In local mode, we auto-discover the repo root by looking for a path with "cookbooks" under it. + # This allows us to run config-free. + path = cwd + until File.directory?(path_join(path, "cookbooks")) + new_path = File.expand_path('..', path) + if new_path == path + Chef::Log.warn("No cookbooks directory found at or above current directory. Assuming #{Dir.pwd}.") + return Dir.pwd + end + path = new_path + end + Chef::Log.info("Auto-discovered chef repository at #{path}") + path + end + + def self.derive_path_from_chef_repo_path(child_path) + if chef_repo_path.kind_of?(String) + path_join(chef_repo_path, child_path) + else + chef_repo_path.map { |path| path_join(path, child_path)} end end + # Location of acls on disk. String or array of strings. + # Defaults to <chef_repo_path>/acls. + # Only applies to Enterprise Chef commands. + default(:acl_path) { derive_path_from_chef_repo_path('acls') } + + # Location of clients on disk. String or array of strings. + # Defaults to <chef_repo_path>/acls. + default(:client_path) { derive_path_from_chef_repo_path('clients') } + + # Location of cookbooks on disk. String or array of strings. + # Defaults to <chef_repo_path>/cookbooks. If chef_repo_path + # is not specified, this is set to [/var/chef/cookbooks, /var/chef/site-cookbooks]). + default(:cookbook_path) do + if self.configuration[:chef_repo_path] + derive_path_from_chef_repo_path('cookbooks') + else + Array(derive_path_from_chef_repo_path('cookbooks')).flatten + + Array(derive_path_from_chef_repo_path('site-cookbooks')).flatten + end + end + + # Location of containers on disk. String or array of strings. + # Defaults to <chef_repo_path>/containers. + # Only applies to Enterprise Chef commands. + default(:container_path) { derive_path_from_chef_repo_path('containers') } + + # Location of data bags on disk. String or array of strings. + # Defaults to <chef_repo_path>/data_bags. + default(:data_bag_path) { derive_path_from_chef_repo_path('data_bags') } + + # Location of environments on disk. String or array of strings. + # Defaults to <chef_repo_path>/environments. + default(:environment_path) { derive_path_from_chef_repo_path('environments') } + + # Location of groups on disk. String or array of strings. + # Defaults to <chef_repo_path>/groups. + # Only applies to Enterprise Chef commands. + default(:group_path) { derive_path_from_chef_repo_path('groups') } + + # Location of nodes on disk. String or array of strings. + # Defaults to <chef_repo_path>/nodes. + default(:node_path) { derive_path_from_chef_repo_path('nodes') } + + # Location of roles on disk. String or array of strings. + # Defaults to <chef_repo_path>/roles. + default(:role_path) { derive_path_from_chef_repo_path('roles') } + + # Location of users on disk. String or array of strings. + # Defaults to <chef_repo_path>/users. + # Does not apply to Enterprise Chef commands. + default(:user_path) { derive_path_from_chef_repo_path('users') } + # Turn on "path sanity" by default. See also: http://wiki.opscode.com/display/chef/User+Environment+PATH+Sanity - enforce_path_sanity(true) + default :enforce_path_sanity, true # Formatted Chef Client output is a beta feature, disabled by default: - formatter "null" + default :formatter, "null" # The number of times the client should retry when registering with the server - client_registration_retries 5 - - # Where the cookbooks are located. Meaning is somewhat context dependent between - # knife, chef-client, and chef-solo. - cookbook_path [ platform_specific_path("/var/chef/cookbooks"), - platform_specific_path("/var/chef/site-cookbooks") ] + default :client_registration_retries, 5 # An array of paths to search for knife exec scripts if they aren't in the current directory - script_path [] + default :script_path, [] + + # The root of all caches (checksums, cache and backup). If local mode is on, + # this is under the user's home directory. + default(:cache_path) do + if local_mode + "#{config_dir}local-mode-cache" + else + platform_specific_path("/var/chef") + end + end # Where cookbook files are stored on the server (by content checksum) - checksum_path "/var/chef/checksums" + default(:checksum_path) { path_join(cache_path, "checksums") } # Where chef's cache files should be stored - file_cache_path platform_specific_path("/var/chef/cache") + default(:file_cache_path) { path_join(cache_path, "cache") } - # By default, chef-client (or solo) creates a lockfile in - # `file_cache_path`/chef-client-running.pid - # If `lockfile` is explicitly set, this path will be used instead. + # Where backups of chef-managed files should go + default(:file_backup_path) { path_join(cache_path, "backup") } + + # The chef-client (or solo) lockfile. # # If your `file_cache_path` resides on a NFS (or non-flock()-supporting # fs), it's recommended to set this to something like # '/tmp/chef-client-running.pid' - lockfile nil - - # Where backups of chef-managed files should go - file_backup_path platform_specific_path("/var/chef/backup") + default(:lockfile) { path_join(file_cache_path, "chef-client-running.pid") } ## Daemonization Settings ## # What user should Chef run as? - user nil - group nil - umask 0022 + default :user, nil + default :group, nil + default :umask, 0022 # Valid log_levels are: # * :debug @@ -164,57 +296,76 @@ class Chef # in a console), the log level is set to :warn, and output formatters are # used as the primary mode of output. When a tty is not available, the # logger is the primary mode of output, and the log level is set to :info - log_level :auto + default :log_level, :auto # Using `force_formatter` causes chef to default to formatter output when STDOUT is not a tty - force_formatter false + default :force_formatter, false # Using `force_logger` causes chef to default to logger output when STDOUT is a tty - force_logger false - - http_retry_count 5 - http_retry_delay 5 - interval nil - json_attribs nil - log_location STDOUT + default :force_logger, false + + default :http_retry_count, 5 + default :http_retry_delay, 5 + default :interval, nil + default :once, nil + default :json_attribs, nil + default :log_location, STDOUT # toggle info level log items that can create a lot of output - verbose_logging true - node_name nil - diff_disabled false - diff_filesize_threshold 10000000 - diff_output_threshold 1000000 - - pid_file nil - - chef_server_url "https://localhost:443" - - rest_timeout 300 - yum_timeout 900 - solo false - splay nil - why_run false - color false - client_fork true - enable_reporting true - enable_reporting_url_fatals false + default :verbose_logging, true + default :node_name, nil + default :diff_disabled, false + default :diff_filesize_threshold, 10000000 + default :diff_output_threshold, 1000000 + default :local_mode, false + + default :pid_file, nil + + config_context :chef_zero do + config_strict_mode true + default(:enabled) { Chef::Config.local_mode } + default :port, 8889 + end + default :chef_server_url, "https://localhost:443" + + default :rest_timeout, 300 + default :yum_timeout, 900 + default :solo, false + default :splay, nil + default :why_run, false + default :color, false + default :client_fork, true + default :enable_reporting, true + default :enable_reporting_url_fatals, false # Set these to enable SSL authentication / mutual-authentication # with the server - ssl_client_cert nil - ssl_client_key nil - ssl_verify_mode :verify_none - ssl_ca_path nil - ssl_ca_file nil - # Where should chef-solo look for role files? - role_path platform_specific_path("/var/chef/roles") + # Client side SSL cert/key for mutual auth + default :ssl_client_cert, nil + default :ssl_client_key, nil + + # Whether or not to verify the SSL cert for all HTTPS requests. If set to + # :verify_peer, all HTTPS requests will be validated regardless of other + # SSL verification settings. + default :ssl_verify_mode, :verify_none - data_bag_path platform_specific_path("/var/chef/data_bags") + # Whether or not to verify the SSL cert for HTTPS requests to the Chef + # server API. If set to `true`, the server's cert will be validated + # regardless of the :ssl_verify_mode setting. + default :verify_api_cert, false - environment_path platform_specific_path("/var/chef/environments") + # Path to the default CA bundle files. + default :ssl_ca_path, nil + default :ssl_ca_file, nil + + # A directory that contains additional SSL certificates to trust. Any + # certificates in this directory will be added to whatever CA bundle ruby + # is using. Use this to add self-signed certs for your Chef Server or local + # HTTP file servers. + default(:trusted_certs_dir) { config_dir && path_join(config_dir, "trusted_certs") } # Where should chef-solo download recipes from? - recipe_url nil + default :recipe_url, nil # Sets the version of the signed header authentication protocol to use (see # the 'mixlib-authorization' project for more detail). Currently, versions @@ -230,7 +381,7 @@ class Chef # # In the future, this configuration option may be replaced with an # automatic negotiation scheme. - authentication_protocol_version "1.0" + default :authentication_protocol_version, "1.0" # This key will be used to sign requests to the Chef server. This location # must be writable by Chef during initial setup when generating a client @@ -238,17 +389,21 @@ class Chef # # The chef-server will look up the public key for the client using the # `node_name` of the client. - client_key platform_specific_path("/etc/chef/client.pem") + # + # If chef-zero is enabled, this defaults to nil (no authentication). + default(:client_key) { chef_zero.enabled ? nil : platform_specific_path("/etc/chef/client.pem") } # This secret is used to decrypt encrypted data bag items. - encrypted_data_bag_secret platform_specific_path("/etc/chef/encrypted_data_bag_secret") - - # We have to check for the existence of the default file before setting it - # since +Chef::Config[:encrypted_data_bag_secret]+ is read by older - # bootstrap templates to determine if the local secret should be uploaded to - # node being bootstrapped. This should be removed in Chef 12. - unless File.exist?(platform_specific_path("/etc/chef/encrypted_data_bag_secret")) - encrypted_data_bag_secret(nil) + default(:encrypted_data_bag_secret) do + # We have to check for the existence of the default file before setting it + # since +Chef::Config[:encrypted_data_bag_secret]+ is read by older + # bootstrap templates to determine if the local secret should be uploaded to + # node being bootstrapped. This should be removed in Chef 12. + if File.exist?(platform_specific_path("/etc/chef/encrypted_data_bag_secret")) + platform_specific_path("/etc/chef/encrypted_data_bag_secret") + else + nil + end end # As of Chef 11.0, version "1" is the default encrypted data bag item @@ -256,7 +411,7 @@ class Chef # To maintain compatibility, versions other than 1 must be opt-in. # # Set this to `2` if you have chef-client 11.6.0+ in your infrastructure: - data_bag_encrypt_version 1 + default :data_bag_encrypt_version, 1 # When reading data bag items, any supported version is accepted. However, # if all encrypted data bags have been generated with the version 2 format, @@ -264,7 +419,7 @@ class Chef # security. For example, the version 2 format is identical to version 1 # except for the addition of an HMAC, so an attacker with MITM capability # could downgrade an encrypted data bag to version 1 as part of an attack. - data_bag_decrypt_minimum_version 0 + default :data_bag_decrypt_minimum_version, 0 # If there is no file in the location given by `client_key`, chef-client # will temporarily use the "validator" identity to generate one. If the @@ -272,43 +427,53 @@ class Chef # chef-client will not be able to authenticate to the server. # # The `validation_key` is never used if the `client_key` exists. - validation_key platform_specific_path("/etc/chef/validation.pem") - validation_client_name "chef-validator" + # + # If chef-zero is enabled, this defaults to nil (no authentication). + default(:validation_key) { chef_zero.enabled ? nil : platform_specific_path("/etc/chef/validation.pem") } + default :validation_client_name, "chef-validator" # Zypper package provider gpg checks. Set to true to enable package # gpg signature checking. This will be default in the # future. Setting to false disables the warnings. # Leaving this set to nil or false is a security hazard! - zypper_check_gpg nil + default :zypper_check_gpg, nil # Report Handlers - report_handlers [] + default :report_handlers, [] # Exception Handlers - exception_handlers [] + default :exception_handlers, [] # Start handlers - start_handlers [] + default :start_handlers, [] # Syntax Check Cache. Knife keeps track of files that is has already syntax # checked by storing files in this directory. `syntax_check_cache_path` is # the new (and preferred) configuration setting. If not set, knife will - # fall back to using cache_options[:path]. - # - # Because many users will have knife configs with cache_options (generated - # by `knife configure`), the default for now is to *not* set - # syntax_check_cache_path, and thus fallback to cache_options[:path]. We - # leave that value to the same default as was previously set. - syntax_check_cache_path nil + # fall back to using cache_options[:path], which is deprecated but exists in + # many client configs generated by pre-Chef-11 bootstrappers. + default(:syntax_check_cache_path) { cache_options[:path] } # Deprecated: - cache_options({ :path => platform_specific_path("/var/chef/cache/checksums") }) + default(:cache_options) { { :path => path_join(file_cache_path, "checksums") } } # Set to false to silence Chef 11 deprecation warnings: - chef11_deprecation_warnings true - - # Arbitrary knife configuration data - knife Hash.new + default :chef11_deprecation_warnings, true + + # knife configuration data + config_context :knife do + default :ssh_port, nil + default :ssh_user, nil + default :ssh_attribute, nil + default :ssh_gateway, nil + default :bootstrap_version, nil + default :bootstrap_proxy, nil + default :identity_file, nil + default :host_key_verify, nil + default :forward_agent, nil + default :sort_status_reverse, nil + default :hints, {} + end # Those lists of regular expressions define what chef considers a # valid user and group name @@ -316,31 +481,31 @@ class Chef # From http://technet.microsoft.com/en-us/library/cc776019(WS.10).aspx principal_valid_regex_part = '[^"\/\\\\\[\]\:;|=,+*?<>]+' - user_valid_regex [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ] - group_valid_regex [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ] + default :user_valid_regex, [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ] + default :group_valid_regex, [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ] - fatal_windows_admin_check false + default :fatal_windows_admin_check, false else - user_valid_regex [ /^([-a-zA-Z0-9_.]+[\\@]?[-a-zA-Z0-9_.]+)$/, /^\d+$/ ] - group_valid_regex [ /^([-a-zA-Z0-9_.\\@^ ]+)$/, /^\d+$/ ] + default :user_valid_regex, [ /^([-a-zA-Z0-9_.]+[\\@]?[-a-zA-Z0-9_.]+)$/, /^\d+$/ ] + default :group_valid_regex, [ /^([-a-zA-Z0-9_.\\@^ ]+)$/, /^\d+$/ ] end # returns a platform specific path to the user home dir windows_home_path = ENV['SYSTEMDRIVE'] + ENV['HOMEPATH'] if ENV['SYSTEMDRIVE'] && ENV['HOMEPATH'] - user_home(ENV['HOME'] || windows_home_path || ENV['USERPROFILE']) + default :user_home, (ENV['HOME'] || windows_home_path || ENV['USERPROFILE']) # Enable file permission fixup for selinux. Fixup will be done # only if selinux is enabled in the system. - enable_selinux_file_permission_fixup true + default :enable_selinux_file_permission_fixup, true # Use atomic updates (i.e. move operation) while updating contents # of the files resources. When set to false copy operation is # used to update files. - file_atomic_update true + default :file_atomic_update, true # If false file staging is will be done via tempfiles that are # created under ENV['TMP'] otherwise tempfiles will be created in # the directory that files are going to reside. - file_staging_uses_destdir false + default :file_staging_uses_destdir, false end end diff --git a/lib/chef/config_fetcher.rb b/lib/chef/config_fetcher.rb new file mode 100644 index 0000000000..80a313590b --- /dev/null +++ b/lib/chef/config_fetcher.rb @@ -0,0 +1,79 @@ +require 'chef/application' +require 'chef/chef_fs/path_utils' +require 'chef/http/simple' +require 'chef/json_compat' + +class Chef + class ConfigFetcher + + attr_reader :config_location + attr_reader :config_file_jail + + def initialize(config_location, config_file_jail) + @config_location = config_location + @config_file_jail = config_file_jail + end + + def fetch_json + config_data = read_config + begin + Chef::JSONCompat.from_json(config_data) + rescue JSON::ParserError => error + Chef::Application.fatal!("Could not parse the provided JSON file (#{config_location}): " + error.message, 2) + end + end + + def read_config + if remote_config? + fetch_remote_config + else + read_local_config + end + end + + def fetch_remote_config + http.get("") + rescue SocketError, SystemCallError, Net::HTTPServerException => error + Chef::Application.fatal!("Cannot fetch config '#{config_location}': '#{error.class}: #{error.message}", 2) + end + + def read_local_config + ::File.read(config_location) + rescue Errno::ENOENT => error + Chef::Application.fatal!("Cannot load configuration from #{config_location}", 2) + rescue Errno::EACCES => error + Chef::Application.fatal!("Permissions are incorrect on #{config_location}. Please chmod a+r #{config_location}", 2) + end + + def config_missing? + return false if remote_config? + + # Check if the config file exists, and check if it is underneath the config file jail + begin + real_config_file = Pathname.new(config_location).realpath.to_s + rescue Errno::ENOENT + return true + end + + # If realpath succeeded, the file exists + return false if !config_file_jail + + begin + real_jail = Pathname.new(config_file_jail).realpath.to_s + rescue Errno::ENOENT + Chef::Log.warn("Config file jail #{config_file_jail} does not exist: will not load any config file.") + return true + end + + !Chef::ChefFS::PathUtils.descendant_of?(real_config_file, real_jail) + end + + def http + Chef::HTTP::Simple.new(config_location) + end + + def remote_config? + !!(config_location =~ %r{^(http|https)://}) + end + end +end diff --git a/lib/chef/cookbook/file_vendor.rb b/lib/chef/cookbook/file_vendor.rb index 38eab185ca..406f23ca25 100644 --- a/lib/chef/cookbook/file_vendor.rb +++ b/lib/chef/cookbook/file_vendor.rb @@ -7,9 +7,9 @@ # 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. @@ -27,14 +27,14 @@ class Chef def self.on_create(&block) @instance_creator = block end - + # Factory method that creates the appropriate kind of # Cookbook::FileVendor to serve the contents of the manifest def self.create_from_manifest(manifest) raise "Must call Chef::Cookbook::FileVendor.on_create before calling create_from_manifest factory" unless defined?(@instance_creator) @instance_creator.call(manifest) end - + # Gets the on-disk location for the given cookbook file. # # Subclasses are responsible for determining exactly how the @@ -42,7 +42,7 @@ class Chef def get_filename(filename) raise NotImplemented, "Subclasses must implement this method" end - + end end end diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb index 18368bd99f..b9b32c8224 100644 --- a/lib/chef/cookbook/metadata.rb +++ b/lib/chef/cookbook/metadata.rb @@ -110,8 +110,8 @@ class Chef @version = Version.new "0.0.0" if cookbook @recipes = cookbook.fully_qualified_recipe_names.inject({}) do |r, e| - e = self.name if e =~ /::default$/ - r[e] = "" + e = self.name.to_s if e =~ /::default$/ + r[e] ||= "" self.provides e r end diff --git a/lib/chef/cookbook/syntax_check.rb b/lib/chef/cookbook/syntax_check.rb index 0e757074e3..59888e2ba3 100644 --- a/lib/chef/cookbook/syntax_check.rb +++ b/lib/chef/cookbook/syntax_check.rb @@ -6,9 +6,9 @@ # 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. @@ -39,19 +39,9 @@ class Chef attr_reader :cache_path # Create a new PersistentSet. Values in the set are persisted by - # creating a file in the +cache_path+ directory. If not given, the - # value of Chef::Config[:syntax_check_cache_path] is used; if that - # value is not configured, the value of - # Chef::Config[:cache_options][:path] is used. - #-- - # history: prior to Chef 11, the cache implementation was based on - # moneta and configured via cache_options[:path]. Knife configs - # generated with Chef 11 will have `syntax_check_cache_path`, but older - # configs will have `cache_options[:path]`. `cache_options` is marked - # deprecated in chef/config.rb but doesn't currently trigger a warning. - # See also: CHEF-3715 - def initialize(cache_path=nil) - @cache_path = cache_path || Chef::Config[:syntax_check_cache_path] || Chef::Config[:cache_options][:path] + # creating a file in the +cache_path+ directory. + def initialize(cache_path=Chef::Config[:syntax_check_cache_path]) + @cache_path = cache_path @cache_path_created = false end @@ -137,7 +127,7 @@ class Chef end def untested_template_files - template_files.reject do |file| + template_files.reject do |file| if validated?(file) Chef::Log.debug("Template #{file} is unchanged, skipping syntax check") true diff --git a/lib/chef/cookbook_site_streaming_uploader.rb b/lib/chef/cookbook_site_streaming_uploader.rb index abb5499042..92193fee33 100644 --- a/lib/chef/cookbook_site_streaming_uploader.rb +++ b/lib/chef/cookbook_site_streaming_uploader.rb @@ -208,8 +208,11 @@ class Chef @parts.inject(0) {|size, part| size + part.size} end - def read(how_much) - return nil if @part_no >= @parts.size + def read(how_much, dst_buf = nil) + if @part_no >= @parts.size + dst_buf.replace('') if dst_buf + return dst_buf + end how_much_current_part = @parts[@part_no].size - @part_offset @@ -228,15 +231,16 @@ class Chef @part_no += 1 @part_offset = 0 next_part = read(how_much_next_part) - current_part + if next_part + result = current_part + if next_part next_part else '' end else @part_offset += how_much_current_part - current_part + result = current_part end + dst_buf ? dst_buf.replace(result || '') : result end end diff --git a/lib/chef/cookbook_uploader.rb b/lib/chef/cookbook_uploader.rb index 9ba5b2bd8b..3ead26e56d 100644 --- a/lib/chef/cookbook_uploader.rb +++ b/lib/chef/cookbook_uploader.rb @@ -137,15 +137,17 @@ class Chef timestamp = Time.now.utc.iso8601 file_contents = File.open(file, "rb") {|f| f.read} # TODO - 5/28/2010, cw: make signing and sending the request streaming - sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object( - :http_method => :put, - :path => URI.parse(url).path, - :body => file_contents, - :timestamp => timestamp, - :user_id => rest.client_name - ) headers = { 'content-type' => 'application/x-binary', 'content-md5' => checksum64, :accept => 'application/json' } - headers.merge!(sign_obj.sign(OpenSSL::PKey::RSA.new(rest.signing_key))) + if rest.signing_key + sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object( + :http_method => :put, + :path => URI.parse(url).path, + :body => file_contents, + :timestamp => timestamp, + :user_id => rest.client_name + ) + headers.merge!(sign_obj.sign(OpenSSL::PKey::RSA.new(rest.signing_key))) + end begin RestClient::Resource.new(url, :headers=>headers, :timeout=>1800, :open_timeout=>1800).put(file_contents) diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb index 4e8b2a048e..5bd0ca064c 100644 --- a/lib/chef/cookbook_version.rb +++ b/lib/chef/cookbook_version.rb @@ -265,6 +265,18 @@ class Chef end end + # Query whether a template file +template_filename+ is available. File + # specificity for the given +node+ is obeyed in the lookup. + def has_template_for_node?(node, template_filename) + !!find_preferred_manifest_record(node, :templates, template_filename) + end + + # Query whether a cookbook_file file +cookbook_filename+ is available. File + # specificity for the given +node+ is obeyed in the lookup. + def has_cookbook_file_for_node?(node, cookbook_filename) + !!find_preferred_manifest_record(node, :files, cookbook_filename) + end + # Determine the most specific manifest record for the given # segment/filename, given information in the node. Throws # FileNotFound if there is no such segment and filename in the @@ -278,14 +290,7 @@ class Chef # :checksum => "1234" # } def preferred_manifest_record(node, segment, filename) - preferences = preferences_for_path(node, segment, filename) - - # ensure that we generate the manifest, which will also generate - # @manifest_records_by_path - manifest - - # in order of prefernce, look for the filename in the manifest - found_pref = preferences.find {|preferred_filename| @manifest_records_by_path[preferred_filename] } + found_pref = find_preferred_manifest_record(node, segment, filename) if found_pref @manifest_records_by_path[found_pref] else @@ -567,6 +572,17 @@ class Chef private + def find_preferred_manifest_record(node, segment, filename) + preferences = preferences_for_path(node, segment, filename) + + # ensure that we generate the manifest, which will also generate + # @manifest_records_by_path + manifest + + # in order of prefernce, look for the filename in the manifest + preferences.find {|preferred_filename| @manifest_records_by_path[preferred_filename] } + end + # For each filename, produce a mapping of base filename (i.e. recipe name # or attribute file) to on disk location def filenames_by_name(filenames) diff --git a/lib/chef/daemon.rb b/lib/chef/daemon.rb index 9a3d5a884a..e5abca29d8 100644 --- a/lib/chef/daemon.rb +++ b/lib/chef/daemon.rb @@ -6,9 +6,9 @@ # 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. @@ -18,12 +18,14 @@ # I love you Merb (lib/merb-core/server.rb) require 'chef/config' +require 'chef/run_lock' require 'etc' class Chef class Daemon class << self attr_accessor :name + attr_accessor :runlock # Daemonize the current process, managing pidfiles and process uid/gid # @@ -32,9 +34,9 @@ class Chef # def daemonize(name) @name = name - pid = pid_from_file - unless running? - remove_pid_file() + @runlock = RunLock.new(pid_file) + if runlock.test + # We've acquired the daemon lock. Now daemonize. Chef::Log.info("Daemonizing..") begin exit if fork @@ -45,53 +47,15 @@ class Chef $stdin.reopen("/dev/null") $stdout.reopen("/dev/null", "a") $stderr.reopen($stdout) - save_pid_file - at_exit { remove_pid_file } + runlock.save_pid rescue NotImplementedError => e Chef::Application.fatal!("There is no fork: #{e.message}") end else - Chef::Application.fatal!("Chef is already running pid #{pid}") - end - end - - # Check if Chef is running based on the pid_file - # ==== Returns - # Boolean:: - # True if Chef is running - # False if Chef is not running - # - def running? - if pid_from_file.nil? - false - else - Process.kill(0, pid_from_file) - true - end - rescue Errno::ESRCH, Errno::ENOENT - false - rescue Errno::EACCES => e - Chef::Application.fatal!("You don't have access to the PID file at #{pid_file}: #{e.message}") - end - - # Check if this process if forked from a Chef daemon - # ==== Returns - # Boolean:: - # True if this process is forked - # False if this process is not forked - # - def forked? - if running? and Process.ppid == pid_from_file.to_i - # chef daemon is running and this process is a child of it - true - elsif not running? and Process.ppid == 1 - # an orphaned fork, its parent becomes init, launchd, etc. after chef daemon dies - true - else - false + Chef::Application.fatal!("Chef is already running pid #{pid_from_file}") end end - + # Gets the pid file for @name # ==== Returns # String:: @@ -99,7 +63,7 @@ class Chef def pid_file Chef::Config[:pid_file] or "/tmp/#{@name}.pid" end - + # Suck the pid out of pid_file # ==== Returns # Integer:: @@ -112,31 +76,6 @@ class Chef rescue Errno::ENOENT, Errno::EACCES nil end - - # Store the PID on the filesystem - # This uses the Chef::Config[:pid_file] option, or "/tmp/name.pid" otherwise - # - def save_pid_file - file = pid_file - begin - FileUtils.mkdir_p(File.dirname(file)) - rescue Errno::EACCES => e - Chef::Application.fatal!("Failed store pid in #{File.dirname(file)}, permission denied: #{e.message}") - end - - begin - File.open(file, "w") { |f| f.write(Process.pid.to_s) } - rescue Errno::EACCES => e - Chef::Application.fatal!("Couldn't write to pidfile #{file}, permission denied: #{e.message}") - end - end - - # Delete the PID from the filesystem - def remove_pid_file - if not forked? then - FileUtils.rm(pid_file) if File.exists?(pid_file) - end - end # Change process user/group to those specified in Chef::Config # @@ -151,7 +90,7 @@ class Chef _change_privilege(Chef::Config[:user]) end end - + # Change privileges of the process to be the specified user and group # # ==== Parameters @@ -170,14 +109,14 @@ class Chef Chef::Application.fatal!("Failed to get UID for user #{user}, does it exist? #{e.message}") return false end - + begin target_gid = Etc.getgrnam(group).gid rescue ArgumentError => e Chef::Application.fatal!("Failed to get GID for group #{group}, does it exist? #{e.message}") return false end - + if (uid != target_uid) or (gid != target_gid) Process.initgroups(user, target_gid) Process::GID.change_privilege(target_gid) diff --git a/lib/chef/data_bag.rb b/lib/chef/data_bag.rb index dcc01ec743..5994e6f8d1 100644 --- a/lib/chef/data_bag.rb +++ b/lib/chef/data_bag.rb @@ -129,11 +129,10 @@ class Chef if Chef::Config[:why_run] Chef::Log.warn("In whyrun mode, so NOT performing data bag save.") else - chef_server_rest.put_rest("data/#{@name}", self) + create end rescue Net::HTTPServerException => e - raise e unless e.response.code == "404" - chef_server_rest.post_rest("data", self) + raise e unless e.response.code == "409" end self end diff --git a/lib/chef/dsl/include_recipe.rb b/lib/chef/dsl/include_recipe.rb index b4d076da10..fc95e38c75 100644 --- a/lib/chef/dsl/include_recipe.rb +++ b/lib/chef/dsl/include_recipe.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb index 494d3cee79..82beefeec9 100644 --- a/lib/chef/event_dispatch/base.rb +++ b/lib/chef/event_dispatch/base.rb @@ -295,7 +295,7 @@ class Chef # Called when a provider makes an assumption after a failed assertion # in whyrun mode, in order to allow execution to continue - def whyrun_assumption(action, resource, message) + def whyrun_assumption(action, resource, message) end ## TODO: deprecation warning. this way we can queue them up and present diff --git a/lib/chef/event_dispatch/dispatcher.rb b/lib/chef/event_dispatch/dispatcher.rb index 82da69a60c..c172a406d8 100644 --- a/lib/chef/event_dispatch/dispatcher.rb +++ b/lib/chef/event_dispatch/dispatcher.rb @@ -23,7 +23,7 @@ class Chef # define the forwarding in one go: # - # Define a method that will be forwarded to all + # Define a method that will be forwarded to all def self.def_forwarding_method(method_name) class_eval(<<-END_OF_METHOD, __FILE__, __LINE__) def #{method_name}(*args) diff --git a/lib/chef/file_access_control/windows.rb b/lib/chef/file_access_control/windows.rb index 35a16337ab..32ac2996bd 100644 --- a/lib/chef/file_access_control/windows.rb +++ b/lib/chef/file_access_control/windows.rb @@ -220,7 +220,7 @@ class Chef flags = 0 # - # Configure child inheritence only if the the resource is some + # Configure child inheritence only if the resource is some # type of a directory. # if resource.is_a? Chef::Resource::Directory diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb index 300311819f..e403ed9f5b 100644 --- a/lib/chef/formatters/doc.rb +++ b/lib/chef/formatters/doc.rb @@ -188,13 +188,13 @@ class Chef def resource_update_applied(resource, action, update) prefix = Chef::Config[:why_run] ? "Would " : "" Array(update).each do |line| - next if line.nil? + next if line.nil? output_record line if line.kind_of? String @output.color "\n - #{prefix}#{line}", :green - elsif line.kind_of? Array - # Expanded output - delta - # @todo should we have a resource_update_delta callback? + elsif line.kind_of? Array + # Expanded output - delta + # @todo should we have a resource_update_delta callback? line.each do |detail| @output.color "\n #{detail}", :white end @@ -216,7 +216,7 @@ class Chef # Called when a provider makes an assumption after a failed assertion # in whyrun mode, in order to allow execution to continue - def whyrun_assumption(action, resource, message) + def whyrun_assumption(action, resource, message) return unless message [ message ].flatten.each do |line| @output.color("\n * #{line}", :yellow) diff --git a/lib/chef/formatters/error_inspectors/api_error_formatting.rb b/lib/chef/formatters/error_inspectors/api_error_formatting.rb index bb5379ed3f..cb64955961 100644 --- a/lib/chef/formatters/error_inspectors/api_error_formatting.rb +++ b/lib/chef/formatters/error_inspectors/api_error_formatting.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/formatters/error_inspectors/compile_error_inspector.rb b/lib/chef/formatters/error_inspectors/compile_error_inspector.rb index 1fa8a70b52..93328adbe3 100644 --- a/lib/chef/formatters/error_inspectors/compile_error_inspector.rb +++ b/lib/chef/formatters/error_inspectors/compile_error_inspector.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/formatters/error_inspectors/cookbook_sync_error_inspector.rb b/lib/chef/formatters/error_inspectors/cookbook_sync_error_inspector.rb index 054984a50e..56a55a296b 100644 --- a/lib/chef/formatters/error_inspectors/cookbook_sync_error_inspector.rb +++ b/lib/chef/formatters/error_inspectors/cookbook_sync_error_inspector.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/formatters/error_inspectors/node_load_error_inspector.rb b/lib/chef/formatters/error_inspectors/node_load_error_inspector.rb index 7168ac0edb..e257ee30c0 100644 --- a/lib/chef/formatters/error_inspectors/node_load_error_inspector.rb +++ b/lib/chef/formatters/error_inspectors/node_load_error_inspector.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb b/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb index 9ad56bb70b..6f1f71b8f9 100644 --- a/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb +++ b/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb @@ -7,9 +7,9 @@ # 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. diff --git a/lib/chef/handler/json_file.rb b/lib/chef/handler/json_file.rb index 977c5a2c92..3473db1838 100644 --- a/lib/chef/handler/json_file.rb +++ b/lib/chef/handler/json_file.rb @@ -41,11 +41,11 @@ class Chef build_report_dir savetime = Time.now.strftime("%Y%m%d%H%M%S") File.open(File.join(config[:path], "chef-run-report-#{savetime}.json"), "w") do |file| - + #ensure start time and end time are output in the json properly in the event activesupport happens to be on the system run_data = data run_data[:start_time] = run_data[:start_time].to_s - run_data[:end_time] = run_data[:end_time].to_s + run_data[:end_time] = run_data[:end_time].to_s file.puts Chef::JSONCompat.to_json_pretty(run_data) end diff --git a/lib/chef/http.rb b/lib/chef/http.rb new file mode 100644 index 0000000000..2b2466843e --- /dev/null +++ b/lib/chef/http.rb @@ -0,0 +1,386 @@ +#-- +# Author:: Adam Jacob (<adam@opscode.com>) +# Author:: Thom May (<thom@clearairturbulence.org>) +# Author:: Nuo Yan (<nuo@opscode.com>) +# Author:: Christopher Brown (<cb@opscode.com>) +# Author:: Christopher Walters (<cw@opscode.com>) +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Copyright:: Copyright (c) 2009, 2010, 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 'net/https' +require 'uri' +require 'chef/http/basic_client' +require 'chef/monkey_patches/string' +require 'chef/monkey_patches/net_http' +require 'chef/config' +require 'chef/exceptions' + +class Chef + + # == Chef::HTTP + # Basic HTTP client, with support for adding features via middleware + class HTTP + + # Class for applying middleware behaviors to streaming + # responses. Collects stream handlers (if any) from each + # middleware. When #handle_chunk is called, the chunk gets + # passed to all handlers in turn for processing. + class StreamHandler + def initialize(middlewares, response) + middlewares = middlewares.flatten + @stream_handlers = [] + middlewares.each do |middleware| + stream_handler = middleware.stream_response_handler(response) + @stream_handlers << stream_handler unless stream_handler.nil? + end + end + + def handle_chunk(next_chunk) + @stream_handlers.inject(next_chunk) do |chunk, handler| + handler.handle_chunk(chunk) + end + end + + end + + + def self.middlewares + @middlewares ||= [] + end + + def self.use(middleware_class) + middlewares << middleware_class + end + + attr_reader :url + attr_reader :sign_on_redirect + attr_reader :redirect_limit + + attr_reader :middlewares + + # Create a HTTP client object. The supplied +url+ is used as the base for + # all subsequent requests. For example, when initialized with a base url + # http://localhost:4000, a call to +get+ with 'nodes' will make an + # HTTP GET request to http://localhost:4000/nodes + def initialize(url, options={}) + @url = url + @default_headers = options[:headers] || {} + @sign_on_redirect = true + @redirects_followed = 0 + @redirect_limit = 10 + + @middlewares = [] + self.class.middlewares.each do |middleware_class| + @middlewares << middleware_class.new(options) + end + end + + # Send an HTTP HEAD request to the path + # + # === Parameters + # path:: path part of the request URL + def head(path, headers={}) + request(:HEAD, path, headers) + end + + # Send an HTTP GET request to the path + # + # === Parameters + # path:: The path to GET + def get(path, headers={}) + request(:GET, path, headers) + end + + # Send an HTTP PUT request to the path + # + # === Parameters + # path:: path part of the request URL + def put(path, json, headers={}) + request(:PUT, path, headers, json) + end + + # Send an HTTP POST request to the path + # + # === Parameters + # path:: path part of the request URL + def post(path, json, headers={}) + request(:POST, path, headers, json) + end + + # Send an HTTP DELETE request to the path + # + # === Parameters + # path:: path part of the request URL + def delete(path, headers={}) + request(:DELETE, path, headers) + end + + # Makes an HTTP request to +path+ with the given +method+, +headers+, and + # +data+ (if applicable). + def request(method, path, headers={}, data=false) + url = create_url(path) + method, url, headers, data = apply_request_middleware(method, url, headers, data) + + response, rest_request, return_value = send_http_request(method, url, headers, data) + response, rest_request, return_value = apply_response_middleware(response, rest_request, return_value) + response.error! unless success_response?(response) + return_value + rescue Exception => exception + log_failed_request(response, return_value) unless response.nil? + + if exception.respond_to?(:chef_rest_request=) + exception.chef_rest_request = rest_request + end + raise + end + + # Makes a streaming download request, streaming the response body to a + # tempfile. If a block is given, the tempfile is passed to the block and + # the tempfile will automatically be unlinked after the block is executed. + # + # If no block is given, the tempfile is returned, which means it's up to + # you to unlink the tempfile when you're done with it. + def streaming_request(path, headers={}, &block) + url = create_url(path) + response, rest_request, return_value = nil, nil, nil + tempfile = nil + + method = :GET + method, url, headers, data = apply_request_middleware(method, url, headers, data) + + response, rest_request, return_value = send_http_request(method, url, headers, data) do |http_response| + if http_response.kind_of?(Net::HTTPSuccess) + tempfile = stream_to_tempfile(url, http_response) + if block_given? + begin + yield tempfile + ensure + tempfile && tempfile.close! + end + end + end + end + unless response.kind_of?(Net::HTTPSuccess) or response.kind_of?(Net::HTTPRedirection) + response.error! + end + tempfile + rescue Exception => e + log_failed_request(response, return_value) unless response.nil? + if e.respond_to?(:chef_rest_request=) + e.chef_rest_request = rest_request + end + raise + end + + def http_client(base_url=nil) + base_url ||= url + BasicClient.new(base_url) + end + + protected + + def create_url(path) + return path if path.is_a?(URI) + if path =~ /^(http|https):\/\// + URI.parse(path) + elsif path.nil? or path.empty? + URI.parse(@url) + else + URI.parse("#{@url}/#{path}") + end + end + + def apply_request_middleware(method, url, headers, data) + middlewares.inject([method, url, headers, data]) do |req_data, middleware| + middleware.handle_request(*req_data) + end + end + + def apply_response_middleware(response, rest_request, return_value) + middlewares.reverse.inject([response, rest_request, return_value]) do |res_data, middleware| + middleware.handle_response(*res_data) + end + end + + def log_failed_request(response, return_value) + return_value ||= {} + error_message = "HTTP Request Returned #{response.code} #{response.message}: " + error_message << (return_value["error"].respond_to?(:join) ? return_value["error"].join(", ") : return_value["error"].to_s) + Chef::Log.info(error_message) + end + + def success_response?(response) + response.kind_of?(Net::HTTPSuccess) || response.kind_of?(Net::HTTPRedirection) + end + + # Runs a synchronous HTTP request, with no middleware applied (use #request + # to have the middleware applied). The entire response will be loaded into memory. + def send_http_request(method, url, headers, body, &response_handler) + headers = build_headers(method, url, headers, body) + + retrying_http_errors(url) do + client = http_client(url) + return_value = nil + if block_given? + request, response = client.request(method, url, body, headers, &response_handler) + else + request, response = client.request(method, url, body, headers) {|r| r.read_body } + return_value = response.read_body + end + @last_response = response + + Chef::Log.debug("---- HTTP Status and Header Data: ----") + Chef::Log.debug("HTTP #{response.http_version} #{response.code} #{response.msg}") + + response.each do |header, value| + Chef::Log.debug("#{header}: #{value}") + end + Chef::Log.debug("---- End HTTP Status/Header Data ----") + + if response.kind_of?(Net::HTTPSuccess) + [response, request, return_value] + elsif response.kind_of?(Net::HTTPNotModified) # Must be tested before Net::HTTPRedirection because it's subclass. + [response, request, false] + elsif redirect_location = redirected_to(response) + if [:GET, :HEAD].include?(method) + follow_redirect do + send_http_request(method, create_url(redirect_location), headers, body, &response_handler) + end + else + raise Exceptions::InvalidRedirect, "#{method} request was redirected from #{url} to #{redirect_location}. Only GET and HEAD support redirects." + end + else + [response, request, nil] + end + end + end + + + # Wraps an HTTP request with retry logic. + # === Arguments + # url:: URL of the request, used for error messages + def retrying_http_errors(url) + http_attempts = 0 + begin + http_attempts += 1 + + yield + + rescue SocketError, Errno::ETIMEDOUT => e + e.message.replace "Error connecting to #{url} - #{e.message}" + raise e + rescue Errno::ECONNREFUSED + if http_retry_count - http_attempts + 1 > 0 + Chef::Log.error("Connection refused connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") + sleep(http_retry_delay) + retry + end + raise Errno::ECONNREFUSED, "Connection refused connecting to #{url}, giving up" + rescue Timeout::Error + if http_retry_count - http_attempts + 1 > 0 + Chef::Log.error("Timeout connecting to #{url}, retry #{http_attempts}/#{http_retry_count}") + sleep(http_retry_delay) + retry + end + raise Timeout::Error, "Timeout connecting to #{url}, giving up" + rescue Net::HTTPFatalError => e + if http_retry_count - http_attempts + 1 > 0 + sleep_time = 1 + (2 ** http_attempts) + rand(2 ** http_attempts) + Chef::Log.error("Server returned error for #{url}, retrying #{http_attempts}/#{http_retry_count} in #{sleep_time}s") + sleep(sleep_time) + retry + end + raise + end + end + + def http_retry_delay + config[:http_retry_delay] + end + + def http_retry_count + config[:http_retry_count] + end + + def config + Chef::Config + end + + def follow_redirect + raise Chef::Exceptions::RedirectLimitExceeded if @redirects_followed >= redirect_limit + @redirects_followed += 1 + Chef::Log.debug("Following redirect #{@redirects_followed}/#{redirect_limit}") + + yield + ensure + @redirects_followed = 0 + end + + private + + def redirected_to(response) + return nil unless response.kind_of?(Net::HTTPRedirection) + # Net::HTTPNotModified is undesired subclass of Net::HTTPRedirection so test for this + return nil if response.kind_of?(Net::HTTPNotModified) + response['location'] + end + + def build_headers(method, url, headers={}, json_body=false) + headers = @default_headers.merge(headers) + headers['Content-Length'] = json_body.bytesize.to_s if json_body + headers.merge!(Chef::Config[:custom_http_headers]) if Chef::Config[:custom_http_headers] + headers + end + + def stream_to_tempfile(url, response) + tf = Tempfile.open("chef-rest") + if Chef::Platform.windows? + tf.binmode # required for binary files on Windows platforms + end + Chef::Log.debug("Streaming download from #{url.to_s} to tempfile #{tf.path}") + # Stolen from http://www.ruby-forum.com/topic/166423 + # Kudos to _why! + + stream_handler = StreamHandler.new(middlewares, response) + + response.read_body do |chunk| + tf.write(stream_handler.handle_chunk(chunk)) + end + tf.close + tf + rescue Exception + tf.close! + raise + end + + + public + + ############################################################################ + # DEPRECATED + ############################################################################ + + # This is only kept around to provide access to cache control data in + # lib/chef/provider/remote_file/http.rb + # Find a better API. + def last_response + @last_response + end + + end +end + diff --git a/lib/chef/rest/auth_credentials.rb b/lib/chef/http/auth_credentials.rb index 00711c960d..bd73524b1f 100644 --- a/lib/chef/rest/auth_credentials.rb +++ b/lib/chef/http/auth_credentials.rb @@ -24,7 +24,7 @@ require 'chef/log' require 'mixlib/authentication/signedheaderauth' class Chef - class REST + class HTTP class AuthCredentials attr_reader :client_name, :key diff --git a/lib/chef/http/authenticator.rb b/lib/chef/http/authenticator.rb new file mode 100644 index 0000000000..489675ad66 --- /dev/null +++ b/lib/chef/http/authenticator.rb @@ -0,0 +1,89 @@ +#-- +# Author:: Daniel DeLeo (<dan@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/http/auth_credentials' +require 'chef/exceptions' +require 'openssl' + +class Chef + class HTTP + class Authenticator + + attr_reader :signing_key_filename + attr_reader :raw_key + attr_reader :attr_names + attr_reader :auth_credentials + + attr_accessor :sign_request + + def initialize(opts={}) + @raw_key = nil + @sign_request = true + @signing_key_filename = opts[:signing_key_filename] + @key = load_signing_key(opts[:signing_key_filename], opts[:raw_key]) + @auth_credentials = AuthCredentials.new(opts[:client_name], @key) + end + + def handle_request(method, url, headers={}, data=false) + headers.merge!(authentication_headers(method, url, data)) if sign_requests? + [method, url, headers, data] + end + + def handle_response(http_response, rest_request, return_value) + [http_response, rest_request, return_value] + end + + def stream_response_handler(response) + nil + end + + def sign_requests? + auth_credentials.sign_requests? && @sign_request + end + + def client_name + @auth_credentials.client_name + end + + def load_signing_key(key_file, raw_key = nil) + if (!!key_file) + @raw_key = IO.read(key_file).strip + elsif (!!raw_key) + @raw_key = raw_key.strip + else + return nil + end + @key = OpenSSL::PKey::RSA.new(@raw_key) + rescue SystemCallError, IOError => e + Chef::Log.warn "Failed to read the private key #{key_file}: #{e.inspect}" + raise Chef::Exceptions::PrivateKeyMissing, "I cannot read #{key_file}, which you told me to use to sign requests!" + rescue OpenSSL::PKey::RSAError + msg = "The file #{key_file} or :raw_key option does not contain a correctly formatted private key.\n" + msg << "The key file should begin with '-----BEGIN RSA PRIVATE KEY-----' and end with '-----END RSA PRIVATE KEY-----'" + raise Chef::Exceptions::InvalidPrivateKey, msg + end + + def authentication_headers(method, url, json_body=nil) + request_params = {:http_method => method, :path => url.path, :body => json_body, :host => "#{url.host}:#{url.port}"} + request_params[:body] ||= "" + auth_credentials.signature_headers(request_params) + end + + end + end +end diff --git a/lib/chef/http/basic_client.rb b/lib/chef/http/basic_client.rb new file mode 100644 index 0000000000..5ee0fbf88d --- /dev/null +++ b/lib/chef/http/basic_client.rb @@ -0,0 +1,114 @@ +#-- +# Author:: Adam Jacob (<adam@opscode.com>) +# Author:: Thom May (<thom@clearairturbulence.org>) +# Author:: Nuo Yan (<nuo@opscode.com>) +# Author:: Christopher Brown (<cb@opscode.com>) +# Author:: Christopher Walters (<cw@opscode.com>) +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Copyright:: Copyright (c) 2009, 2010 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 'uri' +require 'net/http' +require 'chef/http/ssl_policies' +require 'chef/http/http_request' + +class Chef + class HTTP + class BasicClient + + HTTPS = "https".freeze + + attr_reader :url + attr_reader :http_client + attr_reader :ssl_policy + + # Instantiate a BasicClient. + # === Arguments: + # url:: An URI for the remote server. + # === Options: + # ssl_policy:: The SSL Policy to use, defaults to DefaultSSLPolicy + def initialize(url, opts={}) + @url = url + @ssl_policy = opts[:ssl_policy] || DefaultSSLPolicy + @http_client = build_http_client + end + + def host + @url.host + end + + def port + @url.port + end + + def request(method, url, req_body, base_headers={}) + http_request = HTTPRequest.new(method, url, req_body, base_headers).http_request + Chef::Log.debug("Initiating #{method} to #{url}") + http_client.request(http_request) do |response| + yield response if block_given? + # http_client.request may not have the return signature we want, so + # force the issue: + return [http_request, response] + end + rescue OpenSSL::SSL::SSLError => e + Chef::Log.error("SSL Validation failure connecting to host: #{host} - #{e.message}") + raise + end + + #adapted from buildr/lib/buildr/core/transports.rb + def proxy_uri + proxy = Chef::Config["#{url.scheme}_proxy"] + proxy = URI.parse(proxy) if String === proxy + excludes = Chef::Config[:no_proxy].to_s.split(/\s*,\s*/).compact + excludes = excludes.map { |exclude| exclude =~ /:\d+$/ ? exclude : "#{exclude}:*" } + return proxy unless excludes.any? { |exclude| File.fnmatch(exclude, "#{host}:#{port}") } + end + + def build_http_client + http_client = http_client_builder.new(host, port) + + if url.scheme == HTTPS + configure_ssl(http_client) + end + + http_client.read_timeout = config[:rest_timeout] + http_client + end + + def config + Chef::Config + end + + def http_client_builder + http_proxy = proxy_uri + if http_proxy.nil? + Net::HTTP + else + Chef::Log.debug("Using #{http_proxy.host}:#{http_proxy.port} for proxy") + user = Chef::Config["#{url.scheme}_proxy_user"] + pass = Chef::Config["#{url.scheme}_proxy_pass"] + Net::HTTP.Proxy(http_proxy.host, http_proxy.port, user, pass) + end + end + + def configure_ssl(http_client) + http_client.use_ssl = true + ssl_policy.apply_to(http_client) + end + + end + end +end diff --git a/lib/chef/rest/cookie_jar.rb b/lib/chef/http/cookie_jar.rb index e3137708a2..418fb1d352 100644 --- a/lib/chef/rest/cookie_jar.rb +++ b/lib/chef/http/cookie_jar.rb @@ -23,7 +23,7 @@ require 'singleton' class Chef - class REST + class HTTP class CookieJar < Hash include Singleton end diff --git a/lib/chef/http/cookie_manager.rb b/lib/chef/http/cookie_manager.rb new file mode 100644 index 0000000000..f6dcf9aa32 --- /dev/null +++ b/lib/chef/http/cookie_manager.rb @@ -0,0 +1,56 @@ +#-- +# Author:: Daniel DeLeo (<dan@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/http/cookie_jar' + +class Chef + class HTTP + + # An HTTP middleware to manage storing/sending cookies in HTTP requests. + # Most HTTP communication in Chef does not need cookies, it was originally + # implemented to support OpenID, but it's not known who might be relying on + # it, so it's included with Chef::REST + class CookieManager + + def initialize(options={}) + @cookies = CookieJar.instance + end + + def handle_request(method, url, headers={}, data=false) + @host, @port = url.host, url.port + if @cookies.has_key?("#{@host}:#{@port}") + headers['Cookie'] = @cookies["#{@host}:#{@port}"] + end + [method, url, headers, data] + end + + def handle_response(http_response, rest_request, return_value) + if http_response['set-cookie'] + @cookies["#{@host}:#{@port}"] = http_response['set-cookie'] + end + [http_response, rest_request, return_value] + end + + def stream_response_handler(response) + nil + end + + + end + end +end diff --git a/lib/chef/http/decompressor.rb b/lib/chef/http/decompressor.rb new file mode 100644 index 0000000000..6010ffa698 --- /dev/null +++ b/lib/chef/http/decompressor.rb @@ -0,0 +1,137 @@ +#-- +# Author:: Daniel DeLeo (<dan@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 'zlib' +require 'chef/http/http_request' + +class Chef + class HTTP + + # Middleware-esque class for handling compression in HTTP responses. + class Decompressor + class NoopInflater + def inflate(chunk) + chunk + end + alias :handle_chunk :inflate + end + + class GzipInflater < Zlib::Inflate + def initialize + super(Zlib::MAX_WBITS + 16) + end + alias :handle_chunk :inflate + end + + class DeflateInflater < Zlib::Inflate + def initialize + super + end + alias :handle_chunk :inflate + end + + CONTENT_ENCODING = "content-encoding".freeze + GZIP = "gzip".freeze + DEFLATE = "deflate".freeze + IDENTITY = "identity".freeze + + def initialize(opts={}) + @disable_gzip = false + handle_options(opts) + end + + def handle_request(method, url, headers={}, data=false) + headers[HTTPRequest::ACCEPT_ENCODING] = HTTPRequest::ENCODING_GZIP_DEFLATE unless gzip_disabled? + [method, url, headers, data] + end + + def handle_response(http_response, rest_request, return_value) + # temporary hack, skip processing if return_value is false + # needed to keep conditional get stuff working correctly. + return [http_response, rest_request, return_value] if return_value == false + response_body = decompress_body(http_response) + http_response.body.replace(response_body) if http_response.body.respond_to?(:replace) + [http_response, rest_request, return_value] + end + + def decompress_body(response) + if gzip_disabled? || response.body.nil? + response.body + else + case response[CONTENT_ENCODING] + when GZIP + Chef::Log.debug "decompressing gzip response" + Zlib::Inflate.new(Zlib::MAX_WBITS + 16).inflate(response.body) + when DEFLATE + Chef::Log.debug "decompressing deflate response" + Zlib::Inflate.inflate(response.body) + else + response.body + end + end + end + + # This isn't used when this class is used as middleware; it returns an + # object you can use to unzip/inflate a streaming response. + def stream_response_handler(response) + if gzip_disabled? + NoopInflater.new + else + case response[CONTENT_ENCODING] + when GZIP + Chef::Log.debug "decompressing gzip stream" + GzipInflater.new + when DEFLATE + Chef::Log.debug "decompressing inflate stream" + DeflateInflater.new + else + NoopInflater.new + end + end + end + + + # gzip is disabled using the disable_gzip => true option in the + # constructor. When gzip is disabled, no 'Accept-Encoding' header will be + # set, and the response will not be decompressed, no matter what the + # Content-Encoding header of the response is. The intended use case for + # this is to work around situations where you request +file.tar.gz+, but + # the server responds with a content type of tar and a content encoding of + # gzip, tricking the client into decompressing the response so you end up + # with a tar archive (no gzip) named file.tar.gz + def gzip_disabled? + @disable_gzip + end + + private + + def handle_options(opts) + opts.each do |name, value| + case name.to_s + when 'disable_gzip' + @disable_gzip = value + end + end + end + + + end + end +end + + diff --git a/lib/chef/rest/rest_request.rb b/lib/chef/http/http_request.rb index ff9738de99..ec837f13f2 100644 --- a/lib/chef/rest/rest_request.rb +++ b/lib/chef/http/http_request.rb @@ -22,7 +22,6 @@ # require 'uri' require 'net/http' -require 'chef/rest/cookie_jar' # To load faster, we only want ohai's version string. # However, in ohai before 0.6.0, the version is defined @@ -36,8 +35,8 @@ end require 'chef/version' class Chef - class REST - class RESTRequest + class HTTP + class HTTPRequest engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby" @@ -72,8 +71,6 @@ class Chef def initialize(method, url, req_body, base_headers={}) @method, @url = method, url @request_body = nil - @cookies = CookieJar.instance - configure_http_client build_headers(base_headers) configure_http_request(req_body) end @@ -94,10 +91,10 @@ class Chef @url.path.empty? ? SLASH : @url.path end + # DEPRECATED. Call request on an HTTP client object instead. def call hide_net_http_bug do http_client.request(http_request) do |response| - store_cookie(response) yield response if block_given? response end @@ -108,6 +105,11 @@ class Chef Chef::Config end + # DEPRECATED. Call request on an HTTP client object instead. + def http_client + @http_client ||= BasicClient.new(url).http_client + end + private def hide_net_http_bug @@ -125,77 +127,12 @@ class Chef end end - def store_cookie(response) - if response['set-cookie'] - @cookies["#{host}:#{port}"] = response['set-cookie'] - end - end - def build_headers(headers) @headers = headers.dup - # TODO: need to set accept somewhere else - # headers.merge!('Accept' => "application/json") unless raw + # No response compression unless we asked for it explicitly: + @headers[HTTPRequest::ACCEPT_ENCODING] ||= "identity" @headers['X-Chef-Version'] = ::Chef::VERSION - @headers[ACCEPT_ENCODING] = ENCODING_GZIP_DEFLATE - - if @cookies.has_key?("#{host}:#{port}") - @headers['Cookie'] = @cookies["#{host}:#{port}"] - end - end - - #adapted from buildr/lib/buildr/core/transports.rb - def proxy_uri - proxy = Chef::Config["#{url.scheme}_proxy"] - proxy = URI.parse(proxy) if String === proxy - excludes = Chef::Config[:no_proxy].to_s.split(/\s*,\s*/).compact - excludes = excludes.map { |exclude| exclude =~ /:\d+$/ ? exclude : "#{exclude}:*" } - return proxy unless excludes.any? { |exclude| File.fnmatch(exclude, "#{host}:#{port}") } - end - - def configure_http_client - http_proxy = proxy_uri - if http_proxy.nil? - @http_client = Net::HTTP.new(host, port) - else - Chef::Log.debug("Using #{http_proxy.host}:#{http_proxy.port} for proxy") - user = Chef::Config["#{url.scheme}_proxy_user"] - pass = Chef::Config["#{url.scheme}_proxy_pass"] - @http_client = Net::HTTP.Proxy(http_proxy.host, http_proxy.port, user, pass).new(host, port) - end - if url.scheme == HTTPS - @http_client.use_ssl = true - if config[:ssl_verify_mode] == :verify_none - @http_client.verify_mode = OpenSSL::SSL::VERIFY_NONE - elsif config[:ssl_verify_mode] == :verify_peer - @http_client.verify_mode = OpenSSL::SSL::VERIFY_PEER - end - if config[:ssl_ca_path] - unless ::File.exist?(config[:ssl_ca_path]) - raise Chef::Exceptions::ConfigurationError, "The configured ssl_ca_path #{config[:ssl_ca_path]} does not exist" - end - @http_client.ca_path = config[:ssl_ca_path] - elsif config[:ssl_ca_file] - unless ::File.exist?(config[:ssl_ca_file]) - raise Chef::Exceptions::ConfigurationError, "The configured ssl_ca_file #{config[:ssl_ca_file]} does not exist" - end - @http_client.ca_file = config[:ssl_ca_file] - end - if (config[:ssl_client_cert] || config[:ssl_client_key]) - unless (config[:ssl_client_cert] && config[:ssl_client_key]) - raise Chef::Exceptions::ConfigurationError, "You must configure ssl_client_cert and ssl_client_key together" - end - unless ::File.exists?(config[:ssl_client_cert]) - raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_cert #{config[:ssl_client_cert]} does not exist" - end - unless ::File.exists?(config[:ssl_client_key]) - raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_key #{config[:ssl_client_key]} does not exist" - end - @http_client.cert = OpenSSL::X509::Certificate.new(::File.read(config[:ssl_client_cert])) - @http_client.key = OpenSSL::PKey::RSA.new(::File.read(config[:ssl_client_key])) - end - end - - @http_client.read_timeout = config[:rest_timeout] + @headers end @@ -225,6 +162,8 @@ class Chef password = URI.unescape(url.password) if url.password @http_request.basic_auth(user, password) end + + # Overwrite default UA @http_request[USER_AGENT] = self.class.user_agent end diff --git a/lib/chef/http/json_input.rb b/lib/chef/http/json_input.rb new file mode 100644 index 0000000000..741c48f5f6 --- /dev/null +++ b/lib/chef/http/json_input.rb @@ -0,0 +1,53 @@ +#-- +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Author:: John Keiser (<jkeiser@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/json_compat' + +class Chef + class HTTP + + # Middleware that takes json input and turns it into raw text + class JSONInput + + def initialize(opts={}) + end + + def handle_request(method, url, headers={}, data=false) + if data + headers["Content-Type"] = 'application/json' + data = Chef::JSONCompat.to_json(data) + # Force encoding to binary to fix SSL related EOFErrors + # cf. http://tickets.opscode.com/browse/CHEF-2363 + # http://redmine.ruby-lang.org/issues/5233 + data.force_encoding(Encoding::BINARY) if data.respond_to?(:force_encoding) + end + [method, url, headers, data] + end + + def handle_response(http_response, rest_request, return_value) + [http_response, rest_request, return_value] + end + + def stream_response_handler(response) + nil + end + + end + end +end diff --git a/lib/chef/http/json_output.rb b/lib/chef/http/json_output.rb new file mode 100644 index 0000000000..48407d933f --- /dev/null +++ b/lib/chef/http/json_output.rb @@ -0,0 +1,69 @@ +#-- +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Author:: John Keiser (<jkeiser@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/json_compat' +require 'chef/log' + +class Chef + class HTTP + + # Middleware that takes an HTTP response, parses it as JSON if possible. + class JSONOutput + + def initialize(opts={}) + @raw_output = opts[:raw_output] + @inflate_json_class = opts[:inflate_json_class] + end + + def handle_request(method, url, headers={}, data=false) + # Ideally this should always set Accept to application/json, but + # Chef::REST is sometimes used to make non-JSON requests, so it sets + # Accept to the desired value before middlewares get called. + headers['Accept'] ||= 'application/json' + [method, url, headers, data] + end + + def handle_response(http_response, rest_request, return_value) + # temporary hack, skip processing if return_value is false + # needed to keep conditional get stuff working correctly. + return [http_response, rest_request, return_value] if return_value == false + if http_response['content-type'] =~ /json/ + if @raw_output + return_value = http_response.body.to_s + else + if @inflate_json_class + return_value = Chef::JSONCompat.from_json(http_response.body.chomp) + else + return_value = Chef::JSONCompat.from_json(http_response.body.chomp, :create_additions => false) + end + end + [http_response, rest_request, return_value] + else + Chef::Log.warn("Expected JSON response, but got content-type '#{http_response['content-type']}'") + return [http_response, rest_request, http_response.body.to_s] + end + end + + def stream_response_handler(response) + nil + end + + end + end +end diff --git a/lib/chef/http/json_to_model_output.rb b/lib/chef/http/json_to_model_output.rb new file mode 100644 index 0000000000..9bc90a52ae --- /dev/null +++ b/lib/chef/http/json_to_model_output.rb @@ -0,0 +1,34 @@ +#-- +# Author:: Daniel DeLeo (<dan@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/http/json_output' + +class Chef + class HTTP + + # A Middleware-ish thing that takes an HTTP response, parses it as JSON if + # possible, and converts it into an appropriate model object if it contains + # a `json_class` key. + class JSONToModelOutput < JSONOutput + def initialize(opts={}) + opts[:inflate_json_class] = true if !opts.has_key?(:inflate_json_class) + super + end + end + end +end diff --git a/lib/chef/http/simple.rb b/lib/chef/http/simple.rb new file mode 100644 index 0000000000..0ecb28846c --- /dev/null +++ b/lib/chef/http/simple.rb @@ -0,0 +1,16 @@ +require 'chef/http' +require 'chef/http/authenticator' +require 'chef/http/decompressor' + + +class Chef + class HTTP + + class Simple < HTTP + + use Decompressor + use CookieManager + + end + end +end diff --git a/lib/chef/http/ssl_policies.rb b/lib/chef/http/ssl_policies.rb new file mode 100644 index 0000000000..17b46a6762 --- /dev/null +++ b/lib/chef/http/ssl_policies.rb @@ -0,0 +1,121 @@ +#-- +# Author:: Adam Jacob (<adam@opscode.com>) +# Author:: Thom May (<thom@clearairturbulence.org>) +# Author:: Nuo Yan (<nuo@opscode.com>) +# Author:: Christopher Brown (<cb@opscode.com>) +# Author:: Christopher Walters (<cw@opscode.com>) +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Copyright:: Copyright (c) 2009, 2010, 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 'openssl' + +class Chef + class HTTP + + # == Chef::HTTP::DefaultSSLPolicy + # Configures SSL behavior on an HTTP object via visitor pattern. + class DefaultSSLPolicy + + def self.apply_to(http_client) + new(http_client).apply + http_client + end + + attr_reader :http_client + + def initialize(http_client) + @http_client = http_client + end + + def apply + set_verify_mode + set_ca_store + set_custom_certs + set_client_credentials + end + + def set_verify_mode + if config[:ssl_verify_mode] == :verify_none + http_client.verify_mode = OpenSSL::SSL::VERIFY_NONE + elsif config[:ssl_verify_mode] == :verify_peer + http_client.verify_mode = OpenSSL::SSL::VERIFY_PEER + end + end + + def set_ca_store + if config[:ssl_ca_path] + unless ::File.exist?(config[:ssl_ca_path]) + raise Chef::Exceptions::ConfigurationError, "The configured ssl_ca_path #{config[:ssl_ca_path]} does not exist" + end + http_client.ca_path = config[:ssl_ca_path] + elsif config[:ssl_ca_file] + unless ::File.exist?(config[:ssl_ca_file]) + raise Chef::Exceptions::ConfigurationError, "The configured ssl_ca_file #{config[:ssl_ca_file]} does not exist" + end + http_client.ca_file = config[:ssl_ca_file] + end + end + + def set_custom_certs + unless http_client.cert_store + http_client.cert_store = OpenSSL::X509::Store.new + http_client.cert_store.set_default_paths + end + if config.trusted_certs_dir + certs = Dir.glob(File.join(config.trusted_certs_dir, "*.{crt,pem}")) + certs.each do |cert_file| + cert = OpenSSL::X509::Certificate.new(File.read(cert_file)) + http_client.cert_store.add_cert(cert) + end + end + end + + def set_client_credentials + if (config[:ssl_client_cert] || config[:ssl_client_key]) + unless (config[:ssl_client_cert] && config[:ssl_client_key]) + raise Chef::Exceptions::ConfigurationError, "You must configure ssl_client_cert and ssl_client_key together" + end + unless ::File.exists?(config[:ssl_client_cert]) + raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_cert #{config[:ssl_client_cert]} does not exist" + end + unless ::File.exists?(config[:ssl_client_key]) + raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_key #{config[:ssl_client_key]} does not exist" + end + http_client.cert = OpenSSL::X509::Certificate.new(::File.read(config[:ssl_client_cert])) + http_client.key = OpenSSL::PKey::RSA.new(::File.read(config[:ssl_client_key])) + end + end + + def config + Chef::Config + end + + end + + class APISSLPolicy < DefaultSSLPolicy + + def set_verify_mode + if config[:ssl_verify_mode] == :verify_peer or config[:verify_api_cert] + http_client.verify_mode = OpenSSL::SSL::VERIFY_PEER + elsif config[:ssl_verify_mode] == :verify_none + http_client.verify_mode = OpenSSL::SSL::VERIFY_NONE + end + end + end + + end +end diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index 9c48925216..341402242e 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -20,6 +20,7 @@ require 'forwardable' require 'chef/version' require 'mixlib/cli' +require 'chef/config_fetcher' require 'chef/mixin/convert_to_class_name' require 'chef/mixin/path_sanity' require 'chef/knife/core/subcommand_loader' @@ -314,7 +315,11 @@ class Chef config_file_settings end - def locate_config_file + def self.config_fetcher(candidate_config) + Chef::ConfigFetcher.new(candidate_config, Chef::Config.config_file_jail) + end + + def self.locate_config_file candidate_configs = [] # Look for $KNIFE_HOME/knife.rb (allow multiple knives config on same machine) @@ -326,8 +331,8 @@ class Chef candidate_configs << File.join(Dir.pwd, 'knife.rb') end # Look for $UPWARD/.chef/knife.rb - if self.class.chef_config_dir - candidate_configs << File.join(self.class.chef_config_dir, 'knife.rb') + if chef_config_dir + candidate_configs << File.join(chef_config_dir, 'knife.rb') end # Look for $HOME/.chef/knife.rb if ENV['HOME'] @@ -335,12 +340,12 @@ class Chef end candidate_configs.each do | candidate_config | - candidate_config = File.expand_path(candidate_config) - if File.exist?(candidate_config) - config[:config_file] = candidate_config - break + fetcher = config_fetcher(candidate_config) + if !fetcher.config_missing? + return candidate_config end end + return nil end # Apply Config in this order: @@ -379,6 +384,12 @@ class Chef Chef::Config[:chef_server_url] = config[:chef_server_url] if config[:chef_server_url] Chef::Config[:environment] = config[:environment] if config[:environment] + Chef::Config.local_mode = config[:local_mode] if config.has_key?(:local_mode) + if Chef::Config.local_mode && !Chef::Config.has_key?(:cookbook_path) && !Chef::Config.has_key?(:chef_repo_path) + Chef::Config.chef_repo_path = Chef::Config.find_chef_repo_path(Dir.pwd) + end + Chef::Config.chef_zero.port = config[:chef_zero_port] if config[:chef_zero_port] + # Expand a relative path from the config directory. Config from command # line should already be expanded, and absolute paths will be unchanged. if Chef::Config[:client_key] && config[:config_file] @@ -397,14 +408,20 @@ class Chef end def configure_chef - unless config[:config_file] - locate_config_file + if !config[:config_file] + located_config_file = self.class.locate_config_file + config[:config_file] = located_config_file if located_config_file end - # Don't try to load a knife.rb if it doesn't exist. + # Don't try to load a knife.rb if it wasn't specified. if config[:config_file] + fetcher = Chef::ConfigFetcher.new(config[:config_file], Chef::Config.config_file_jail) + if fetcher.config_missing? + ui.error("Specified config file #{config[:config_file]} does not exist#{Chef::Config.config_file_jail ? " or is not under config file jail #{Chef::Config.config_file_jail}" : ""}!") + exit 1 + end Chef::Log.debug("Using configuration from #{config[:config_file]}") - read_config_file(config[:config_file]) + read_config(fetcher.read_config, config[:config_file]) else # ...but do log a message if no config was found. Chef::Config[:color] = config[:color] @@ -415,24 +432,24 @@ class Chef apply_computed_config end - def read_config_file(file) - Chef::Config.from_file(file) + def read_config(config_content, config_file_path) + Chef::Config.from_string(config_content, config_file_path) rescue SyntaxError => e - ui.error "You have invalid ruby syntax in your config file #{file}" + ui.error "You have invalid ruby syntax in your config file #{config_file_path}" ui.info(ui.color(e.message, :red)) - if file_line = e.message[/#{Regexp.escape(file)}:[\d]+/] + if file_line = e.message[/#{Regexp.escape(config_file_path)}:[\d]+/] line = file_line[/:([\d]+)$/, 1].to_i - highlight_config_error(file, line) + highlight_config_error(config_file_path, line) end exit 1 rescue Exception => e - ui.error "You have an error in your config file #{file}" + ui.error "You have an error in your config file #{config_file_path}" ui.info "#{e.class.name}: #{e.message}" - filtered_trace = e.backtrace.grep(/#{Regexp.escape(file)}/) + filtered_trace = e.backtrace.grep(/#{Regexp.escape(config_file_path)}/) filtered_trace.each {|line| ui.msg(" " + ui.color(line, :red))} if !filtered_trace.empty? - line_nr = filtered_trace.first[/#{Regexp.escape(file)}:([\d]+)/, 1] - highlight_config_error(file, line_nr.to_i) + line_nr = filtered_trace.first[/#{Regexp.escape(config_file_path)}:([\d]+)/, 1] + highlight_config_error(config_file_path, line_nr.to_i) end exit 1 @@ -458,14 +475,19 @@ class Chef stdout.puts("USAGE: " + self.opt_parser.to_s) end - def run_with_pretty_exceptions + def run_with_pretty_exceptions(raise_exception = false) unless self.respond_to?(:run) ui.error "You need to add a #run method to your knife command before you can use it" end enforce_path_sanity - run + Chef::Application.setup_server_connectivity + begin + run + ensure + Chef::Application.destroy_server_connectivity + end rescue Exception => e - raise if Chef::Config[:verbosity] == 2 + raise if raise_exception || Chef::Config[:verbosity] == 2 humanize_exception(e) exit 100 end diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb index 942a5681b8..e88bbc1f19 100644 --- a/lib/chef/knife/bootstrap.rb +++ b/lib/chef/knife/bootstrap.rb @@ -89,6 +89,11 @@ class Chef :description => "The proxy server for the node being bootstrapped", :proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p } + option :bootstrap_no_proxy, + :long => "--bootstrap-no-proxy [NO_PROXY_URL|NO_PROXY_IP]", + :description => "Do not proxy locations for the node being bootstrapped", + :proc => Proc.new { |np| Chef::Config[:knife][:bootstrap_no_proxy] = np } + option :distro, :short => "-d DISTRO", :long => "--distro DISTRO", @@ -141,11 +146,13 @@ class Chef option :secret, :short => "-s SECRET", :long => "--secret ", - :description => "The secret key to use to encrypt data bag item values" + :description => "The secret key to use to encrypt data bag item values", + :proc => Proc.new { |s| Chef::Config[:knife][:secret] = s } option :secret_file, :long => "--secret-file SECRET_FILE", - :description => "A file containing the secret key to use to encrypt data bag item values" + :description => "A file containing the secret key to use to encrypt data bag item values", + :proc => Proc.new { |sf| Chef::Config[:knife][:secret_file] = sf } def find_template(template=nil) # Are we bootstrapping using an already shipped template? @@ -244,7 +251,7 @@ class Chef command = render_template(read_template) if config[:use_sudo] - command = config[:use_sudo_password] ? "echo #{config[:ssh_password]} | sudo -S #{command}" : "sudo #{command}" + command = config[:use_sudo_password] ? "echo '#{config[:ssh_password]}' | sudo -S #{command}" : "sudo #{command}" end command diff --git a/lib/chef/knife/bootstrap/chef-full.erb b/lib/chef/knife/bootstrap/chef-full.erb index 974b522653..549ffaea8c 100644 --- a/lib/chef/knife/bootstrap/chef-full.erb +++ b/lib/chef/knife/bootstrap/chef-full.erb @@ -1,5 +1,13 @@ bash -c ' -<%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%> +<%= "export https_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%> + +distro=`uname -s` + +if [ "X$distro" == "XSunOS" ]; then + if [ -e "/usr/sfw/bin" ]; then + export PATH=/usr/sfw/bin:$PATH + fi +fi exists() { if command -v $1 &>/dev/null diff --git a/lib/chef/knife/client_create.rb b/lib/chef/knife/client_create.rb index 5b5078b574..285254aef0 100644 --- a/lib/chef/knife/client_create.rb +++ b/lib/chef/knife/client_create.rb @@ -61,7 +61,7 @@ class Chef # We only get a private_key on client creation, not on client update. if client['private_key'] ui.info("Created #{output}") - + if config[:file] File.open(config[:file], "w") do |f| f.print(client['private_key']) diff --git a/lib/chef/knife/configure.rb b/lib/chef/knife/configure.rb index 8e725952b4..3ad4fac970 100644 --- a/lib/chef/knife/configure.rb +++ b/lib/chef/knife/configure.rb @@ -57,7 +57,7 @@ class Chef option :validation_key, :long => "--validation-key PATH", - :description => "The location of the location of the validation key (usually a file named validation.pem)" + :description => "The location of the validation key (usually a file named validation.pem)" def configure_chef # We are just faking out the system so that you can do this without a key specified diff --git a/lib/chef/knife/cookbook_create.rb b/lib/chef/knife/cookbook_create.rb index 4e6b8d0c1f..01bd8293f3 100644 --- a/lib/chef/knife/cookbook_create.rb +++ b/lib/chef/knife/cookbook_create.rb @@ -214,7 +214,7 @@ EOH TODO: Enter the cookbook description here. e.g. -This cookbook makes your favorite breakfast sandwhich. +This cookbook makes your favorite breakfast sandwich. == Requirements TODO: List your cookbook requirements. Be sure to include any requirements this cookbook has on platforms, libraries, other cookbooks, packages, operating systems, etc. @@ -224,7 +224,7 @@ e.g. - +toaster+ - #{cookbook_name} needs toaster to brown your bagel. == Attributes -TODO: List you cookbook attributes here. +TODO: List your cookbook attributes here. e.g. ==== #{cookbook_name}::default @@ -263,7 +263,7 @@ TODO: (optional) If this is a public cookbook, detail the process for contributi e.g. 1. Fork the repository on Github 2. Create a named feature branch (like `add_component_x`) -3. Write you change +3. Write your change 4. Write tests for your change (if applicable) 5. Run the tests, ensuring they all pass 6. Submit a Pull Request using Github @@ -278,7 +278,7 @@ EOH TODO: Enter the cookbook description here. e.g. -This cookbook makes your favorite breakfast sandwhich. +This cookbook makes your favorite breakfast sandwich. Requirements ------------ @@ -333,7 +333,7 @@ TODO: (optional) If this is a public cookbook, detail the process for contributi e.g. 1. Fork the repository on Github 2. Create a named feature branch (like `add_component_x`) -3. Write you change +3. Write your change 4. Write tests for your change (if applicable) 5. Run the tests, ensuring they all pass 6. Submit a Pull Request using Github @@ -349,7 +349,7 @@ EOH TODO: Enter the cookbook description here. e.g. - This cookbook makes your favorite breakfast sandwhich. + This cookbook makes your favorite breakfast sandwich. Requirements TODO: List your cookbook requirements. Be sure to include any requirements this cookbook has on platforms, libraries, other cookbooks, packages, operating systems, etc. @@ -386,7 +386,7 @@ Contributing e.g. 1. Fork the repository on Github 2. Create a named feature branch (like `add_component_x`) - 3. Write you change + 3. Write your change 4. Write tests for your change (if applicable) 5. Run the tests, ensuring they all pass 6. Submit a Pull Request using Github diff --git a/lib/chef/knife/cookbook_download.rb b/lib/chef/knife/cookbook_download.rb index 6132c9dca0..cb8eeb8edf 100644 --- a/lib/chef/knife/cookbook_download.rb +++ b/lib/chef/knife/cookbook_download.rb @@ -7,9 +7,9 @@ # 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. diff --git a/lib/chef/knife/cookbook_metadata_from_file.rb b/lib/chef/knife/cookbook_metadata_from_file.rb index eb1afa8b11..8e26251d6e 100644 --- a/lib/chef/knife/cookbook_metadata_from_file.rb +++ b/lib/chef/knife/cookbook_metadata_from_file.rb @@ -9,9 +9,9 @@ # 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. diff --git a/lib/chef/knife/cookbook_show.rb b/lib/chef/knife/cookbook_show.rb index 3545d20817..7c9cbebdb1 100644 --- a/lib/chef/knife/cookbook_show.rb +++ b/lib/chef/knife/cookbook_show.rb @@ -6,9 +6,9 @@ # 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. @@ -50,7 +50,7 @@ class Chef :long => "--with-uri", :description => "Show corresponding URIs" - def run + def run case @name_args.length when 4 # We are showing a specific file node = Hash.new diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb index d7a3bfd62c..913d171b3c 100644 --- a/lib/chef/knife/cookbook_site_install.rb +++ b/lib/chef/knife/cookbook_site_install.rb @@ -151,11 +151,11 @@ class Chef ui.info("Removing pre-existing version.") FileUtils.rmtree(cookbook_path) if File.directory?(cookbook_path) end - + def convert_path(upstream_file) if ENV['MSYSTEM'] == 'MINGW32' return upstream_file.sub(/^([[:alpha:]]):/, '/\1') - else + else return Shellwords.escape upstream_file end end diff --git a/lib/chef/knife/cookbook_site_list.rb b/lib/chef/knife/cookbook_site_list.rb index 96c4ef0eed..fe83b71388 100644 --- a/lib/chef/knife/cookbook_site_list.rb +++ b/lib/chef/knife/cookbook_site_list.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/knife/cookbook_site_search.rb b/lib/chef/knife/cookbook_site_search.rb index 5df7d67327..b636276cba 100644 --- a/lib/chef/knife/cookbook_site_search.rb +++ b/lib/chef/knife/cookbook_site_search.rb @@ -5,9 +5,9 @@ # 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. @@ -36,7 +36,7 @@ class Chef end new_start = start + cr["items"].length if new_start < cr["total"] - search_cookbook(query, items, new_start, cookbook_collection) + search_cookbook(query, items, new_start, cookbook_collection) else cookbook_collection end diff --git a/lib/chef/knife/cookbook_site_show.rb b/lib/chef/knife/cookbook_site_show.rb index a02dd61fc8..d15098e915 100644 --- a/lib/chef/knife/cookbook_site_show.rb +++ b/lib/chef/knife/cookbook_site_show.rb @@ -5,9 +5,9 @@ # 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. @@ -27,10 +27,10 @@ class Chef def run output(format_for_display(get_cookbook_data)) end - + def get_cookbook_data case @name_args.length - when 1 + when 1 noauth_rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{@name_args[0]}") when 2 noauth_rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{@name_args[0]}/versions/#{name_args[1].gsub('.', '_')}") @@ -45,7 +45,7 @@ class Chef end new_start = start + cr["items"].length if new_start < cr["total"] - get_cookbook_list(items, new_start, cookbook_collection) + get_cookbook_list(items, new_start, cookbook_collection) else cookbook_collection end diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb index 248d7c7a64..e1ad606c80 100644 --- a/lib/chef/knife/core/bootstrap_context.rb +++ b/lib/chef/knife/core/bootstrap_context.rb @@ -51,9 +51,9 @@ class Chef end def encrypted_data_bag_secret - @config[:secret] || begin - if @config[:secret_file] && File.exist?(@config[:secret_file]) - IO.read(File.expand_path(@config[:secret_file])) + knife_config[:secret] || begin + if knife_config[:secret_file] && File.exist?(knife_config[:secret_file]) + IO.read(File.expand_path(knife_config[:secret_file])) elsif @chef_config[:encrypted_data_bag_secret] && File.exist?(@chef_config[:encrypted_data_bag_secret]) IO.read(File.expand_path(@chef_config[:encrypted_data_bag_secret])) end @@ -78,6 +78,10 @@ CONFIG client_rb << %Q{https_proxy "#{knife_config[:bootstrap_proxy]}"\n} end + if knife_config[:bootstrap_no_proxy] + client_rb << %Q{no_proxy "#{knife_config[:bootstrap_no_proxy]}"\n} + end + if encrypted_data_bag_secret client_rb << %Q{encrypted_data_bag_secret "/etc/chef/encrypted_data_bag_secret"\n} end diff --git a/lib/chef/knife/core/node_presenter.rb b/lib/chef/knife/core/node_presenter.rb index a35baf2264..d1aab592ef 100644 --- a/lib/chef/knife/core/node_presenter.rb +++ b/lib/chef/knife/core/node_presenter.rb @@ -86,7 +86,7 @@ class Chef # Converts a Chef::Node object to a string suitable for output to a # terminal. If config[:medium_output] or config[:long_output] are set # the volume of output is adjusted accordingly. Uses colors if enabled - # in the the ui object. + # in the ui object. def summarize(data) if data.kind_of?(Chef::Node) node = data diff --git a/lib/chef/knife/core/subcommand_loader.rb b/lib/chef/knife/core/subcommand_loader.rb index 2475717441..91c0590121 100644 --- a/lib/chef/knife/core/subcommand_loader.rb +++ b/lib/chef/knife/core/subcommand_loader.rb @@ -6,9 +6,9 @@ # 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. @@ -112,7 +112,7 @@ class Chef check_spec_for_glob(spec, glob) end end.flatten - + files.concat gem_files files.uniq! if check_load_path @@ -133,9 +133,9 @@ class Chef else spec.require_paths.first end - + glob = File.join("#{spec.full_gem_path}/#{dirs}", glob) - + Dir[glob].map { |f| f.untaint } end end diff --git a/lib/chef/knife/core/ui.rb b/lib/chef/knife/core/ui.rb index f18d30a039..d0bdaa7ac0 100644 --- a/lib/chef/knife/core/ui.rb +++ b/lib/chef/knife/core/ui.rb @@ -167,7 +167,7 @@ class Chef if (!config[:disable_editing]) filename = "knife-edit-" 0.upto(20) { filename += rand(9).to_s } - filename << ".js" + filename << ".json" filename = File.join(Dir.tmpdir, filename) tf = File.open(filename, "w") tf.sync = true diff --git a/lib/chef/knife/data_bag_create.rb b/lib/chef/knife/data_bag_create.rb index e644ab78d3..55c1c71798 100644 --- a/lib/chef/knife/data_bag_create.rb +++ b/lib/chef/knife/data_bag_create.rb @@ -32,13 +32,15 @@ class Chef category "data bag" option :secret, - :short => "-s SECRET", - :long => "--secret ", - :description => "The secret key to use to encrypt data bag item values" + :short => "-s SECRET", + :long => "--secret ", + :description => "The secret key to use to encrypt data bag item values", + :proc => Proc.new { |s| Chef::Config[:knife][:secret] = s } option :secret_file, - :long => "--secret-file SECRET_FILE", - :description => "A file containing the secret key to use to encrypt data bag item values" + :long => "--secret-file SECRET_FILE", + :description => "A file containing the secret key to use to encrypt data bag item values", + :proc => Proc.new { |sf| Chef::Config[:knife][:secret_file] = sf } def read_secret if config[:secret] diff --git a/lib/chef/knife/data_bag_delete.rb b/lib/chef/knife/data_bag_delete.rb index f8e52018a6..575e9d604d 100644 --- a/lib/chef/knife/data_bag_delete.rb +++ b/lib/chef/knife/data_bag_delete.rb @@ -6,9 +6,9 @@ # 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. @@ -29,7 +29,7 @@ class Chef banner "knife data bag delete BAG [ITEM] (options)" category "data bag" - def run + def run if @name_args.length == 2 delete_object(Chef::DataBagItem, @name_args[1], "data_bag_item") do rest.delete_rest("data/#{@name_args[0]}/#{@name_args[1]}") diff --git a/lib/chef/knife/data_bag_edit.rb b/lib/chef/knife/data_bag_edit.rb index 234c77177d..b3f53af919 100644 --- a/lib/chef/knife/data_bag_edit.rb +++ b/lib/chef/knife/data_bag_edit.rb @@ -7,9 +7,9 @@ # 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. @@ -32,13 +32,15 @@ class Chef category "data bag" option :secret, - :short => "-s SECRET", - :long => "--secret ", - :description => "The secret key to use to encrypt data bag item values" + :short => "-s SECRET", + :long => "--secret ", + :description => "The secret key to use to encrypt data bag item values", + :proc => Proc.new { |s| Chef::Config[:knife][:secret] = s } option :secret_file, - :long => "--secret-file SECRET_FILE", - :description => "A file containing the secret key to use to encrypt data bag item values" + :long => "--secret-file SECRET_FILE", + :description => "A file containing the secret key to use to encrypt data bag item values", + :proc => Proc.new { |sf| Chef::Config[:knife][:secret_file] = sf } def read_secret if config[:secret] diff --git a/lib/chef/knife/data_bag_from_file.rb b/lib/chef/knife/data_bag_from_file.rb index 275cbeac52..4c90fe6c6c 100644 --- a/lib/chef/knife/data_bag_from_file.rb +++ b/lib/chef/knife/data_bag_from_file.rb @@ -35,18 +35,20 @@ class Chef category "data bag" option :secret, - :short => "-s SECRET", - :long => "--secret ", - :description => "The secret key to use to encrypt data bag item values" + :short => "-s SECRET", + :long => "--secret ", + :description => "The secret key to use to encrypt data bag item values", + :proc => Proc.new { |s| Chef::Config[:knife][:secret] = s } option :secret_file, - :long => "--secret-file SECRET_FILE", - :description => "A file containing the secret key to use to encrypt data bag item values" + :long => "--secret-file SECRET_FILE", + :description => "A file containing the secret key to use to encrypt data bag item values", + :proc => Proc.new { |sf| Chef::Config[:knife][:secret_file] = sf } option :all, - :short => "-a", - :long => "--all", - :description => "Upload all data bags or all items for specified data bags" + :short => "-a", + :long => "--all", + :description => "Upload all data bags or all items for specified data bags" def read_secret if config[:secret] diff --git a/lib/chef/knife/data_bag_list.rb b/lib/chef/knife/data_bag_list.rb index 31dcf984f6..5e556b60bc 100644 --- a/lib/chef/knife/data_bag_list.rb +++ b/lib/chef/knife/data_bag_list.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/knife/data_bag_show.rb b/lib/chef/knife/data_bag_show.rb index 81b1425f78..519859ca2d 100644 --- a/lib/chef/knife/data_bag_show.rb +++ b/lib/chef/knife/data_bag_show.rb @@ -7,9 +7,9 @@ # 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. @@ -32,13 +32,15 @@ class Chef category "data bag" option :secret, - :short => "-s SECRET", - :long => "--secret ", - :description => "The secret key to use to decrypt data bag item values" + :short => "-s SECRET", + :long => "--secret ", + :description => "The secret key to use to decrypt data bag item values", + :proc => Proc.new { |s| Chef::Config[:knife][:secret] = s } option :secret_file, - :long => "--secret-file SECRET_FILE", - :description => "A file containing the secret key to use to decrypt data bag item values" + :long => "--secret-file SECRET_FILE", + :description => "A file containing the secret key to use to decrypt data bag item values", + :proc => Proc.new { |sf| Chef::Config[:knife][:secret_file] = sf } def read_secret if config[:secret] diff --git a/lib/chef/knife/delete.rb b/lib/chef/knife/delete.rb index fb26b9ea35..0030c45026 100644 --- a/lib/chef/knife/delete.rb +++ b/lib/chef/knife/delete.rb @@ -5,6 +5,8 @@ class Chef class Delete < Chef::ChefFS::Knife banner "knife delete [PATTERN1 ... PATTERNn]" + category "path-based" + deps do require 'chef/chef_fs/file_system' end diff --git a/lib/chef/knife/deps.rb b/lib/chef/knife/deps.rb index c4b3678ff8..b2a39a0725 100644 --- a/lib/chef/knife/deps.rb +++ b/lib/chef/knife/deps.rb @@ -5,6 +5,8 @@ class Chef class Deps < Chef::ChefFS::Knife banner "knife deps PATTERN1 [PATTERNn]" + category "path-based" + deps do require 'chef/chef_fs/file_system' require 'chef/run_list' diff --git a/lib/chef/knife/diff.rb b/lib/chef/knife/diff.rb index 5a3a80544d..e5eda5228c 100644 --- a/lib/chef/knife/diff.rb +++ b/lib/chef/knife/diff.rb @@ -5,6 +5,8 @@ class Chef class Diff < Chef::ChefFS::Knife banner "knife diff PATTERNS" + category "path-based" + deps do require 'chef/chef_fs/command_line' end @@ -30,6 +32,10 @@ class Chef :description => "Select only files that are Added (A), Deleted (D), Modified (M), or have their type (i.e. regular file, directory) changed (T). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected." + option :cookbook_version, + :long => '--cookbook-version VERSION', + :description => 'Version of cookbook to download (if there are multiple versions and cookbook_versions is false)' + def run if config[:name_only] output_mode = :name_only diff --git a/lib/chef/knife/download.rb b/lib/chef/knife/download.rb index e8f26a74aa..5a432afd47 100644 --- a/lib/chef/knife/download.rb +++ b/lib/chef/knife/download.rb @@ -5,6 +5,8 @@ class Chef class Download < Chef::ChefFS::Knife banner "knife download PATTERNS" + category "path-based" + deps do require 'chef/chef_fs/command_line' end @@ -40,6 +42,10 @@ class Chef :default => true, :description => 'Turn off to avoid uploading existing files; only new (and possibly deleted) files with --no-diff' + option :cookbook_version, + :long => '--cookbook-version VERSION', + :description => 'Version of cookbook to download (if there are multiple versions and cookbook_versions is false)' + def run if name_args.length == 0 show_usage diff --git a/lib/chef/knife/edit.rb b/lib/chef/knife/edit.rb index ea068cb250..830da84a12 100644 --- a/lib/chef/knife/edit.rb +++ b/lib/chef/knife/edit.rb @@ -5,6 +5,8 @@ class Chef class Edit < Chef::ChefFS::Knife banner "knife edit [PATTERN1 ... PATTERNn]" + category "path-based" + deps do require 'chef/chef_fs/file_system' require 'chef/chef_fs/file_system/not_found_error' diff --git a/lib/chef/knife/environment_from_file.rb b/lib/chef/knife/environment_from_file.rb index af72f84622..3812024c9c 100644 --- a/lib/chef/knife/environment_from_file.rb +++ b/lib/chef/knife/environment_from_file.rb @@ -62,7 +62,7 @@ class Chef ui.info("Updated Environment #{updated.name}") end - + def run if config[:all] == true load_all_environments @@ -72,7 +72,7 @@ class Chef ui.fatal("You must specify a file to load") exit 1 end - + @name_args.each do |arg| load_environment(arg) end diff --git a/lib/chef/knife/index_rebuild.rb b/lib/chef/knife/index_rebuild.rb index 3e97c7751b..4b9fcdd159 100644 --- a/lib/chef/knife/index_rebuild.rb +++ b/lib/chef/knife/index_rebuild.rb @@ -40,7 +40,7 @@ class Chef nag output rest.post_rest("/search/reindex", {}) end - + end def grab_api_info @@ -55,7 +55,7 @@ class Chef r = exception.response parse_api_info(r) end - + # Only Chef 11+ servers will have version information in their # headers, and only those servers will lack an API endpoint for # index rebuilding. diff --git a/lib/chef/knife/list.rb b/lib/chef/knife/list.rb index 83d5c5a8c4..4338e195bd 100644 --- a/lib/chef/knife/list.rb +++ b/lib/chef/knife/list.rb @@ -5,6 +5,8 @@ class Chef class List < Chef::ChefFS::Knife banner "knife list [-dfR1p] [PATTERN1 ... PATTERNn]" + category "path-based" + deps do require 'chef/chef_fs/file_system' require 'highline' diff --git a/lib/chef/knife/raw.rb b/lib/chef/knife/raw.rb index ee22d1ade5..2756de1a5a 100644 --- a/lib/chef/knife/raw.rb +++ b/lib/chef/knife/raw.rb @@ -6,10 +6,13 @@ class Chef banner "knife raw REQUEST_PATH" deps do - require 'json' - require 'chef/rest' + require 'chef/json_compat' require 'chef/config' - require 'chef/chef_fs/raw_request' + require 'chef/http' + require 'chef/http/authenticator' + require 'chef/http/cookie_manager' + require 'chef/http/decompressor' + require 'chef/http/json_output' end option :method, @@ -29,6 +32,18 @@ class Chef :short => '-i FILE', :description => "Name of file to use for PUT or POST" + class RawInputServerAPI < Chef::HTTP + def initialize(options = {}) + options[:client_name] ||= Chef::Config[:node_name] + options[:signing_key_filename] ||= Chef::Config[:client_key] + super(Chef::Config[:chef_server_url], options) + end + use Chef::HTTP::JSONOutput + use Chef::HTTP::CookieManager + use Chef::HTTP::Decompressor + use Chef::HTTP::Authenticator + end + def run if name_args.length == 0 show_usage @@ -45,9 +60,20 @@ class Chef if config[:input] data = IO.read(config[:input]) end - chef_rest = Chef::REST.new(Chef::Config[:chef_server_url]) begin - output Chef::ChefFS::RawRequest.api_request(chef_rest, config[:method].to_sym, chef_rest.create_url(name_args[0]), {}, data) + method = config[:method].to_sym + + if config[:pretty] + chef_rest = RawInputServerAPI.new + result = chef_rest.request(method, name_args[0], {'Content-Type' => 'application/json'}, data) + unless result.is_a?(String) + result = Chef::JSONCompat.to_json_pretty(result) + end + else + chef_rest = RawInputServerAPI.new(:raw_output => true) + result = chef_rest.request(method, name_args[0], {'Content-Type' => 'application/json'}, data) + end + output result rescue Timeout::Error => e ui.error "Server timeout" exit 1 diff --git a/lib/chef/knife/show.rb b/lib/chef/knife/show.rb index b5e8aa9882..acf1996e96 100644 --- a/lib/chef/knife/show.rb +++ b/lib/chef/knife/show.rb @@ -5,6 +5,8 @@ class Chef class Show < Chef::ChefFS::Knife banner "knife show [PATTERN1 ... PATTERNn]" + category "path-based" + deps do require 'chef/chef_fs/file_system' require 'chef/chef_fs/file_system/not_found_error' diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb index 8cc05bd433..e1090fcca0 100644 --- a/lib/chef/knife/ssh.rb +++ b/lib/chef/knife/ssh.rb @@ -147,7 +147,7 @@ class Chef @action_nodes = q.search(:node, @name_args[0])[0] @action_nodes.each do |item| # we should skip the loop to next iteration if the item returned by the search is nil - next if item.nil? + next if item.nil? # if a command line attribute was not passed, and we have a cloud public_hostname, use that. # see #configure_attribute for the source of config[:attribute] and config[:override_attribute] if !config[:override_attribute] && item[:cloud] and item[:cloud][:public_hostname] @@ -211,15 +211,28 @@ class Chef end def print_data(host, data) - if data =~ /\n/ - data.split(/\n/).each { |d| print_data(host, d) } + @buffers ||= {} + if leftover = @buffers[host] + @buffers[host] = nil + print_data(host, leftover + data) else - padding = @longest - host.length - str = ui.color(host, :cyan) + (" " * (padding + 1)) + data - ui.msg(str) + if newline_index = data.index("\n") + line = data.slice!(0...newline_index) + data.slice!(0) + print_line(host, line) + print_data(host, data) + else + @buffers[host] = data + end end end + def print_line(host, data) + padding = @longest - host.length + str = ui.color(host, :cyan) + (" " * (padding + 1)) + data + ui.msg(str) + end + def ssh_command(command, subsession=nil) exit_status = 0 subsession ||= session @@ -232,6 +245,7 @@ class Chef ch.on_data do |ichannel, data| print_data(ichannel[:host], data) if data =~ /^knife sudo password: / + print_data(ichannel[:host], "\n") ichannel.send_data("#{get_password}\n") end end @@ -383,7 +397,7 @@ class Chef # Thus we can differentiate between a config file value and a command line override at this point by checking config[:attribute] # We can tell here if fqdn was passed from the command line, rather than being the default, by checking config[:attribute] # However, after here, we cannot tell these things, so we must preserve config[:attribute] - config[:override_attribute] = config[:attribute] || Chef::Config[:knife][:ssh_attribute] + config[:override_attribute] = config[:attribute] || Chef::Config[:knife][:ssh_attribute] config[:attribute] = (Chef::Config[:knife][:ssh_attribute] || config[:attribute] || "fqdn").strip diff --git a/lib/chef/knife/status.rb b/lib/chef/knife/status.rb index ceb394ce3a..5906a4a624 100644 --- a/lib/chef/knife/status.rb +++ b/lib/chef/knife/status.rb @@ -72,7 +72,7 @@ class Chef hours, minutes, seconds = time_difference_in_hms(node["ohai_time"]) hours_text = "#{hours} hour#{hours == 1 ? ' ' : 's'}" minutes_text = "#{minutes} minute#{minutes == 1 ? ' ' : 's'}" - run_list = ", #{node.run_list}." if config[:run_list] + run_list = "#{node.run_list}" if config[:run_list] if hours > 24 color = :red text = hours_text diff --git a/lib/chef/knife/upload.rb b/lib/chef/knife/upload.rb index f72b6ea616..8abd22b4dd 100644 --- a/lib/chef/knife/upload.rb +++ b/lib/chef/knife/upload.rb @@ -5,6 +5,8 @@ class Chef class Upload < Chef::ChefFS::Knife banner "knife upload PATTERNS" + category "path-based" + deps do require 'chef/chef_fs/command_line' end diff --git a/lib/chef/knife/xargs.rb b/lib/chef/knife/xargs.rb index be6db9d64f..dd8e848058 100644 --- a/lib/chef/knife/xargs.rb +++ b/lib/chef/knife/xargs.rb @@ -5,6 +5,8 @@ class Chef class Xargs < Chef::ChefFS::Knife banner "knife xargs [COMMAND]" + category "path-based" + deps do require 'chef/chef_fs/file_system' require 'chef/chef_fs/file_system/not_found_error' diff --git a/lib/chef/mixin/checksum.rb b/lib/chef/mixin/checksum.rb index 8217296915..1d9c99ec7e 100644 --- a/lib/chef/mixin/checksum.rb +++ b/lib/chef/mixin/checksum.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/mixin/command.rb b/lib/chef/mixin/command.rb index 55c028ff5f..2cc25e149e 100644 --- a/lib/chef/mixin/command.rb +++ b/lib/chef/mixin/command.rb @@ -6,9 +6,9 @@ # 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. @@ -41,23 +41,32 @@ class Chef # === Parameters # args<Hash>: A number of required and optional arguments - # command<String>, <Array>: A complete command with options to execute or a command and options as an Array + # command<String>, <Array>: A complete command with options to execute or a command and options as an Array # creates<String>: The absolute path to a file that prevents the command from running if it exists # cwd<String>: Working directory to execute command in, defaults to Dir.tmpdir # timeout<String>: How many seconds to wait for the command to execute before timing out # returns<String>: The single exit value command is expected to return, otherwise causes an exception # ignore_failure<Boolean>: Whether to raise an exception on failure, or just return the status # output_on_failure<Boolean>: Return output in raised exception regardless of Log.level - # + # # user<String>: The UID or user name of the user to execute the command as # group<String>: The GID or group name of the group to execute the command as # environment<Hash>: Pairs of environment variable names and their values to set before execution # # === Returns # Returns the exit status of args[:command] - def run_command(args={}) + def run_command(args={}) + status, stdout, stderr = run_command_and_return_stdout_stderr(args) + + status + end + + # works same as above, except that it returns stdout and stderr + # requirement => platforms like solaris 9,10 has wierd issues where + # even in command failure the exit code is zero, so we need to lookup stderr. + def run_command_and_return_stdout_stderr(args={}) command_output = "" - + args[:ignore_failure] ||= false args[:output_on_failure] ||= false @@ -68,28 +77,28 @@ class Chef return false end end - + status, stdout, stderr = output_of_command(args[:command], args) command_output << "STDOUT: #{stdout}" command_output << "STDERR: #{stderr}" handle_command_failures(status, command_output, args) - - status + + return status, stdout, stderr end - + def output_of_command(command, args) Chef::Log.debug("Executing #{command}") stderr_string, stdout_string, status = "", "", nil - + exec_processing_block = lambda do |pid, stdin, stdout, stderr| stdout_string, stderr_string = stdout.string.chomp, stderr.string.chomp end - + args[:cwd] ||= Dir.tmpdir unless ::File.directory?(args[:cwd]) raise Chef::Exceptions::Exec, "#{args[:cwd]} does not exist or is not a directory" end - + Dir.chdir(args[:cwd]) do if args[:timeout] begin @@ -103,17 +112,17 @@ class Chef else status = popen4(command, args, &exec_processing_block) end - + Chef::Log.debug("---- Begin output of #{command} ----") Chef::Log.debug("STDOUT: #{stdout_string}") Chef::Log.debug("STDERR: #{stderr_string}") Chef::Log.debug("---- End output of #{command} ----") Chef::Log.debug("Ran #{command} returned #{status.exitstatus}") end - + return status, stdout_string, stderr_string end - + def handle_command_failures(status, command_output, opts={}) unless opts[:ignore_failure] opts[:returns] ||= 0 @@ -129,7 +138,7 @@ class Chef end end end - + # Call #run_command but set LC_ALL to the system's current environment so it doesn't get changed to C. # # === Parameters diff --git a/lib/chef/mixin/convert_to_class_name.rb b/lib/chef/mixin/convert_to_class_name.rb index 7b4ec7ad3f..ece16990a1 100644 --- a/lib/chef/mixin/convert_to_class_name.rb +++ b/lib/chef/mixin/convert_to_class_name.rb @@ -7,9 +7,9 @@ # 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. @@ -27,20 +27,20 @@ class Chef str.gsub!(/[^A-Za-z0-9_]/,'_') rname = nil regexp = %r{^(.+?)(_(.+))?$} - + mn = str.match(regexp) if mn rname = mn[1].capitalize while mn && mn[3] - mn = mn[3].match(regexp) + mn = mn[3].match(regexp) rname << mn[1].capitalize if mn end end rname end - + def convert_to_snake_case(str, namespace=nil) str = str.dup str.sub!(/^#{namespace}(\:\:)?/, '') if namespace @@ -49,17 +49,17 @@ class Chef str.sub!(/^\_/, "") str end - + def snake_case_basename(str) with_namespace = convert_to_snake_case(str) with_namespace.split("::").last.sub(/^_/, '') end - + def filename_to_qualified_string(base, filename) file_base = File.basename(filename, ".rb") base.to_s + (file_base == 'default' ? '' : "_#{file_base}") end - + end end end diff --git a/lib/chef/mixin/create_path.rb b/lib/chef/mixin/create_path.rb index 9b5dba14f2..9d1248e907 100644 --- a/lib/chef/mixin/create_path.rb +++ b/lib/chef/mixin/create_path.rb @@ -6,9 +6,9 @@ # 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. @@ -18,21 +18,21 @@ class Chef module Mixin module CreatePath - + # Creates a given path, including all directories that lead up to it. # Like mkdir_p, but without the leaking. # # === Parameters - # file_path<String, Array>:: A string that represents the path to create, + # file_path<String, Array>:: A string that represents the path to create, # or an Array with the path-parts. # # === Returns # The created file_path. def create_path(file_path) unless file_path.kind_of?(String) || file_path.kind_of?(Array) - raise ArgumentError, "file_path must be a string or an array!" + raise ArgumentError, "file_path must be a string or an array!" end - + if file_path.kind_of?(String) file_path = File.expand_path(file_path).split(File::SEPARATOR) file_path.shift if file_path[0] == '' @@ -41,17 +41,17 @@ class Chef file_path[0] = "#{File::SEPARATOR}#{file_path[0]}" end end - + file_path.each_index do |i| create_path = File.join(file_path[0, i + 1]) unless File.directory?(create_path) Chef::Log.debug("Creating directory #{create_path}") Dir.mkdir(create_path) - end + end end File.expand_path(File.join(file_path)) end - + end end end diff --git a/lib/chef/mixin/deep_merge.rb b/lib/chef/mixin/deep_merge.rb index 1f2125be01..9fa86948b6 100644 --- a/lib/chef/mixin/deep_merge.rb +++ b/lib/chef/mixin/deep_merge.rb @@ -8,9 +8,9 @@ # 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. diff --git a/lib/chef/mixin/from_file.rb b/lib/chef/mixin/from_file.rb index 609fe1de55..0d1ddca4fa 100644 --- a/lib/chef/mixin/from_file.rb +++ b/lib/chef/mixin/from_file.rb @@ -7,9 +7,9 @@ # 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. @@ -20,9 +20,9 @@ class Chef module Mixin module FromFile - - # Loads a given ruby file, and runs instance_eval against it in the context of the current - # object. + + # Loads a given ruby file, and runs instance_eval against it in the context of the current + # object. # # Raises an IOError if the file cannot be found, or is not readable. def from_file(filename) @@ -33,7 +33,7 @@ class Chef end end - # Loads a given ruby file, and runs class_eval against it in the context of the current + # Loads a given ruby file, and runs class_eval against it in the context of the current # object. # # Raises an IOError if the file cannot be found, or is not readable. diff --git a/lib/chef/mixin/language_include_recipe.rb b/lib/chef/mixin/language_include_recipe.rb index b534b6628f..d85e5c682d 100644 --- a/lib/chef/mixin/language_include_recipe.rb +++ b/lib/chef/mixin/language_include_recipe.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/mixin/params_validate.rb b/lib/chef/mixin/params_validate.rb index a9822df134..a9799f749c 100644 --- a/lib/chef/mixin/params_validate.rb +++ b/lib/chef/mixin/params_validate.rb @@ -6,9 +6,9 @@ # 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. @@ -20,7 +20,7 @@ class Chef end module Mixin module ParamsValidate - + # Takes a hash of options, along with a map to validate them. Returns the original # options hash, plus any changes that might have been made (through things like setting # default values in the validation map) @@ -28,19 +28,19 @@ class Chef # For example: # # validate({ :one => "neat" }, { :one => { :kind_of => String }}) - # + # # Would raise an exception if the value of :one above is not a kind_of? string. Valid # map options are: # # :default:: Sets the default value for this parameter. - # :callbacks:: Takes a hash of Procs, which should return true if the argument is valid. + # :callbacks:: Takes a hash of Procs, which should return true if the argument is valid. # The key will be inserted into the error message if the Proc does not return true: # "Option #{key}'s value #{value} #{message}!" - # :kind_of:: Ensure that the value is a kind_of?(Whatever). If passed an array, it will ensure + # :kind_of:: Ensure that the value is a kind_of?(Whatever). If passed an array, it will ensure # that the value is one of those types. # :respond_to:: Ensure that the value has a given method. Takes one method name or an array of # method names. - # :required:: Raise an exception if this parameter is missing. Valid values are true or false, + # :required:: Raise an exception if this parameter is missing. Valid values are true or false, # by default, options are not required. # :regex:: Match the value of the paramater against a regular expression. # :equal_to:: Match the value of the paramater with ==. An array means it can be equal to any @@ -48,12 +48,12 @@ class Chef def validate(opts, map) #-- # validate works by taking the keys in the validation map, assuming it's a hash, and - # looking for _pv_:symbol as methods. Assuming it find them, it calls the right - # one. + # looking for _pv_:symbol as methods. Assuming it find them, it calls the right + # one. #++ raise ArgumentError, "Options must be a hash" unless opts.kind_of?(Hash) - raise ArgumentError, "Validation Map must be a hash" unless map.kind_of?(Hash) - + raise ArgumentError, "Validation Map must be a hash" unless map.kind_of?(Hash) + map.each do |key, validation| unless key.kind_of?(Symbol) || key.kind_of?(String) raise ArgumentError, "Validation map keys must be symbols or strings!" @@ -76,7 +76,7 @@ class Chef end opts end - + def lazy(&block) DelayedEvaluator.new(&block) end @@ -99,9 +99,9 @@ class Chef self.instance_variable_set(iv_symbol, val) end end - + private - + # Return the value of a parameter, or nil if it doesn't exist. def _pv_opts_lookup(opts, key) if opts.has_key?(key.to_s) @@ -112,7 +112,7 @@ class Chef nil end end - + # Raise an exception if the parameter is not found. def _pv_required(opts, key, is_required=true) if is_required @@ -124,7 +124,7 @@ class Chef end end end - + def _pv_equal_to(opts, key, to_be) value = _pv_opts_lookup(opts, key) unless value.nil? @@ -137,7 +137,7 @@ class Chef end end end - + # Raise an exception if the parameter is not a kind_of?(to_be) def _pv_kind_of(opts, key, to_be) value = _pv_opts_lookup(opts, key) @@ -151,7 +151,7 @@ class Chef end end end - + # Raise an exception if the parameter does not respond to a given set of methods. def _pv_respond_to(opts, key, method_name_list) value = _pv_opts_lookup(opts, key) @@ -181,7 +181,7 @@ class Chef end end end - + # Assign a default value to a parameter. def _pv_default(opts, key, default_value) value = _pv_opts_lookup(opts, key) @@ -189,7 +189,7 @@ class Chef opts[key] = default_value end end - + # Check a parameter against a regular expression. def _pv_regex(opts, key, regex) value = _pv_opts_lookup(opts, key) @@ -207,7 +207,7 @@ class Chef end end end - + # Check a parameter against a hash of proc's. def _pv_callbacks(opts, key, callbacks) raise ArgumentError, "Callback list must be a hash!" unless callbacks.kind_of?(Hash) diff --git a/lib/chef/mixin/shell_out.rb b/lib/chef/mixin/shell_out.rb index 4eaa509f8b..f0c2ba2000 100644 --- a/lib/chef/mixin/shell_out.rb +++ b/lib/chef/mixin/shell_out.rb @@ -15,13 +15,22 @@ # See the License for the specific language governing permissions and # limitations under the License. +# chef/shell_out has been deprecated in favor of mixlib/shellout +# chef/shell_out is still required here to ensure backward compatibility require 'chef/shell_out' + +require 'mixlib/shellout' require 'chef/config' class Chef module Mixin module ShellOut + # shell_out! runs a command on the system and will raise an error if the command fails, which is what you want + # for debugging, shell_out and shell_out! both will display command output to the tty when the log level is debug + # Generally speaking, 'extend Chef::Mixin::ShellOut' in your recipes and include 'Chef::Mixin::ShellOut' in your LWRPs + # You can also call Mixlib::Shellout.new directly, but you lose all of the above functionality + def shell_out(*command_args) cmd = Mixlib::ShellOut.new(*run_command_compatible_options(command_args)) if STDOUT.tty? && !Chef::Config[:daemon] && Chef::Log.debug? diff --git a/lib/chef/mixin/template.rb b/lib/chef/mixin/template.rb index 9208ce057e..ae23336581 100644 --- a/lib/chef/mixin/template.rb +++ b/lib/chef/mixin/template.rb @@ -121,17 +121,6 @@ class Chef ### def _render_template(template, context) - # CHEF-2991 - # Erubis always emits unix line endings during template - # rendering. This results in automatic conversion of windows - # line endings to linux line endings if the original template - # contains windows line endings. In order to fix this we - # determine the line ending style of the template before - # rendering and convert the line endings of the output if needed - # If template contains any windows line endings we emit - # the template result with windows line endings. - windows_line_endings = template.include? "\r\n" - begin eruby = Erubis::Eruby.new(template) output = eruby.evaluate(context) @@ -139,11 +128,19 @@ class Chef raise TemplateError.new(e, template, context) end - if windows_line_endings - # Convert line endings from "\n" -> "\r\n". Also converts - # "\r\n" -> "\r\n". - # This makes the regex match on all of "\r\n", so we don't - # accidentally convert "\r\n" -> "\r\r\n". + # CHEF-4399 + # Erubis always emits unix line endings during template + # rendering. Chef used to convert line endings to the + # original line endings in the template. However this + # created problems in cases when cookbook developer is + # coding the cookbook on windows but using it on non-windows + # platforms. + # The safest solution is to make sure that native to the + # platform we are running on is used in order to minimize + # potential issues for the applications that will consume + # this template. + + if Chef::Platform.windows? output = output.gsub(/\r?\n/,"\r\n") end diff --git a/lib/chef/mixin/why_run.rb b/lib/chef/mixin/why_run.rb index 788e2fe2bc..d650e3332f 100644 --- a/lib/chef/mixin/why_run.rb +++ b/lib/chef/mixin/why_run.rb @@ -178,8 +178,8 @@ class Chef # when the requirement is not met and Chef is executing in why run # mode # - # If no failure_message is provided (above), then execution - # will be allowed to continue in both whyrun an dnon-whyrun + # If no failure_message is provided (above), then execution + # will be allowed to continue in both whyrun and non-whyrun # mode # # With a service resource that requires /etc/init.d/service-name to exist: @@ -196,16 +196,16 @@ class Chef @resource_modifier = resource_modifier end - # Prevents associated actions from being invoked in whyrun mode. - # This will also stop further processing of assertions for a given action. - # - # An example from the template provider: if the source template doesn't exist - # we can't parse it in the action_create block of template - something that we do - # even in whyrun mode. Because the soruce template may have been created in an earlier + # Prevents associated actions from being invoked in whyrun mode. + # This will also stop further processing of assertions for a given action. + # + # An example from the template provider: if the source template doesn't exist + # we can't parse it in the action_create block of template - something that we do + # even in whyrun mode. Because the source template may have been created in an earlier # step, we still want to keep going in whyrun mode. - # + # # assert(:create, :create_if_missing) do |a| - # a.assertion { File::exists?(@new_resource.source) } + # a.assertion { File::exists?(@new_resource.source) } # a.whyrun "Template source file does not exist, assuming it would have been created." # a.block_action! # end @@ -214,7 +214,7 @@ class Chef @block_action = true end - def block_action? + def block_action? @block_action end @@ -258,7 +258,7 @@ class Chef # Check to see if a given action is blocked by a failed assertion # # Takes the action name to be verified. - def action_blocked?(action) + def action_blocked?(action) @blocked_actions.include?(action) end @@ -296,9 +296,9 @@ class Chef # "You don't have sufficient privileges to delete #{@new_resource.path}") # end # - # A Template provider that will prevent action execution but continue the run in + # A Template provider that will prevent action execution but continue the run in # whyrun mode if the template source is not available. - # assert(:create, :create_if_missing) do |a| + # assert(:create, :create_if_missing) do |a| # a.assertion { File::exist?(@new_resource.source) } # a.failure_message Chef::Exceptions::TemplateError, "Template #{@new_resource.source} could not be found exist." # a.whyrun "Template source #{@new_resource.source} does not exist. Assuming it would have been created." @@ -318,9 +318,9 @@ class Chef # Run the assertion and assumption logic. def run(action) - @assertions[action.to_sym].each do |a| + @assertions[action.to_sym].each do |a| a.run(action, events, @resource) - if a.assertion_failed? and a.block_action? + if a.assertion_failed? and a.block_action? @blocked_actions << action return end diff --git a/lib/chef/mixin/windows_architecture_helper.rb b/lib/chef/mixin/windows_architecture_helper.rb index 38c08e236d..c13278693f 100644 --- a/lib/chef/mixin/windows_architecture_helper.rb +++ b/lib/chef/mixin/windows_architecture_helper.rb @@ -6,9 +6,9 @@ # 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. @@ -17,7 +17,7 @@ # -require 'chef/exceptions' +require 'chef/exceptions' require 'win32/api' if Chef::Platform.windows? class Chef @@ -32,7 +32,7 @@ class Chef is_i386_windows_process? && node_windows_architecture(node) == :x86_64 && desired_architecture == :x86_64 - end + end def node_supports_windows_architecture?(node, desired_architecture) assert_valid_windows_architecture!(desired_architecture) @@ -85,7 +85,7 @@ class Chef end end end - + end end end diff --git a/lib/chef/mixin/xml_escape.rb b/lib/chef/mixin/xml_escape.rb index dac2f0c6af..ceb45df3e6 100644 --- a/lib/chef/mixin/xml_escape.rb +++ b/lib/chef/mixin/xml_escape.rb @@ -7,9 +7,9 @@ # 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. @@ -18,26 +18,26 @@ #-- # Portions of this code are adapted from Sam Ruby's xchar.rb -# http://intertwingly.net/stories/2005/09/28/xchar.rb +# http://intertwingly.net/stories/2005/09/28/xchar.rb # # Such code appears here under Sam's original MIT license, while portions of # this file are covered by the above Apache License. For a completely MIT # licensed version, please see Sam's original. # # Thanks, Sam! -# -# Copyright (c) 2005, Sam Ruby -# +# +# Copyright (c) 2005, Sam Ruby +# # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: -# +# # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -99,7 +99,7 @@ class Chef } # http://www.w3.org/TR/REC-xml/#charsets - VALID = [[0x9, 0xA, 0xD], (0x20..0xD7FF), + VALID = [[0x9, 0xA, 0xD], (0x20..0xD7FF), (0xE000..0xFFFD), (0x10000..0x10FFFF)] def xml_escape(unescaped_str) @@ -118,7 +118,7 @@ class Chef char = PREDEFINED[char] || (char<128 ? char.chr : "&##{char};") end end - + module FastXS extend self diff --git a/lib/chef/monkey_patches/numeric.rb b/lib/chef/monkey_patches/numeric.rb index 1f5ff14209..f4612fdbf3 100644 --- a/lib/chef/monkey_patches/numeric.rb +++ b/lib/chef/monkey_patches/numeric.rb @@ -8,7 +8,7 @@ end # String elements referenced with [] <= 1.8.6 return a Fixnum. Cheat to allow # for the simpler "test"[2].ord construct -class Numeric +class Numeric def ord return self end diff --git a/lib/chef/monkey_patches/regexp.rb b/lib/chef/monkey_patches/regexp.rb index 9304209edf..8a7ee77cb5 100644 --- a/lib/chef/monkey_patches/regexp.rb +++ b/lib/chef/monkey_patches/regexp.rb @@ -1,5 +1,5 @@ # Copyright (c) 2009 Marc-Andre Lafortune -# +# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -7,10 +7,10 @@ # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: -# +# # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -31,4 +31,4 @@ class Regexp end end end -end
\ No newline at end of file +end diff --git a/lib/chef/monkey_patches/string.rb b/lib/chef/monkey_patches/string.rb index c77c5c8816..f91e27ddc5 100644 --- a/lib/chef/monkey_patches/string.rb +++ b/lib/chef/monkey_patches/string.rb @@ -6,9 +6,9 @@ # 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. @@ -39,7 +39,7 @@ class String end end -# <= 1.8.6 needs some ord! +# <= 1.8.6 needs some ord! class String unless method_defined?(:ord) def ord diff --git a/lib/chef/monkey_patches/tempfile.rb b/lib/chef/monkey_patches/tempfile.rb index 3135fb1a00..b9179f182b 100644 --- a/lib/chef/monkey_patches/tempfile.rb +++ b/lib/chef/monkey_patches/tempfile.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/node.rb b/lib/chef/node.rb index 6bd2226ac8..007bd3c560 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -290,6 +290,14 @@ class Chef normal[:tags] end + def tag(*tags) + tags.each do |tag| + self.normal[:tags].push(tag.to_s) unless self[:tags].include? tag.to_s + end + + self[:tags] + end + # Extracts the run list from +attrs+ and applies it. Returns the remaining attributes def consume_run_list(attrs) attrs = attrs ? attrs.dup : {} diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb index a417406721..66569cf0e1 100644 --- a/lib/chef/node/attribute.rb +++ b/lib/chef/node/attribute.rb @@ -243,7 +243,7 @@ class Chef end # Clears merged_attributes, which will cause it to be recomputed on the - # next access. + # next access. def reset_cache @merged_attributes = nil @combined_default = nil diff --git a/lib/chef/platform/provider_mapping.rb b/lib/chef/platform/provider_mapping.rb index 1a282624c8..a252bdc100 100644 --- a/lib/chef/platform/provider_mapping.rb +++ b/lib/chef/platform/provider_mapping.rb @@ -173,6 +173,17 @@ class Chef :ifconfig => Chef::Provider::Ifconfig::Redhat } }, + :opensuse => { + :default => { + :service => Chef::Provider::Service::Redhat, + :cron => Chef::Provider::Cron, + :package => Chef::Provider::Package::Zypper, + :group => Chef::Provider::Group::Suse + }, + ">= 12.3" => { + :group => Chef::Provider::Group::Usermod + } + }, :suse => { :default => { :service => Chef::Provider::Service::Redhat, @@ -180,6 +191,16 @@ class Chef :package => Chef::Provider::Package::Zypper, :group => Chef::Provider::Group::Suse }, + ############################################### + # TODO: Remove this after ohai update is released. + # Only OpenSuSE 12.3+ should use the Usermod group provider: + # Ohai before OHAI-339 is applied reports both OpenSuSE and SuSE + # Enterprise as "suse", Ohai after OHAI-339 will report OpenSuSE as + # "opensuse". + # + # In order to support OpenSuSE both before and after the Ohai + # change, I'm leaving this here. It needs to get removed before + # SuSE enterprise 12.3 ships. ">= 12.3" => { :group => Chef::Provider::Group::Usermod } @@ -320,7 +341,11 @@ class Chef }, :aix => { :default => { - :group => Chef::Provider::Group::Aix + :group => Chef::Provider::Group::Aix, + :mount => Chef::Provider::Mount::Aix, + :ifconfig => Chef::Provider::Ifconfig::Aix, + :cron => Chef::Provider::Cron::Aix, + :package => Chef::Provider::Package::Aix } }, :default => { diff --git a/lib/chef/provider/batch.rb b/lib/chef/provider/batch.rb index e4b35b64f3..354a640e59 100644 --- a/lib/chef/provider/batch.rb +++ b/lib/chef/provider/batch.rb @@ -6,9 +6,9 @@ # 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. @@ -29,7 +29,7 @@ class Chef def flags @new_resource.flags.nil? ? '/c' : new_resource.flags + ' /c' end - + end end end diff --git a/lib/chef/provider/cron.rb b/lib/chef/provider/cron.rb index a7218fea5a..f6f062a410 100644 --- a/lib/chef/provider/cron.rb +++ b/lib/chef/provider/cron.rb @@ -40,11 +40,12 @@ class Chef def whyrun_supported? true end - + def load_current_resource crontab_lines = [] @current_resource = Chef::Resource::Cron.new(@new_resource.name) @current_resource.user(@new_resource.user) + @cron_exists = false if crontab = read_crontab cron_found = false crontab.each_line do |line| @@ -81,7 +82,7 @@ class Chef @current_resource end - + def cron_different? CRON_ATTRIBUTES.any? do |cron_var| !@new_resource.send(cron_var).nil? && @new_resource.send(cron_var) != @current_resource.send(cron_var) @@ -93,14 +94,7 @@ class Chef newcron = String.new cron_found = false - newcron << "# Chef Name: #{new_resource.name}\n" - [ :mailto, :path, :shell, :home ].each do |v| - newcron << "#{v.to_s.upcase}=#{@new_resource.send(v)}\n" if @new_resource.send(v) - end - @new_resource.environment.each do |name, value| - newcron << "#{name}=#{value}\n" - end - newcron << "#{@new_resource.minute} #{@new_resource.hour} #{@new_resource.day} #{@new_resource.month} #{@new_resource.weekday} #{@new_resource.command}\n" + newcron = get_crontab_entry if @cron_exists unless cron_different? @@ -171,7 +165,7 @@ class Chef end crontab << line end - description = cron_found ? "remove #{@new_resource.name} from crontab" : + description = cron_found ? "remove #{@new_resource.name} from crontab" : "save unmodified crontab" converge_by(description) do write_crontab crontab @@ -202,13 +196,33 @@ class Chef end def write_crontab(crontab) + write_exception = false status = popen4("crontab -u #{@new_resource.user} -", :waitlast => true) do |pid, stdin, stdout, stderr| - stdin.write crontab + begin + stdin.write crontab + rescue Errno::EPIPE => e + # popen4 could yield while child has already died. + write_exception = true + Chef::Log.debug("#{e.message}") + end end - if status.exitstatus > 0 + if status.exitstatus > 0 || write_exception raise Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: #{status.exitstatus}" end end + + def get_crontab_entry + newcron = "" + newcron << "# Chef Name: #{new_resource.name}\n" + [ :mailto, :path, :shell, :home ].each do |v| + newcron << "#{v.to_s.upcase}=#{@new_resource.send(v)}\n" if @new_resource.send(v) + end + @new_resource.environment.each do |name, value| + newcron << "#{name}=#{value}\n" + end + newcron << "#{@new_resource.minute} #{@new_resource.hour} #{@new_resource.day} #{@new_resource.month} #{@new_resource.weekday} #{@new_resource.command}\n" + newcron + end end end end diff --git a/lib/chef/provider/cron/aix.rb b/lib/chef/provider/cron/aix.rb new file mode 100644 index 0000000000..473700bf2f --- /dev/null +++ b/lib/chef/provider/cron/aix.rb @@ -0,0 +1,48 @@ +# +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.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/cron/unix" + +class Chef + class Provider + class Cron + class Aix < Chef::Provider::Cron::Unix + + private + + # For AIX we ignore env vars/[ :mailto, :path, :shell, :home ] + def get_crontab_entry + if env_vars_are_set? + raise Chef::Exceptions::Cron, "Aix cron entry does not support environment variables. Please set them in script and use script in cron." + end + + newcron = "" + newcron << "# Chef Name: #{new_resource.name}\n" + newcron << "#{@new_resource.minute} #{@new_resource.hour} #{@new_resource.day} #{@new_resource.month} #{@new_resource.weekday}" + + newcron << " #{@new_resource.command}\n" + newcron + end + + def env_vars_are_set? + @new_resource.environment.length > 0 || !@new_resource.mailto.nil? || !@new_resource.path.nil? || !@new_resource.shell.nil? || !@new_resource.home.nil? + end + end + end + end +end diff --git a/lib/chef/provider/cron/solaris.rb b/lib/chef/provider/cron/solaris.rb index e0811ba0ac..20fa7abcce 100644 --- a/lib/chef/provider/cron/solaris.rb +++ b/lib/chef/provider/cron/solaris.rb @@ -1,15 +1,13 @@ # -# Author:: Bryan McLellan (btm@loftninjas.org) -# Author:: Toomas Pelberg (toomasp@gmx.net) -# Copyright:: Copyright (c) 2009 Bryan McLellan -# Copyright:: Copyright (c) 2010 Toomas Pelberg +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.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 +# 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, @@ -18,39 +16,7 @@ # limitations under the License. # -require 'chef/log' -require 'chef/provider' +require "chef/provider/cron/unix" -class Chef - class Provider - class Cron - class Solaris < Chef::Provider::Cron - - private - - def read_crontab - crontab = nil - status = popen4("crontab -l #{@new_resource.user}") do |pid, stdin, stdout, stderr| - crontab = stdout.read - end - if status.exitstatus > 1 - raise Chef::Exceptions::Cron, "Error determining state of #{@new_resource.name}, exit: #{status.exitstatus}" - end - crontab - end - - def write_crontab(crontab) - tempcron = Tempfile.new("chef-cron") - tempcron << crontab - tempcron.flush - tempcron.chmod(0644) - status = run_command(:command => "/usr/bin/crontab #{tempcron.path}",:user => @new_resource.user) - tempcron.close! - if status.exitstatus > 0 - raise Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: #{status.exitstatus}" - end - end - end - end - end -end +# Just to create an alias so 'Chef::Provider::Cron::Solaris' is exposed and accessible to existing consumers of class. +Chef::Provider::Cron::Solaris = Chef::Provider::Cron::Unix diff --git a/lib/chef/provider/cron/unix.rb b/lib/chef/provider/cron/unix.rb new file mode 100644 index 0000000000..5cb1bcda41 --- /dev/null +++ b/lib/chef/provider/cron/unix.rb @@ -0,0 +1,76 @@ +# +# Author:: Bryan McLellan (btm@loftninjas.org) +# Author:: Toomas Pelberg (toomasp@gmx.net) +# Copyright:: Copyright (c) 2009 Bryan McLellan +# Copyright:: Copyright (c) 2010 Toomas Pelberg +# 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/log' +require 'chef/provider' + +class Chef + class Provider + class Cron + class Unix < Chef::Provider::Cron + + private + + def read_crontab + crontab = nil + status = popen4("crontab -l #{@new_resource.user}") do |pid, stdin, stdout, stderr| + crontab = stdout.read + end + if status.exitstatus > 1 + raise Chef::Exceptions::Cron, "Error determining state of #{@new_resource.name}, exit: #{status.exitstatus}" + end + crontab + end + + def write_crontab(crontab) + tempcron = Tempfile.new("chef-cron") + tempcron << crontab + tempcron.flush + tempcron.chmod(0644) + exit_status = 0 + error_message = "" + begin + status, stdout, stderr = run_command_and_return_stdout_stderr(:command => "/usr/bin/crontab #{tempcron.path}",:user => @new_resource.user) + exit_status = status.exitstatus + # solaris9, 10 on some failures for example invalid 'mins' in crontab fails with exit code of zero :( + if stderr && stderr.include?("errors detected in input, no crontab file generated") + error_message = stderr + exit_status = 1 + end + rescue Chef::Exceptions::Exec => e + Chef::Log.debug(e.message) + exit_status = 1 + error_message = e.message + rescue ArgumentError => e + # usually raised on invalid user. + Chef::Log.debug(e.message) + exit_status = 1 + error_message = e.message + end + tempcron.close! + if exit_status > 0 + raise Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: #{exit_status}, message: #{error_message}" + end + end + + end + end + end +end diff --git a/lib/chef/provider/deploy/timestamped.rb b/lib/chef/provider/deploy/timestamped.rb index 9c2d55b490..ce921161e0 100644 --- a/lib/chef/provider/deploy/timestamped.rb +++ b/lib/chef/provider/deploy/timestamped.rb @@ -6,9 +6,9 @@ # 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. @@ -20,9 +20,9 @@ class Chef class Provider class Deploy class Timestamped < Chef::Provider::Deploy - + protected - + def release_slug Time.now.utc.strftime("%Y%m%d%H%M%S") end diff --git a/lib/chef/provider/erl_call.rb b/lib/chef/provider/erl_call.rb index 1ee1da500c..cdd494a243 100644 --- a/lib/chef/provider/erl_call.rb +++ b/lib/chef/provider/erl_call.rb @@ -32,7 +32,7 @@ class Chef def whyrun_supported? true end - + def load_current_resource true end diff --git a/lib/chef/provider/execute.rb b/lib/chef/provider/execute.rb index 8d2a7d997d..2907688e88 100644 --- a/lib/chef/provider/execute.rb +++ b/lib/chef/provider/execute.rb @@ -29,7 +29,7 @@ class Chef def load_current_resource true end - + def whyrun_supported? true end @@ -56,7 +56,7 @@ class Chef if STDOUT.tty? && !Chef::Config[:daemon] && Chef::Log.info? opts[:live_stream] = STDOUT end - converge_by("execute #{@new_resource.command}") do + converge_by("execute #{@new_resource.command}") do result = shell_out!(@new_resource.command, opts) Chef::Log.info("#{@new_resource} ran successfully") end diff --git a/lib/chef/provider/git.rb b/lib/chef/provider/git.rb index 7cda1a873a..b22004eda0 100644 --- a/lib/chef/provider/git.rb +++ b/lib/chef/provider/git.rb @@ -273,6 +273,7 @@ class Chef run_opts[:group] = @new_resource.group if @new_resource.group run_opts[:environment] = {"GIT_SSH" => @new_resource.ssh_wrapper} if @new_resource.ssh_wrapper run_opts[:log_tag] = @new_resource.to_s + run_opts[:timeout] = @new_resource.timeout if @new_resource.timeout run_opts end diff --git a/lib/chef/provider/group.rb b/lib/chef/provider/group.rb index c941ed72bd..eacb033492 100644 --- a/lib/chef/provider/group.rb +++ b/lib/chef/provider/group.rb @@ -6,9 +6,9 @@ # 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. @@ -35,11 +35,11 @@ class Chef super @group_exists = true end - + def load_current_resource @current_resource = Chef::Resource::Group.new(@new_resource.name) @current_resource.group_name(@new_resource.group_name) - + group_info = nil begin group_info = Etc.getgrnam(@new_resource.group_name) @@ -47,26 +47,26 @@ class Chef @group_exists = false Chef::Log.debug("#{@new_resource} group does not exist") end - + if group_info @new_resource.gid(group_info.gid) unless @new_resource.gid @current_resource.gid(group_info.gid) @current_resource.members(group_info.mem) end - + @current_resource end def define_resource_requirements - requirements.assert(:modify) do |a| - a.assertion { @group_exists } + requirements.assert(:modify) do |a| + a.assertion { @group_exists } a.failure_message(Chef::Exceptions::Group, "Cannot modify #{@new_resource} - group does not exist!") a.whyrun("Group #{@new_resource} does not exist. Unless it would have been created earlier in this run, this attempt to modify it would fail.") end end - - # Check to see if a group needs any changes. Populate - # @change_desc with a description of why a change must occur + + # Check to see if a group needs any changes. Populate + # @change_desc with a description of why a change must occur # # ==== Returns # <true>:: If a change is required @@ -77,7 +77,7 @@ class Chef @change_desc = "change gid #{@current_resource.gid} to #{@new_resource.gid}" return true end - + if(@new_resource.append) missing_members = [] @new_resource.members.each do |member| @@ -96,24 +96,24 @@ class Chef end return false end - + def action_create case @group_exists when false - converge_by("create #{@new_resource}") do + converge_by("create #{@new_resource}") do create_group Chef::Log.info("#{@new_resource} created") end - else + else if compare_group - converge_by(["alter group #{@new_resource}", @change_desc ]) do + converge_by(["alter group #{@new_resource}", @change_desc ]) do manage_group Chef::Log.info("#{@new_resource} altered") end end end end - + def action_remove if @group_exists converge_by("remove group #{@new_resource}") do @@ -122,16 +122,16 @@ class Chef end end end - + def action_manage if @group_exists && compare_group converge_by(["manage group #{@new_resource}", @change_desc]) do - manage_group + manage_group Chef::Log.info("#{@new_resource} managed") end end end - + def action_modify if compare_group converge_by(["modify group #{@new_resource}", @change_desc]) do @@ -140,7 +140,7 @@ class Chef end end end - + def create_group raise NotImplementedError, "subclasses of Chef::Provider::Group should define #create_group" end diff --git a/lib/chef/provider/group/dscl.rb b/lib/chef/provider/group/dscl.rb index a8ba32641c..d0b2a4d499 100644 --- a/lib/chef/provider/group/dscl.rb +++ b/lib/chef/provider/group/dscl.rb @@ -6,9 +6,9 @@ # 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. @@ -38,7 +38,7 @@ class Chef raise(Chef::Exceptions::Group,"dscl error: #{result.inspect}") if result[2] =~ /No such key: / return result[2] end - + # This is handled in providers/group.rb by Etc.getgrnam() # def group_exists?(group) # groups = safe_dscl("list /Groups") @@ -86,8 +86,8 @@ class Chef def define_resource_requirements super - requirements.assert(:all_actions) do |a| - a.assertion { ::File.exists?("/usr/bin/dscl") } + requirements.assert(:all_actions) do |a| + a.assertion { ::File.exists?("/usr/bin/dscl") } a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/bin/dscl for #{@new_resource.name}" # No whyrun alternative: this component should be available in the base install of any given system that uses it end @@ -96,13 +96,13 @@ class Chef def load_current_resource super end - + def create_group dscl_create_group set_gid set_members end - + def manage_group if @new_resource.group_name && (@current_resource.group_name != @new_resource.group_name) dscl_create_group @@ -114,12 +114,12 @@ class Chef set_members end end - + def dscl_create_group safe_dscl("create /Groups/#{@new_resource.group_name}") safe_dscl("create /Groups/#{@new_resource.group_name} Password '*'") end - + def remove_group safe_dscl("delete /Groups/#{@new_resource.group_name}") end diff --git a/lib/chef/provider/group/gpasswd.rb b/lib/chef/provider/group/gpasswd.rb index 7fb27a7777..2638b82383 100644 --- a/lib/chef/provider/group/gpasswd.rb +++ b/lib/chef/provider/group/gpasswd.rb @@ -6,9 +6,9 @@ # 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. @@ -32,9 +32,9 @@ class Chef def define_resource_requirements super - requirements.assert(:all_actions) do |a| - a.assertion { ::File.exists?("/usr/bin/gpasswd") } - a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/bin/gpasswd for #{@new_resource}" + requirements.assert(:all_actions) do |a| + a.assertion { ::File.exists?("/usr/bin/gpasswd") } + a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/bin/gpasswd for #{@new_resource}" # No whyrun alternative: this component should be available in the base install of any given system that uses it end end diff --git a/lib/chef/provider/group/groupadd.rb b/lib/chef/provider/group/groupadd.rb index 544fee4304..45ae308612 100644 --- a/lib/chef/provider/group/groupadd.rb +++ b/lib/chef/provider/group/groupadd.rb @@ -6,9 +6,9 @@ # 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. @@ -20,7 +20,7 @@ class Chef class Provider class Group class Groupadd < Chef::Provider::Group - + def required_binaries [ "/usr/sbin/groupadd", "/usr/sbin/groupmod", @@ -34,9 +34,9 @@ class Chef def define_resource_requirements super required_binaries.each do |required_binary| - requirements.assert(:all_actions) do |a| - a.assertion { ::File.exists?(required_binary) } - a.failure_message Chef::Exceptions::Group, "Could not find binary #{required_binary} for #{@new_resource}" + requirements.assert(:all_actions) do |a| + a.assertion { ::File.exists?(required_binary) } + a.failure_message Chef::Exceptions::Group, "Could not find binary #{required_binary} for #{@new_resource}" # No whyrun alternative: this component should be available in the base install of any given system that uses it end end @@ -48,9 +48,9 @@ class Chef command << set_options command << groupadd_options run_command(:command => command) - modify_group_members + modify_group_members end - + # Manage the group when it already exists def manage_group command = "groupmod" @@ -58,12 +58,12 @@ class Chef run_command(:command => command) modify_group_members end - + # Remove the group def remove_group run_command(:command => "groupdel #{@new_resource.group_name}") end - + def modify_group_members raise Chef::Exceptions::Group, "you must override modify_group_members in #{self.to_s}" end @@ -87,6 +87,7 @@ class Chef def groupadd_options opts = '' opts << " -r" if @new_resource.system + opts << " -o" if @new_resource.non_unique opts end diff --git a/lib/chef/provider/group/pw.rb b/lib/chef/provider/group/pw.rb index 3bf67a515a..66da8281be 100644 --- a/lib/chef/provider/group/pw.rb +++ b/lib/chef/provider/group/pw.rb @@ -6,9 +6,9 @@ # 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. @@ -20,21 +20,21 @@ class Chef class Provider class Group class Pw < Chef::Provider::Group - + def load_current_resource super end - + def define_resource_requirements super - requirements.assert(:all_actions) do |a| - a.assertion { ::File.exists?("/usr/sbin/pw") } + requirements.assert(:all_actions) do |a| + a.assertion { ::File.exists?("/usr/sbin/pw") } a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/pw for #{@new_resource}" # No whyrun alternative: this component should be available in the base install of any given system that uses it end end - + # Create the group def create_group command = "pw groupadd" @@ -42,7 +42,7 @@ class Chef command << set_members_option run_command(:command => command) end - + # Manage the group when it already exists def manage_group command = "pw groupmod" @@ -50,12 +50,12 @@ class Chef command << set_members_option run_command(:command => command) end - + # Remove the group def remove_group run_command(:command => "pw groupdel #{@new_resource.group_name}") end - + # Little bit of magic as per Adam's useradd provider to pull and assign the command line flags # # ==== Returns @@ -86,7 +86,7 @@ class Chef end opt end - + end end end diff --git a/lib/chef/provider/group/suse.rb b/lib/chef/provider/group/suse.rb index 0b66c1f912..4c343bddf9 100644 --- a/lib/chef/provider/group/suse.rb +++ b/lib/chef/provider/group/suse.rb @@ -6,9 +6,9 @@ # 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. @@ -32,8 +32,8 @@ class Chef def define_resource_requirements super - requirements.assert(:all_actions) do |a| - a.assertion { ::File.exists?("/usr/sbin/groupmod") } + requirements.assert(:all_actions) do |a| + a.assertion { ::File.exists?("/usr/sbin/groupmod") } a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/groupmod for #{@new_resource.name}" # No whyrun alternative: this component should be available in the base install of any given system that uses it end diff --git a/lib/chef/provider/group/usermod.rb b/lib/chef/provider/group/usermod.rb index 0d44d3940f..5788ac8fad 100644 --- a/lib/chef/provider/group/usermod.rb +++ b/lib/chef/provider/group/usermod.rb @@ -6,9 +6,9 @@ # 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. @@ -22,7 +22,7 @@ class Chef class Provider class Group class Usermod < Chef::Provider::Group::Groupadd - + def load_current_resource super end @@ -30,24 +30,24 @@ class Chef def define_resource_requirements super - requirements.assert(:all_actions) do |a| - a.assertion { ::File.exists?("/usr/sbin/usermod") } + requirements.assert(:all_actions) do |a| + a.assertion { ::File.exists?("/usr/sbin/usermod") } a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/usermod for #{@new_resource}" # No whyrun alternative: this component should be available in the base install of any given system that uses it end requirements.assert(:modify, :create) do |a| - a.assertion { @new_resource.members.empty? || @new_resource.append } + a.assertion { @new_resource.members.empty? || @new_resource.append } a.failure_message Chef::Exceptions::Group, "setting group members directly is not supported by #{self.to_s}, must set append true in group" # No whyrun alternative - this action is simply not supported. end end - + def modify_group_members case node[:platform] when "openbsd", "netbsd", "aix", "solaris2", "smartos" append_flags = "-G" - when "solaris", "suse" + when "solaris", "suse", "opensuse" append_flags = "-a -G" end diff --git a/lib/chef/provider/group/windows.rb b/lib/chef/provider/group/windows.rb index 88280408cd..da12366329 100644 --- a/lib/chef/provider/group/windows.rb +++ b/lib/chef/provider/group/windows.rb @@ -6,9 +6,9 @@ # 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. @@ -25,16 +25,16 @@ class Chef class Provider class Group class Windows < Chef::Provider::Group - + def initialize(new_resource,run_context) super - @net_group = Chef::Util::Windows::NetGroup.new(@new_resource.name) + @net_group = Chef::Util::Windows::NetGroup.new(@new_resource.group_name) end def load_current_resource @current_resource = Chef::Resource::Group.new(@new_resource.name) @current_resource.group_name(@new_resource.group_name) - + members = nil begin members = @net_group.local_get_members @@ -49,12 +49,12 @@ class Chef @current_resource end - + def create_group @net_group.local_add manage_group end - + def manage_group if @new_resource.append begin @@ -68,11 +68,11 @@ class Chef @net_group.local_set_members(@new_resource.members) end end - + def remove_group @net_group.local_delete end - + end end end diff --git a/lib/chef/provider/http_request.rb b/lib/chef/provider/http_request.rb index a5bc3b5e04..1e0aa8b4a0 100644 --- a/lib/chef/provider/http_request.rb +++ b/lib/chef/provider/http_request.rb @@ -17,26 +17,27 @@ # require 'tempfile' +require 'chef/http/simple' class Chef class Provider class HttpRequest < Chef::Provider - attr_accessor :rest + attr_accessor :http def whyrun_supported? true end def load_current_resource - @rest = Chef::REST.new(@new_resource.url, nil, nil) + @http = Chef::HTTP::Simple.new(@new_resource.url) end # Send a HEAD request to @new_resource.url, with ?message=@new_resource.message def action_head message = check_message(@new_resource.message) # returns true from Chef::REST if returns 2XX (Net::HTTPSuccess) - modified = @rest.head( + modified = @http.head( "#{@new_resource.url}?message=#{message}", @new_resource.headers ) @@ -53,9 +54,8 @@ class Chef converge_by("#{@new_resource} GET to #{@new_resource.url}") do message = check_message(@new_resource.message) - body = @rest.get( + body = @http.get( "#{@new_resource.url}?message=#{message}", - false, @new_resource.headers ) Chef::Log.info("#{@new_resource} GET to #{@new_resource.url} successful") @@ -67,7 +67,7 @@ class Chef def action_put converge_by("#{@new_resource} PUT to #{@new_resource.url}") do message = check_message(@new_resource.message) - body = @rest.put( + body = @http.put( "#{@new_resource.url}", message, @new_resource.headers @@ -81,7 +81,7 @@ class Chef def action_post converge_by("#{@new_resource} POST to #{@new_resource.url}") do message = check_message(@new_resource.message) - body = @rest.post( + body = @http.post( "#{@new_resource.url}", message, @new_resource.headers @@ -94,7 +94,7 @@ class Chef # Send a DELETE request to @new_resource.url def action_delete converge_by("#{@new_resource} DELETE to #{@new_resource.url}") do - body = @rest.delete( + body = @http.delete( "#{@new_resource.url}", @new_resource.headers ) diff --git a/lib/chef/provider/ifconfig.rb b/lib/chef/provider/ifconfig.rb index 0aacc9e616..31f88e5406 100644 --- a/lib/chef/provider/ifconfig.rb +++ b/lib/chef/provider/ifconfig.rb @@ -26,11 +26,11 @@ require 'erb' # # int = {Hash with your network settings...} # -# ifconfig int['ip'] do -# ignore_failure true -# device int['dev'] -# mask int['mask'] -# gateway int['gateway'] +# ifconfig int['ip'] do +# ignore_failure true +# device int['dev'] +# mask int['mask'] +# gateway int['gateway'] # mtu int['mtu'] # end @@ -76,7 +76,7 @@ class Chef @interface = @interfaces.fetch(@new_resource.device) @current_resource.target(@new_resource.target) - @current_resource.device(@int_name) + @current_resource.device(@new_resource.device) @current_resource.inet_addr(@interface["inet_addr"]) @current_resource.hwaddr(@interface["hwaddr"]) @current_resource.bcast(@interface["bcast"]) @@ -89,12 +89,12 @@ class Chef @current_resource end - def define_resource_requirements - requirements.assert(:all_actions) do |a| + def define_resource_requirements + requirements.assert(:all_actions) do |a| a.assertion { @status.exitstatus == 0 } a.failure_message Chef::Exceptions::Ifconfig, "ifconfig failed - #{@status.inspect}!" # no whyrun - if the base ifconfig used in load_current_resource fails - # there's no reasonable action that could have been taken in the course of + # there's no reasonable action that could have been taken in the course of # a chef run to fix it. end end @@ -102,40 +102,32 @@ class Chef def action_add # check to see if load_current_resource found interface in ifconfig unless @current_resource.inet_addr - unless @new_resource.device == "lo" - command = "ifconfig #{@new_resource.device} #{@new_resource.name}" - command << " netmask #{@new_resource.mask}" if @new_resource.mask - command << " metric #{@new_resource.metric}" if @new_resource.metric - command << " mtu #{@new_resource.mtu}" if @new_resource.mtu - end - converge_by ("run #{command} to add #{@new_resource}") do - run_command( - :command => command - ) - Chef::Log.info("#{@new_resource} added") + unless @new_resource.device == loopback_device + command = add_command + converge_by ("run #{command} to add #{@new_resource}") do + run_command( + :command => command + ) + Chef::Log.info("#{@new_resource} added") + # Write out the config files + generate_config + end end end - - # Write out the config files - generate_config end def action_enable # check to see if load_current_resource found ifconfig # enables, but does not manage config files unless @current_resource.inet_addr - unless @new_resource.device == "lo" - command = "ifconfig #{@new_resource.device} #{@new_resource.name}" - command << " netmask #{@new_resource.mask}" if @new_resource.mask - command << " metric #{@new_resource.metric}" if @new_resource.metric - command << " mtu #{@new_resource.mtu}" if @new_resource.mtu - end - - converge_by ("run #{command} to enable #{@new_resource}") do - run_command( - :command => command - ) - Chef::Log.info("#{@new_resource} enabled") + unless @new_resource.device == loopback_device + command = enable_command + converge_by ("run #{command} to enable #{@new_resource}") do + run_command( + :command => command + ) + Chef::Log.info("#{@new_resource} enabled") + end end end end @@ -143,7 +135,7 @@ class Chef def action_delete # check to see if load_current_resource found the interface if @current_resource.device - command = "ifconfig #{@new_resource.device} down" + command = delete_command converge_by ("run #{command} to delete #{@new_resource}") do run_command( :command => command @@ -160,7 +152,7 @@ class Chef # check to see if load_current_resource found the interface # disables, but leaves config files in place. if @current_resource.device - command = "ifconfig #{@new_resource.device} down" + command = disable_command converge_by ("run #{command} to disable #{@new_resource}") do run_command( :command => command @@ -199,6 +191,34 @@ class Chef Chef::Log.info("#{@new_resource} deleted configuration file") end + private + def add_command + command = "ifconfig #{@new_resource.device} #{@new_resource.name}" + command << " netmask #{@new_resource.mask}" if @new_resource.mask + command << " metric #{@new_resource.metric}" if @new_resource.metric + command << " mtu #{@new_resource.mtu}" if @new_resource.mtu + command + end + + def enable_command + command = "ifconfig #{@new_resource.device} #{@new_resource.name}" + command << " netmask #{@new_resource.mask}" if @new_resource.mask + command << " metric #{@new_resource.metric}" if @new_resource.metric + command << " mtu #{@new_resource.mtu}" if @new_resource.mtu + command + end + + def disable_command + "ifconfig #{@new_resource.device} down" + end + + def delete_command + "ifconfig #{@new_resource.device} down" + end + + def loopback_device + 'lo' + end end end end diff --git a/lib/chef/provider/ifconfig/aix.rb b/lib/chef/provider/ifconfig/aix.rb new file mode 100644 index 0000000000..460b1ba7f2 --- /dev/null +++ b/lib/chef/provider/ifconfig/aix.rb @@ -0,0 +1,99 @@ +# +# Author:: Kaustubh Deorukhkar (kaustubh@clogeny.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/ifconfig' + +class Chef + class Provider + class Ifconfig + class Aix < Chef::Provider::Ifconfig + + def load_current_resource + @current_resource = Chef::Resource::Ifconfig.new(@new_resource.name) + + @interface_exists = false + found_interface = false + interface = {} + + @status = popen4("ifconfig -a") do |pid, stdin, stdout, stderr| + stdout.each do |line| + + if !found_interface + if line =~ /^(\S+):\sflags=(\S+)/ + # We have interface name, if this is the interface for @current_resource, load info else skip till next interface is found. + if $1 == @new_resource.device + # Found interface + found_interface = true + @interface_exists = true + @current_resource.target(@new_resource.target) + @current_resource.device($1) + interface[:flags] = $2 + @current_resource.metric($1) if line =~ /metric\s(\S+)/ + end + end + else + # parse interface related information, stop when next interface is found. + if line =~ /^(\S+):\sflags=(\S+)/ + # we are done parsing interface info and hit another one, so stop. + found_interface = false + break + else + if found_interface + # read up interface info + @current_resource.inet_addr($1) if line =~ /inet\s(\S+)\s/ + @current_resource.bcast($1) if line =~ /broadcast\s(\S+)/ + @current_resource.mask(hex_to_dec_netmask($1)) if line =~ /netmask\s(\S+)\s/ + end + end + end + end + end + + @current_resource + end + + private + def add_command + # ifconfig changes are temporary, chdev persist across reboots. + raise Chef::Exceptions::Ifconfig, "interface metric attribute cannot be set for :add action" if @new_resource.metric + command = "chdev -l #{@new_resource.device} -a netaddr=#{@new_resource.name}" + command << " -a netmask=#{@new_resource.mask}" if @new_resource.mask + command << " -a mtu=#{@new_resource.mtu}" if @new_resource.mtu + command + end + + def delete_command + # ifconfig changes are temporary, chdev persist across reboots. + "chdev -l #{@new_resource.device} -a state=down" + end + + def loopback_device + "lo0" + end + + def hex_to_dec_netmask(netmask) + # example '0xffff0000' -> '255.255.0.0' + dec = netmask[2..3].to_i(16).to_s(10) + [4,6,8].each { |n| dec = dec + "." + netmask[n..n+1].to_i(16).to_s(10) } + dec + end + + end + end + end +end diff --git a/lib/chef/provider/log.rb b/lib/chef/provider/log.rb index 927ee72fcc..1c970cc888 100644 --- a/lib/chef/provider/log.rb +++ b/lib/chef/provider/log.rb @@ -6,9 +6,9 @@ # 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. @@ -32,7 +32,7 @@ class Chef def load_current_resource true end - + # Write the log to Chef's log # # === Return diff --git a/lib/chef/provider/mdadm.rb b/lib/chef/provider/mdadm.rb index d93ff69c13..51c9b8d3c6 100644 --- a/lib/chef/provider/mdadm.rb +++ b/lib/chef/provider/mdadm.rb @@ -47,8 +47,9 @@ class Chef def action_create unless @current_resource.exists - converge_by("create RAID device #{new_resource.raid_device}") do - command = "yes | mdadm --create #{@new_resource.raid_device} --chunk=#{@new_resource.chunk} --level #{@new_resource.level}" + converge_by("create RAID device #{new_resource.raid_device}") do + command = "yes | mdadm --create #{@new_resource.raid_device} --level #{@new_resource.level}" + command << " --chunk=#{@new_resource.chunk}" unless @new_resource.level == 1 command << " --metadata=#{@new_resource.metadata}" command << " --bitmap=#{@new_resource.bitmap}" if @new_resource.bitmap command << " --raid-devices #{@new_resource.devices.length} #{@new_resource.devices.join(" ")}" @@ -63,7 +64,7 @@ class Chef def action_assemble unless @current_resource.exists - converge_by("assemble RAID device #{new_resource.raid_device}") do + converge_by("assemble RAID device #{new_resource.raid_device}") do command = "yes | mdadm --assemble #{@new_resource.raid_device} #{@new_resource.devices.join(" ")}" Chef::Log.debug("#{@new_resource} mdadm command: #{command}") shell_out!(command) @@ -76,7 +77,7 @@ class Chef def action_stop if @current_resource.exists - converge_by("stop RAID device #{new_resource.raid_device}") do + converge_by("stop RAID device #{new_resource.raid_device}") do command = "yes | mdadm --stop #{@new_resource.raid_device}" Chef::Log.debug("#{@new_resource} mdadm command: #{command}") shell_out!(command) diff --git a/lib/chef/provider/mount.rb b/lib/chef/provider/mount.rb index 6b9dd91ac8..5f58baa396 100644 --- a/lib/chef/provider/mount.rb +++ b/lib/chef/provider/mount.rb @@ -6,9 +6,9 @@ # 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. @@ -37,7 +37,7 @@ class Chef def action_mount unless @current_resource.mounted - converge_by("mount #{@current_resource.device} to #{@current_resource.mount_point}") do + converge_by("mount #{@current_resource.device} to #{@current_resource.mount_point}") do status = mount_fs() if status Chef::Log.info("#{@new_resource} mounted") @@ -50,7 +50,7 @@ class Chef def action_umount if @current_resource.mounted - converge_by("unmount #{@current_resource.device}") do + converge_by("unmount #{@current_resource.device}") do status = umount_fs() if status Chef::Log.info("#{@new_resource} unmounted") @@ -66,7 +66,7 @@ class Chef raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :remount" else if @current_resource.mounted - converge_by("remount #{@current_resource.device}") do + converge_by("remount #{@current_resource.device}") do status = remount_fs() if status Chef::Log.info("#{@new_resource} remounted") @@ -80,7 +80,7 @@ class Chef def action_enable unless @current_resource.enabled && mount_options_unchanged? - converge_by("remount #{@current_resource.device}") do + converge_by("remount #{@current_resource.device}") do status = enable_fs if status Chef::Log.info("#{@new_resource} enabled") @@ -93,7 +93,7 @@ class Chef def action_disable if @current_resource.enabled - converge_by("remount #{@current_resource.device}") do + converge_by("remount #{@current_resource.device}") do status = disable_fs if status Chef::Log.info("#{@new_resource} disabled") @@ -115,14 +115,14 @@ class Chef def remount_fs raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :remount" end - + def enable_fs - raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :enable" + raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :enable" end - + def disable_fs - raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :disable" - end + raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :disable" + end end end end diff --git a/lib/chef/provider/mount/aix.rb b/lib/chef/provider/mount/aix.rb new file mode 100644 index 0000000000..0d7e11a1b8 --- /dev/null +++ b/lib/chef/provider/mount/aix.rb @@ -0,0 +1,179 @@ +# +# Author:: +# 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/provider/mount' + +class Chef + class Provider + class Mount + class Aix < Chef::Provider::Mount::Mount + + # Override for aix specific handling + def initialize(new_resource, run_context) + super + # options and fstype are set to "defaults" and "auto" respectively in the Mount Resource class. These options are not valid for AIX, override them. + if @new_resource.options[0] == "defaults" + @new_resource.options.clear + end + if @new_resource.fstype == "auto" + @new_resource.fstype = nil + end + end + + def enabled? + # Check to see if there is an entry in /etc/filesystems. Last entry for a volume wins. Using command "lsfs" to fetch entries. + enabled = false + + # lsfs o/p = #MountPoint:Device:Vfs:Nodename:Type:Size:Options:AutoMount:Acct + # search only for current mount point + shell_out("lsfs -c #{@new_resource.mount_point}").stdout.each_line do | line | + case line + when /^#\s/ + next + when /^#{Regexp.escape(@new_resource.mount_point)}:#{device_fstab_regex}:(\S+):(\[\S+\])?:(\S+)?:(\S+):(\S+):(\S+):(\S+)/ + # mount point entry with ipv6 address for nodename (ipv6 address use ':') + enabled = true + @current_resource.fstype($1) + @current_resource.options($5) + Chef::Log.debug("Found mount #{device_fstab} to #{@new_resource.mount_point} in /etc/filesystems") + next + when /^#{Regexp.escape(@new_resource.mount_point)}:#{device_fstab_regex}::(\S+):(\S+)?:(\S+)?:(\S+):(\S+):(\S+):(\S+)/ + # mount point entry with hostname or ipv4 address + enabled = true + @current_resource.fstype($1) + @current_resource.options($5) + Chef::Log.debug("Found mount #{device_fstab} to #{@new_resource.mount_point} in /etc/filesystems") + next + when /^#{Regexp.escape(@new_resource.mount_point)}/ + enabled=false + Chef::Log.debug("Found conflicting mount point #{@new_resource.mount_point} in /etc/filesystems") + end + end + @current_resource.enabled(enabled) + end + + def mounted? + mounted = false + shell_out!("mount").stdout.each_line do |line| + if network_device? + device_details = device_fstab.split(":") + search_device = device_details[1] + else + search_device = device_fstab_regex + end + case line + when /#{search_device}\s+#{Regexp.escape(@new_resource.mount_point)}/ + mounted = true + Chef::Log.debug("Special device #{device_logstring} mounted as #{@new_resource.mount_point}") + when /^[\/\w]+\s+#{Regexp.escape(@new_resource.mount_point)}\s+/ + mounted = false + Chef::Log.debug("Found conflicting mount point #{@new_resource.mount_point} in /etc/fstab") + end + end + @current_resource.mounted(mounted) + end + + def mount_fs + unless @current_resource.mounted + mountable? + command = "mount -v #{@new_resource.fstype}" + + if !(@new_resource.options.nil? || @new_resource.options.empty?) + command << " -o #{@new_resource.options.join(',')}" + end + + command << case @new_resource.device_type + when :device + " #{device_real}" + when :label + " -L #{@new_resource.device}" + when :uuid + " -U #{@new_resource.device}" + end + command << " #{@new_resource.mount_point}" + shell_out!(command) + Chef::Log.debug("#{@new_resource} is mounted at #{@new_resource.mount_point}") + else + Chef::Log.debug("#{@new_resource} is already mounted at #{@new_resource.mount_point}") + end + end + + def remount_command + if !(@new_resource.options.nil? || @new_resource.options.empty?) + return "mount -o remount,#{@new_resource.options.join(',')} #{@new_resource.device} #{@new_resource.mount_point}" + else + return "mount -o remount #{@new_resource.device} #{@new_resource.mount_point}" + end + end + + def enable_fs + if @current_resource.enabled && mount_options_unchanged? + Chef::Log.debug("#{@new_resource} is already enabled - nothing to do") + return nil + end + + if @current_resource.enabled + # The current options don't match what we have, so + # disable, then enable. + disable_fs + end + ::File.open("/etc/filesystems", "a") do |fstab| + fstab.puts("#{@new_resource.mount_point}:") + if network_device? + device_details = device_fstab.split(":") + fstab.puts("\tdev\t\t= #{device_details[1]}") + fstab.puts("\tnodename\t\t= #{device_details[0]}") + else + fstab.puts("\tdev\t\t= #{device_fstab}") + end + fstab.puts("\tvfs\t\t= #{@new_resource.fstype}") + fstab.puts("\tmount\t\t= false") + fstab.puts "\toptions\t\t= #{@new_resource.options.join(',')}" unless @new_resource.options.nil? || @new_resource.options.empty? + Chef::Log.debug("#{@new_resource} is enabled at #{@new_resource.mount_point}") + end + end + + def disable_fs + contents = [] + if @current_resource.enabled + found_device = false + ::File.open("/etc/filesystems", "r").each_line do |line| + case line + when /^\/.+:\s*$/ + if line =~ /#{Regexp.escape(@new_resource.mount_point)}+:/ + found_device = true + else + found_device = false + end + end + if !found_device + contents << line + end + end + ::File.open("/etc/filesystems", "w") do |fstab| + contents.each { |line| fstab.puts line} + end + else + Chef::Log.debug("#{@new_resource} is not enabled - nothing to do") + end + end + + end + end + end +end diff --git a/lib/chef/provider/mount/mount.rb b/lib/chef/provider/mount/mount.rb index ec54831017..25dfd42725 100644 --- a/lib/chef/provider/mount/mount.rb +++ b/lib/chef/provider/mount/mount.rb @@ -39,7 +39,7 @@ class Chef mounted? enabled? end - + def mountable? # only check for existence of non-remote devices if (device_should_exist? && !::File.exists?(device_real) ) @@ -49,7 +49,7 @@ class Chef end return true end - + def enabled? # Check to see if there is a entry in /etc/fstab. Last entry for a volume wins. enabled = false @@ -72,17 +72,27 @@ class Chef end @current_resource.enabled(enabled) end - + def mounted? mounted = false + + # "mount" outputs the mount points as real paths. Convert + # the mount_point of the resource to a real path in case it + # contains symlinks in its parents dirs. + real_mount_point = if ::File.exists? @new_resource.mount_point + ::File.realpath(@new_resource.mount_point) + else + @new_resource.mount_point + end + shell_out!("mount").stdout.each_line do |line| case line - when /^#{device_mount_regex}\s+on\s+#{Regexp.escape(@new_resource.mount_point)}/ + when /^#{device_mount_regex}\s+on\s+#{Regexp.escape(real_mount_point)}/ mounted = true - Chef::Log.debug("Special device #{device_logstring} mounted as #{@new_resource.mount_point}") - when /^([\/\w])+\son\s#{Regexp.escape(@new_resource.mount_point)}\s+/ + Chef::Log.debug("Special device #{device_logstring} mounted as #{real_mount_point}") + when /^([\/\w])+\son\s#{Regexp.escape(real_mount_point)}\s+/ mounted = false - Chef::Log.debug("Special device #{$~[1]} mounted as #{@new_resource.mount_point}") + Chef::Log.debug("Special device #{$~[1]} mounted as #{real_mount_point}") end end @current_resource.mounted(mounted) @@ -118,9 +128,13 @@ class Chef end end + def remount_command + return "mount -o remount #{@new_resource.mount_point}" + end + def remount_fs if @current_resource.mounted and @new_resource.supports[:remount] - shell_out!("mount -o remount #{@new_resource.mount_point}") + shell_out!(remount_command) @new_resource.updated_by_last_action(true) Chef::Log.debug("#{@new_resource} is remounted at #{@new_resource.mount_point}") elsif @current_resource.mounted @@ -137,7 +151,7 @@ class Chef Chef::Log.debug("#{@new_resource} is already enabled - nothing to do") return nil end - + if @current_resource.enabled # The current options don't match what we have, so # disable, then enable. @@ -152,7 +166,7 @@ class Chef def disable_fs if @current_resource.enabled contents = [] - + found = false ::File.readlines("/etc/fstab").reverse_each do |line| if !found && line =~ /^#{device_fstab_regex}\s+#{Regexp.escape(@new_resource.mount_point)}/ @@ -163,7 +177,7 @@ class Chef contents << line end end - + ::File.open("/etc/fstab", "w") do |fstab| contents.reverse_each { |line| fstab.puts line} end @@ -177,7 +191,7 @@ class Chef end def device_should_exist? - ( @new_resource.device != "none" ) && + ( @new_resource.device != "none" ) && ( not network_device? ) && ( not %w[ tmpfs fuse ].include? @new_resource.fstype ) end @@ -196,7 +210,7 @@ class Chef end def device_real - if @real_device == nil + if @real_device == nil if @new_resource.device_type == :device @real_device = @new_resource.device else @@ -243,14 +257,14 @@ class Chef device_fstab end end - + def mount_options_unchanged? @current_resource.fstype == @new_resource.fstype and @current_resource.options == @new_resource.options and @current_resource.dump == @new_resource.dump and @current_resource.pass == @new_resource.pass end - + end end end diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb index a28a6f93fb..c7692a9746 100644 --- a/lib/chef/provider/package.rb +++ b/lib/chef/provider/package.rb @@ -50,7 +50,7 @@ class Chef requirements.assert(:upgrade) do |a| # Can't upgrade what we don't have - a.assertion { !(@current_resource.version.nil? && candidate_version.nil?) } + a.assertion { !(@current_resource.version.nil? && candidate_version.nil?) } a.failure_message(Chef::Exceptions::Package, "No candidate version available for #{@new_resource.package_name}") a.whyrun("Assuming a repository that offers #{@new_resource.package_name} would have been configured") end @@ -71,9 +71,9 @@ class Chef # We need to make sure we handle the preseed file if @new_resource.response_file if preseed_file = get_preseed_file(@new_resource.package_name, install_version) - converge_by("preseed package #{@new_resource.package_name}") do + converge_by("preseed package #{@new_resource.package_name}") do preseed_package(preseed_file) - end + end end end description = install_version ? "version #{install_version} of" : "" @@ -92,7 +92,7 @@ class Chef @new_resource.version(candidate_version) orig_version = @current_resource.version || "uninstalled" converge_by("upgrade package #{@new_resource.package_name} from #{orig_version} to #{candidate_version}") do - status = upgrade_package(@new_resource.package_name, candidate_version) + upgrade_package(@new_resource.package_name, candidate_version) Chef::Log.info("#{@new_resource} upgraded from #{orig_version} to #{candidate_version}") end end @@ -146,7 +146,7 @@ class Chef if preseed_file = get_preseed_file(@new_resource.package_name, @current_resource.version) converge_by("reconfigure package #{@new_resource.package_name}") do preseed_package(preseed_file) - status = reconfig_package(@new_resource.package_name, @current_resource.version) + reconfig_package(@new_resource.package_name, @current_resource.version) Chef::Log.info("#{@new_resource} reconfigured") end else @@ -198,21 +198,21 @@ class Chef Chef::Log.debug("#{@new_resource} fetching preseed file to #{cache_seed_to}") - begin + + if template_available?(@new_resource.response_file) + Chef::Log.debug("#{@new_resource} fetching preseed file via Template") remote_file = Chef::Resource::Template.new(cache_seed_to, run_context) - remote_file.cookbook_name = @new_resource.cookbook_name - remote_file.source(@new_resource.response_file) - remote_file.backup(false) - provider = Chef::Platform.provider_for_resource(remote_file, :create) - provider.template_location - rescue - Chef::Log.debug("#{@new_resource} fetching preseed file via Template resource failed, fallback to CookbookFile resource") + elsif cookbook_file_available?(@new_resource.response_file) + Chef::Log.debug("#{@new_resource} fetching preseed file via cookbook_file") remote_file = Chef::Resource::CookbookFile.new(cache_seed_to, run_context) - remote_file.cookbook_name = @new_resource.cookbook_name - remote_file.source(@new_resource.response_file) - remote_file.backup(false) + else + message = "No template or cookbook file found for response file #{@new_resource.response_file}" + raise Chef::Exceptions::FileNotFound, message end + remote_file.cookbook_name = @new_resource.cookbook_name + remote_file.source(@new_resource.response_file) + remote_file.backup(false) remote_file end @@ -224,6 +224,16 @@ class Chef @new_resource.version == @current_resource.version end + private + + def template_available?(path) + run_context.has_template_in_cookbook?(@new_resource.cookbook_name, path) + end + + def cookbook_file_available?(path) + run_context.has_cookbook_file_in_cookbook?(@new_resource.cookbook_name, path) + end + end end end diff --git a/lib/chef/provider/package/aix.rb b/lib/chef/provider/package/aix.rb new file mode 100644 index 0000000000..4df0ea7a33 --- /dev/null +++ b/lib/chef/provider/package/aix.rb @@ -0,0 +1,146 @@ +# +# Author:: Deepali Jagtap +# 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/package' +require 'chef/mixin/command' +require 'chef/resource/package' +require 'chef/mixin/get_source_from_package' + +class Chef + class Provider + class Package + class Aix < Chef::Provider::Package + + include Chef::Mixin::GetSourceFromPackage + + def define_resource_requirements + super + requirements.assert(:install) do |a| + a.assertion { @new_resource.source } + a.failure_message Chef::Exceptions::Package, "Source for package #{@new_resource.name} required for action install" + end + requirements.assert(:all_actions) do |a| + a.assertion { !@new_resource.source || @package_source_found } + a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}" + a.whyrun "would assume #{@new_resource.source} would be have previously been made available" + end + end + + def load_current_resource + @current_resource = Chef::Resource::Package.new(@new_resource.name) + @current_resource.package_name(@new_resource.package_name) + @new_resource.version(nil) + + if @new_resource.source + @package_source_found = ::File.exists?(@new_resource.source) + if @package_source_found + Chef::Log.debug("#{@new_resource} checking pkg status") + status = popen4("installp -L -d #{@new_resource.source}") do |pid, stdin, stdout, stderr| + package_found = false + stdout.each do |line| + case line + when /#{@new_resource.package_name}:/ + package_found = true + fields = line.split(":") + @new_resource.version(fields[2]) + end + end + end + end + end + + Chef::Log.debug("#{@new_resource} checking install state") + status = popen4("lslpp -lcq #{@current_resource.package_name}") do |pid, stdin, stdout, stderr| + stdout.each do |line| + case line + when /#{@current_resource.package_name}/ + fields = line.split(":") + Chef::Log.debug("#{@new_resource} version #{fields[2]} is already installed") + @current_resource.version(fields[2]) + end + end + end + + unless status.exitstatus == 0 || status.exitstatus == 1 + raise Chef::Exceptions::Package, "lslpp failed - #{status.inspect}!" + end + + @current_resource + end + + def candidate_version + return @candidate_version if @candidate_version + status = popen4("installp -L -d #{@new_resource.source}") do |pid, stdin, stdout, stderr| + stdout.each_line do |line| + case line + when /\w:{Regexp.escape(@new_resource.package_name)}:(.*)/ + fields = line.split(":") + @candidate_version = fields[2] + @new_resource.version(fields[2]) + Chef::Log.debug("#{@new_resource} setting install candidate version to #{@candidate_version}") + end + end + end + unless status.exitstatus == 0 + raise Chef::Exceptions::Package, "installp -L -d #{@new_resource.source} - #{status.inspect}!" + end + @candidate_version + end + + # + # The install/update action needs to be tested with various kinds of packages + # on AIX viz. packages with or without licensing file dependencies, packages + # with dependencies on other packages which will help to test additional + # options of installp. + # So far, the code has been tested only with standalone packages. + # + def install_package(name, version) + Chef::Log.debug("#{@new_resource} package install options: #{@new_resource.options}") + if @new_resource.options.nil? + run_command_with_systems_locale( + :command => "installp -aYF -d #{@new_resource.source} #{@new_resource.package_name}" + ) + Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}") + else + run_command_with_systems_locale( + :command => "installp -aYF #{expand_options(@new_resource.options)} -d #{@new_resource.source} #{@new_resource.package_name}" + ) + Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}") + end + end + + alias_method :upgrade_package, :install_package + + def remove_package(name, version) + if @new_resource.options.nil? + run_command_with_systems_locale( + :command => "installp -u #{name}" + ) + Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}") + else + run_command_with_systems_locale( + :command => "installp -u #{expand_options(@new_resource.options)} #{name}" + ) + Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}") + end + end + + end + end + end +end diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb index e8939b494e..dc7b3f2086 100644 --- a/lib/chef/provider/package/apt.rb +++ b/lib/chef/provider/package/apt.rb @@ -65,7 +65,8 @@ class Chef @is_virtual_package = true showpkg = shell_out!("apt-cache showpkg #{package}").stdout providers = Hash.new - showpkg.rpartition(/Reverse Provides:? #{$/}/)[2].each_line do |line| + # Returns all lines after 'Reverse Provides:' + showpkg.rpartition(/Reverse Provides:\s*#{$/}/)[2].each_line do |line| provider, version = line.split providers[provider] = version end @@ -90,12 +91,7 @@ class Chef def install_package(name, version) package_name = "#{name}=#{version}" package_name = name if @is_virtual_package - run_command_with_systems_locale( - :command => "apt-get -q -y#{expand_options(default_release_options)}#{expand_options(@new_resource.options)} install #{package_name}", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - ) + run_noninteractive("apt-get -q -y#{expand_options(default_release_options)}#{expand_options(@new_resource.options)} install #{package_name}") end def upgrade_package(name, version) @@ -104,41 +100,30 @@ class Chef def remove_package(name, version) package_name = "#{name}" - run_command_with_systems_locale( - :command => "apt-get -q -y#{expand_options(@new_resource.options)} remove #{package_name}", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - ) + run_noninteractive("apt-get -q -y#{expand_options(@new_resource.options)} remove #{package_name}") end def purge_package(name, version) - run_command_with_systems_locale( - :command => "apt-get -q -y#{expand_options(@new_resource.options)} purge #{@new_resource.package_name}", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - ) + run_noninteractive("apt-get -q -y#{expand_options(@new_resource.options)} purge #{@new_resource.package_name}") end def preseed_package(preseed_file) Chef::Log.info("#{@new_resource} pre-seeding package installation instructions") - run_command_with_systems_locale( - :command => "debconf-set-selections #{preseed_file}", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - ) + run_noninteractive("debconf-set-selections #{preseed_file}") end def reconfig_package(name, version) Chef::Log.info("#{@new_resource} reconfiguring") - run_command_with_systems_locale( - :command => "dpkg-reconfigure #{name}", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - ) + run_noninteractive("dpkg-reconfigure #{name}") + end + + private + + # Runs command via shell_out with magic environment to disable + # interactive prompts. Command is run with default localization rather + # than forcing locale to "C", so command output may not be stable. + def run_noninteractive(command) + shell_out!(command, :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil }) end end diff --git a/lib/chef/provider/package/dpkg.rb b/lib/chef/provider/package/dpkg.rb index 795a7b308b..8ec1ad5878 100644 --- a/lib/chef/provider/package/dpkg.rb +++ b/lib/chef/provider/package/dpkg.rb @@ -6,9 +6,9 @@ # 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. @@ -32,14 +32,14 @@ class Chef include Chef::Mixin::GetSourceFromPackage def define_resource_requirements super - requirements.assert(:install) do |a| + requirements.assert(:install) do |a| a.assertion{ not @new_resource.source.nil? } a.failure_message Chef::Exceptions::Package, "Source for package #{@new_resource.name} required for action install" end # TODO this was originally written for any action in which .source is provided # but would it make more sense to only look at source if the action is :install? - requirements.assert(:all_actions) do |a| + requirements.assert(:all_actions) do |a| a.assertion { @source_exists } a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}" a.whyrun "Assuming it would have been previously downloaded." @@ -53,7 +53,7 @@ class Chef @new_resource.version(nil) if @new_resource.source - @source_exists = ::File.exists?(@new_resource.source) + @source_exists = ::File.exists?(@new_resource.source) if @source_exists # Get information from the package if supplied Chef::Log.debug("#{@new_resource} checking dpkg status") @@ -71,7 +71,7 @@ class Chef end end - + # Check to see if it is installed package_installed = nil Chef::Log.debug("#{@new_resource} checking install state") @@ -92,10 +92,10 @@ class Chef unless status.exitstatus == 0 || status.exitstatus == 1 raise Chef::Exceptions::Package, "dpkg failed - #{status.inspect}!" end - + @current_resource end - + def install_package(name, version) run_command_with_systems_locale( :command => "dpkg -i#{expand_options(@new_resource.options)} #{@new_resource.source}", @@ -113,7 +113,7 @@ class Chef } ) end - + def purge_package(name, version) run_command_with_systems_locale( :command => "dpkg -P#{expand_options(@new_resource.options)} #{@new_resource.package_name}", diff --git a/lib/chef/provider/package/freebsd.rb b/lib/chef/provider/package/freebsd.rb index afdd0d812e..f9cb5eb422 100644 --- a/lib/chef/provider/package/freebsd.rb +++ b/lib/chef/provider/package/freebsd.rb @@ -37,7 +37,7 @@ class Chef def current_installed_version pkg_info = shell_out!("pkg_info -E \"#{package_name}*\"", :env => nil, :returns => [0,1]) - pkg_info.stdout[/^#{package_name}-(.+)/, 1] + pkg_info.stdout[/^#{Regexp.escape(package_name)}-(.+)/, 1] end def port_path @@ -52,7 +52,7 @@ class Chef # Otherwise look up the path to the ports directory using 'whereis' else whereis = shell_out!("whereis -s #{@new_resource.package_name}", :env => nil) - unless path = whereis.stdout[/^#{@new_resource.package_name}:\s+(.+)$/, 1] + unless path = whereis.stdout[/^#{Regexp.escape(@new_resource.package_name)}:\s+(.+)$/, 1] raise Chef::Exceptions::Package, "Could not find port with the name #{@new_resource.package_name}" end path diff --git a/lib/chef/provider/package/ips.rb b/lib/chef/provider/package/ips.rb index 5beb46a20a..2c6d98d81a 100644 --- a/lib/chef/provider/package/ips.rb +++ b/lib/chef/provider/package/ips.rb @@ -33,12 +33,12 @@ class Chef def define_resource_requirements super - + requirements.assert(:all_actions) do |a| a.assertion { ! @candidate_version.nil? } a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.package_name} not found" a.whyrun "Assuming package #{@new_resource.package_name} would have been made available." - end + end end def load_current_resource @@ -52,7 +52,7 @@ class Chef Chef::Log.debug("Checking package status for #{package}") installed = false depends = false - + shell_out!("pkg info -r #{package}").stdout.each_line do |line| case line when /^\s+State: Installed/ diff --git a/lib/chef/provider/package/macports.rb b/lib/chef/provider/package/macports.rb index fd33788944..6ef303ee4f 100644 --- a/lib/chef/provider/package/macports.rb +++ b/lib/chef/provider/package/macports.rb @@ -44,7 +44,7 @@ class Chef def install_package(name, version) unless @current_resource.version == version command = "port#{expand_options(@new_resource.options)} install #{name}" - command << " @#{version}" if version and !version.empty? + command << " @#{version}" if version and !version.empty? run_command_with_systems_locale( :command => command ) diff --git a/lib/chef/provider/package/pacman.rb b/lib/chef/provider/package/pacman.rb index f81486ae84..2e8bb7850b 100644 --- a/lib/chef/provider/package/pacman.rb +++ b/lib/chef/provider/package/pacman.rb @@ -6,9 +6,9 @@ # 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. @@ -24,7 +24,7 @@ class Chef class Provider class Package class Pacman < Chef::Provider::Package - + def load_current_resource @current_resource = Chef::Resource::Package.new(@new_resource.name) @current_resource.package_name(@new_resource.package_name) @@ -84,27 +84,27 @@ class Chef @candidate_version end - + def install_package(name, version) run_command_with_systems_locale( :command => "pacman --sync --noconfirm --noprogressbar#{expand_options(@new_resource.options)} #{name}" ) end - + def upgrade_package(name, version) install_package(name, version) end - + def remove_package(name, version) run_command_with_systems_locale( :command => "pacman --remove --noconfirm --noprogressbar#{expand_options(@new_resource.options)} #{name}" ) end - + def purge_package(name, version) remove_package(name, version) end - + end end end diff --git a/lib/chef/provider/package/rpm.rb b/lib/chef/provider/package/rpm.rb index 033ce8efb9..616a78a2f5 100644 --- a/lib/chef/provider/package/rpm.rb +++ b/lib/chef/provider/package/rpm.rb @@ -6,9 +6,9 @@ # 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. @@ -30,18 +30,18 @@ class Chef def define_resource_requirements super - requirements.assert(:all_actions) do |a| + requirements.assert(:all_actions) do |a| a.assertion { @package_source_exists } a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}" a.whyrun "Assuming package #{@new_resource.name} would have been made available." end - requirements.assert(:all_actions) do |a| - a.assertion { !@rpm_status.nil? && (@rpm_status.exitstatus == 0 || @rpm_status.exitstatus == 1) } + requirements.assert(:all_actions) do |a| + a.assertion { !@rpm_status.nil? && (@rpm_status.exitstatus == 0 || @rpm_status.exitstatus == 1) } a.failure_message Chef::Exceptions::Package, "Unable to determine current version due to RPM failure. Detail: #{@rpm_status.inspect}" a.whyrun "Assuming current version would have been determined for package#{@new_resource.name}." end end - + def load_current_resource @package_source_provided = true @package_source_exists = true @@ -49,13 +49,13 @@ class Chef @current_resource = Chef::Resource::Package.new(@new_resource.name) @current_resource.package_name(@new_resource.package_name) @new_resource.version(nil) - + if @new_resource.source unless ::File.exists?(@new_resource.source) @package_source_exists = false return end - + Chef::Log.debug("#{@new_resource} checking rpm status") status = popen4("rpm -qp --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{@new_resource.source}") do |pid, stdin, stdout, stderr| stdout.each do |line| @@ -72,7 +72,7 @@ class Chef return end end - + Chef::Log.debug("#{@new_resource} checking install state") @rpm_status = popen4("rpm -q --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{@current_resource.package_name}") do |pid, stdin, stdout, stderr| stdout.each do |line| @@ -83,11 +83,11 @@ class Chef end end end - - + + @current_resource end - + def install_package(name, version) unless @current_resource.version run_command_with_systems_locale( @@ -99,9 +99,9 @@ class Chef ) end end - + alias_method :upgrade_package, :install_package - + def remove_package(name, version) if version run_command_with_systems_locale( diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb index 28d332420b..b423c199a0 100644 --- a/lib/chef/provider/package/rubygems.rb +++ b/lib/chef/provider/package/rubygems.rb @@ -72,7 +72,7 @@ class Chef raise NotImplementedError end - ## + ## # A rubygems specification object containing the list of gemspecs for all # available gems in the gem installation. # Implemented by subclasses diff --git a/lib/chef/provider/package/smartos.rb b/lib/chef/provider/package/smartos.rb index b17f6f2564..28d56ddc2c 100644 --- a/lib/chef/provider/package/smartos.rb +++ b/lib/chef/provider/package/smartos.rb @@ -64,14 +64,14 @@ class Chef pkg = shell_out!("/opt/local/bin/pkgin se #{new_resource.package_name}", :env => nil, :returns => [0,1]) pkg.stdout.each_line do |line| case line - when /^#{name}/ + when /^#{new_resource.package_name}/ name, version = line.split[0].split(/-([^-]+)$/) end end @candidate_version = version version end - + def install_package(name, version) Chef::Log.debug("#{@new_resource} installing package #{name} version #{version}") package = "#{name}-#{version}" @@ -84,7 +84,7 @@ class Chef end def remove_package(name, version) - Chef::Log.debug("#{@new_resource} removing package #{name} version #{version}") + Chef::Log.debug("#{@new_resource} removing package #{name} version #{version}") package = "#{name}" out = shell_out!("/opt/local/bin/pkgin -y remove #{package}", :env => nil) end diff --git a/lib/chef/provider/package/solaris.rb b/lib/chef/provider/package/solaris.rb index f502a0dc96..0f45b61e18 100644 --- a/lib/chef/provider/package/solaris.rb +++ b/lib/chef/provider/package/solaris.rb @@ -33,12 +33,12 @@ class Chef # end def define_resource_requirements super - requirements.assert(:install) do |a| + requirements.assert(:install) do |a| a.assertion { @new_resource.source } a.failure_message Chef::Exceptions::Package, "Source for package #{@new_resource.name} required for action install" end - requirements.assert(:all_actions) do |a| - a.assertion { !@new_resource.source || @package_source_found } + requirements.assert(:all_actions) do |a| + a.assertion { !@new_resource.source || @package_source_found } a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}" a.whyrun "would assume #{@new_resource.source} would be have previously been made available" end @@ -51,7 +51,7 @@ class Chef if @new_resource.source @package_source_found = ::File.exists?(@new_resource.source) - if @package_source_found + if @package_source_found Chef::Log.debug("#{@new_resource} checking pkg status") status = popen4("pkginfo -l -d #{@new_resource.source} #{@new_resource.package_name}") do |pid, stdin, stdout, stderr| stdout.each do |line| @@ -107,13 +107,23 @@ class Chef def install_package(name, version) Chef::Log.debug("#{@new_resource} package install options: #{@new_resource.options}") if @new_resource.options.nil? + if ::File.directory?(@new_resource.source) # CHEF-4469 + command = "pkgadd -n -d #{@new_resource.source} #{@new_resource.package_name}" + else + command = "pkgadd -n -d #{@new_resource.source} all" + end run_command_with_systems_locale( - :command => "pkgadd -n -d #{@new_resource.source} all" + :command => command ) Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}") else + if ::File.directory?(@new_resource.source) # CHEF-4469 + command = "pkgadd -n#{expand_options(@new_resource.options)} -d #{@new_resource.source} #{@new_resource.package_name}" + else + command = "pkgadd -n#{expand_options(@new_resource.options)} -d #{@new_resource.source} all" + end run_command_with_systems_locale( - :command => "pkgadd -n#{expand_options(@new_resource.options)} -d #{@new_resource.source} all" + :command => command ) Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}") end diff --git a/lib/chef/provider/package/yum-dump.py b/lib/chef/provider/package/yum-dump.py index 407eb8f408..a8f3995e8c 100644 --- a/lib/chef/provider/package/yum-dump.py +++ b/lib/chef/provider/package/yum-dump.py @@ -6,9 +6,9 @@ # 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. @@ -249,8 +249,8 @@ def yum_dump(options): # Preserve order of enable/disable repo args like yum does def gather_repo_opts(option, opt, value, parser): - if getattr(parser.values, option.dest, None) is None: - setattr(parser.values, option.dest, []) + if getattr(parser.values, option.dest, None) is None: + setattr(parser.values, option.dest, []) getattr(parser.values, option.dest).append((opt, value.split(','))) def main(): diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb index 233e949e12..f56d3140b6 100644 --- a/lib/chef/provider/package/yum.rb +++ b/lib/chef/provider/package/yum.rb @@ -667,7 +667,7 @@ class Chef @allow_multi_install = [] - @extra_repo_control = nil + @extra_repo_control = nil # these are for subsequent runs if we are on an interval Chef::Client.when_run_starts do @@ -1046,7 +1046,7 @@ class Chef end # At this point package_name could be: - # + # # 1) a package name, eg: "foo" # 2) a package name.arch, eg: "foo.i386" # 3) or a dependency, eg: "foo >= 1.1" @@ -1154,7 +1154,7 @@ class Chef # Hacky - better overall solution? Custom compare in Package provider? def action_upgrade # Could be uninstalled or have no candidate - if @current_resource.version.nil? || candidate_version.nil? + if @current_resource.version.nil? || candidate_version.nil? super # Ensure the candidate is newer elsif RPMVersion.parse(candidate_version) > RPMVersion.parse(@current_resource.version) diff --git a/lib/chef/provider/powershell_script.rb b/lib/chef/provider/powershell_script.rb index 700eb88c11..c459cdf678 100644 --- a/lib/chef/provider/powershell_script.rb +++ b/lib/chef/provider/powershell_script.rb @@ -6,9 +6,9 @@ # 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. @@ -23,7 +23,7 @@ class Chef class PowershellScript < Chef::Provider::WindowsScript protected - + EXIT_STATUS_NORMALIZATION_SCRIPT = "\nif ($? -eq $true) {exit 0} elseif ( $LASTEXITCODE -ne 0) {exit $LASTEXITCODE} else { exit 1 }" EXIT_STATUS_RESET_SCRIPT = "$LASTEXITCODE=0\n" @@ -41,12 +41,12 @@ class Chef end public - + def initialize (new_resource, run_context) super(new_resource, run_context, '.ps1') NormalizeScriptExitStatus(new_resource.code) end - + def flags default_flags = [ "-NoLogo", @@ -60,8 +60,8 @@ class Chef # file created by the base class that contains the script # code -- otherwise, powershell.exe does not propagate the # error status of a failed Windows process that ran at the - # end of the script, it gets changed to '1'. - "-File" + # end of the script, it gets changed to '1'. + "-File" ] interpreter_flags = default_flags.join(' ') diff --git a/lib/chef/provider/remote_file/ftp.rb b/lib/chef/provider/remote_file/ftp.rb index d75fb7a52c..7f3fdbf383 100644 --- a/lib/chef/provider/remote_file/ftp.rb +++ b/lib/chef/provider/remote_file/ftp.rb @@ -143,6 +143,7 @@ class Chef ftp.voidcmd("TYPE #{typecode.upcase}") end ftp.getbinaryfile(filename, tempfile.path) + tempfile.close if tempfile tempfile end diff --git a/lib/chef/provider/remote_file/http.rb b/lib/chef/provider/remote_file/http.rb index 6ffd83f438..8949e6ab04 100644 --- a/lib/chef/provider/remote_file/http.rb +++ b/lib/chef/provider/remote_file/http.rb @@ -17,7 +17,7 @@ # limitations under the License. # -require 'chef/rest' +require 'chef/http/simple' require 'chef/digester' require 'chef/provider/remote_file' require 'chef/provider/remote_file/cache_control_data' @@ -58,9 +58,9 @@ class Chef def fetch tempfile = nil begin - rest = Chef::REST.new(uri, nil, nil, http_client_opts) - tempfile = rest.streaming_request(uri, headers) - update_cache_control_data(tempfile, rest.last_response) + http = Chef::HTTP::Simple.new(uri, http_client_opts) + tempfile = http.streaming_request(uri, headers) + update_cache_control_data(tempfile, http.last_response) rescue Net::HTTPRetriableError => e if e.response.is_a? Net::HTTPNotModified tempfile = nil @@ -68,7 +68,7 @@ class Chef raise e end end - + tempfile.close if tempfile tempfile end diff --git a/lib/chef/provider/remote_file/local_file.rb b/lib/chef/provider/remote_file/local_file.rb index 87f498e053..b3b2301b81 100644 --- a/lib/chef/provider/remote_file/local_file.rb +++ b/lib/chef/provider/remote_file/local_file.rb @@ -38,6 +38,7 @@ class Chef tempfile = Chef::FileContentManagement::Tempfile.new(new_resource).tempfile Chef::Log.debug("#{new_resource} staging #{uri.path} to #{tempfile.path}") FileUtils.cp(uri.path, tempfile.path) + tempfile.close if tempfile tempfile end diff --git a/lib/chef/provider/resource_update.rb b/lib/chef/provider/resource_update.rb index e2c6bffca4..54f25738ed 100644 --- a/lib/chef/provider/resource_update.rb +++ b/lib/chef/provider/resource_update.rb @@ -4,27 +4,27 @@ class Chef # { # "run_id" : "1000", - # "resource" : { + # "resource" : { # "type" : "file", - # "name" : "/etc/passwd", + # "name" : "/etc/passwd", # "start_time" : "2012-01-09T08:15:30-05:00", # "end_time" : "2012-01-09T08:15:30-05:00", # "status" : "modified", - # "initial_state" : "exists", - # "final_state" : "modified", - # "before" : { - # "group" : "root", + # "initial_state" : "exists", + # "final_state" : "modified", + # "before" : { + # "group" : "root", # "owner" : "root", # "checksum" : "xyz" # }, - # "after" : { - # "group" : "root", + # "after" : { + # "group" : "root", # "owner" : "root", # "checksum" : "abc" # }, # "delta" : "escaped delta goes here" # }, - # "event_data" : "" + # "event_data" : "" # } class ResourceUpdate diff --git a/lib/chef/provider/ruby_block.rb b/lib/chef/provider/ruby_block.rb index 16908b0eff..b0d94a3f8d 100644 --- a/lib/chef/provider/ruby_block.rb +++ b/lib/chef/provider/ruby_block.rb @@ -7,9 +7,9 @@ # 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. @@ -29,7 +29,7 @@ class Chef end def action_run - converge_by("execute the ruby block #{@new_resource.name}") do + converge_by("execute the ruby block #{@new_resource.name}") do @new_resource.block.call Chef::Log.info("#{@new_resource} called") end diff --git a/lib/chef/provider/script.rb b/lib/chef/provider/script.rb index 1b459f36cf..4aacf4f524 100644 --- a/lib/chef/provider/script.rb +++ b/lib/chef/provider/script.rb @@ -27,7 +27,7 @@ class Chef super @code = @new_resource.code end - + def action_run script_file.puts(@code) script_file.close diff --git a/lib/chef/provider/service.rb b/lib/chef/provider/service.rb index 8d76927676..968f9bff9c 100644 --- a/lib/chef/provider/service.rb +++ b/lib/chef/provider/service.rb @@ -35,7 +35,7 @@ class Chef end def load_new_resource_state - # If the user didn't specify a change in enabled state, + # If the user didn't specify a change in enabled state, # it will be the same as the old resource if ( @new_resource.enabled.nil? ) @new_resource.enabled(@current_resource.enabled) @@ -54,7 +54,7 @@ class Chef a.failure_message Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :reload" # if a service is not declared to support reload, that won't # typically change during the course of a run - so no whyrun - # alternative here. + # alternative here. end end diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb index e2a0f60d91..d788d58c00 100644 --- a/lib/chef/provider/service/debian.rb +++ b/lib/chef/provider/service/debian.rb @@ -41,17 +41,17 @@ class Chef shared_resource_requirements requirements.assert(:all_actions) do |a| update_rcd = "/usr/sbin/update-rc.d" - a.assertion { ::File.exists? update_rcd } + a.assertion { ::File.exists? update_rcd } a.failure_message Chef::Exceptions::Service, "#{update_rcd} does not exist!" # no whyrun recovery - this is a base system component of debian - # distros and must be present - end + # distros and must be present + end requirements.assert(:all_actions) do |a| - a.assertion { @priority_success } + a.assertion { @priority_success } a.failure_message Chef::Exceptions::Service, "/usr/sbin/update-rc.d -n -f #{@current_resource.service_name} failed - #{@rcd_status.inspect}" - # This can happen if the service is not yet installed,so we'll fake it. - a.whyrun ["Unable to determine priority of service, assuming service would have been correctly installed earlier in the run.", + # This can happen if the service is not yet installed,so we'll fake it. + a.whyrun ["Unable to determine priority of service, assuming service would have been correctly installed earlier in the run.", "Assigning temporary priorities to continue.", "If this service is not properly installed prior to this point, this will fail."] do temp_priorities = {"6"=>[:stop, "20"], @@ -74,7 +74,7 @@ class Chef [stdout, stderr].each do |iop| iop.each_line do |line| if UPDATE_RC_D_PRIORITIES =~ line - # priority[runlevel] = [ S|K, priority ] + # priority[runlevel] = [ S|K, priority ] # S = Start, K = Kill # debian runlevels: 0 Halt, 1 Singleuser, 2 Multiuser, 3-5 == 2, 6 Reboot priority[$1] = [($2 == "S" ? :start : :stop), $3] @@ -86,6 +86,12 @@ class Chef end end + # Reduce existing priority back to an integer if appropriate, picking + # runlevel 2 as a baseline + if priority[2] && [2..5].all? { |runlevel| priority[runlevel] == priority[2] } + priority = priority[2].last + end + unless @rcd_status.exitstatus == 0 @priority_success = false end @@ -105,14 +111,28 @@ class Chef enabled end - def enable_service() + # Override method from parent to ensure priority is up-to-date + def action_enable + if @current_resource.enabled && @current_resource.priority == @new_resource.priority + Chef::Log.debug("#{@new_resource} already enabled - nothing to do") + else + converge_by("enable service #{@new_resource}") do + enable_service + Chef::Log.info("#{@new_resource} enabled") + end + end + load_new_resource_state + @new_resource.enabled(true) + end + + def enable_service if @new_resource.priority.is_a? Integer run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") run_command(:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} defaults #{@new_resource.priority} #{100 - @new_resource.priority}") elsif @new_resource.priority.is_a? Hash - # we call the same command regardless of we're enabling or disabling + # we call the same command regardless of we're enabling or disabling # users passing a Hash are responsible for setting their own start priorities - set_priority() + set_priority else # No priority, go with update-rc.d defaults run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") run_command(:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} defaults") @@ -120,23 +140,23 @@ class Chef end - def disable_service() + def disable_service if @new_resource.priority.is_a? Integer # Stop processes in reverse order of start using '100 - start_priority' run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop #{100 - @new_resource.priority} 2 3 4 5 .") elsif @new_resource.priority.is_a? Hash - # we call the same command regardless of we're enabling or disabling + # we call the same command regardless of we're enabling or disabling # users passing a Hash are responsible for setting their own stop priorities - set_priority() - else + set_priority + else # no priority, using '100 - 20 (update-rc.d default)' to stop in reverse order of start run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove") run_command(:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop 80 2 3 4 5 .") end end - def set_priority() + def set_priority args = "" @new_resource.priority.each do |level, o| action = o[0] diff --git a/lib/chef/provider/service/freebsd.rb b/lib/chef/provider/service/freebsd.rb index b875838ec2..cb0f6b0fc4 100644 --- a/lib/chef/provider/service/freebsd.rb +++ b/lib/chef/provider/service/freebsd.rb @@ -38,13 +38,13 @@ class Chef elsif ::File.exists?("/usr/local/etc/rc.d/#{current_resource.service_name}") @init_command = "/usr/local/etc/rc.d/#{current_resource.service_name}" else - @rcd_script_found = false + @rcd_script_found = false return end Chef::Log.debug("#{@current_resource} found at #{@init_command}") determine_current_status! # Default to disabled if the service doesn't currently exist - # at all + # at all var_name = service_enable_variable_name if ::File.exists?("/etc/rc.conf") && var_name read_rc_conf.each do |line| @@ -70,19 +70,19 @@ class Chef def define_resource_requirements shared_resource_requirements requirements.assert(:start, :enable, :reload, :restart) do |a| - a.assertion { @rcd_script_found } + a.assertion { @rcd_script_found } a.failure_message Chef::Exceptions::Service, "#{@new_resource}: unable to locate the rc.d script" end - requirements.assert(:all_actions) do |a| - a.assertion { @enabled_state_found } - # for consistentcy with original behavior, this will not fail in non-whyrun mode; + requirements.assert(:all_actions) do |a| + a.assertion { @enabled_state_found } + # for consistentcy with original behavior, this will not fail in non-whyrun mode; # rather it will silently set enabled state=>false - a.whyrun "Unable to determine enabled/disabled state, assuming this will be correct for an actual run. Assuming disabled." + a.whyrun "Unable to determine enabled/disabled state, assuming this will be correct for an actual run. Assuming disabled." end requirements.assert(:start, :enable, :reload, :restart) do |a| - a.assertion { @rcd_script_found && service_enable_variable_name != nil } + a.assertion { @rcd_script_found && service_enable_variable_name != nil } a.failure_message Chef::Exceptions::Service, "Could not find the service name in #{@init_command} and rcvar" # No recovery in whyrun mode - the init file is present but not correct. end @@ -133,7 +133,7 @@ class Chef # corresponding to this service # For example: to enable the service mysql-server with the init command /usr/local/etc/rc.d/mysql-server, you need # to set mysql_enable="YES" in /etc/rc.conf$ - if @rcd_script_found + if @rcd_script_found ::File.open(@init_command) do |rcscript| rcscript.each_line do |line| if line =~ /^name="?(\w+)"?/ diff --git a/lib/chef/provider/service/gentoo.rb b/lib/chef/provider/service/gentoo.rb index 45b5a21f9b..ba4edc5807 100644 --- a/lib/chef/provider/service/gentoo.rb +++ b/lib/chef/provider/service/gentoo.rb @@ -44,7 +44,7 @@ class Chef::Provider::Service::Gentoo < Chef::Provider::Service::Init def define_resource_requirements requirements.assert(:all_actions) do |a| - a.assertion { ::File.exists?("/sbin/rc-update") } + a.assertion { ::File.exists?("/sbin/rc-update") } a.failure_message Chef::Exceptions::Service, "/sbin/rc-update does not exist" # no whyrun recovery -t his is a core component whose presence is # unlikely to be affected by what we do in the course of a chef run @@ -52,15 +52,15 @@ class Chef::Provider::Service::Gentoo < Chef::Provider::Service::Init requirements.assert(:all_actions) do |a| a.assertion { @found_script } - # No failure, just informational output from whyrun + # No failure, just informational output from whyrun a.whyrun "Could not find service #{@new_resource.service_name} under any runlevel" end end - + def enable_service() run_command(:command => "/sbin/rc-update add #{@new_resource.service_name} default") end - + def disable_service() run_command(:command => "/sbin/rc-update del #{@new_resource.service_name} default") end diff --git a/lib/chef/provider/service/init.rb b/lib/chef/provider/service/init.rb index 09f47e866f..63ba8fa6ab 100644 --- a/lib/chef/provider/service/init.rb +++ b/lib/chef/provider/service/init.rb @@ -47,7 +47,7 @@ class Chef end end end - + def start_service if @new_resource.start_command super diff --git a/lib/chef/provider/service/insserv.rb b/lib/chef/provider/service/insserv.rb index 32152376ee..cb9c28e17e 100644 --- a/lib/chef/provider/service/insserv.rb +++ b/lib/chef/provider/service/insserv.rb @@ -32,9 +32,9 @@ class Chef if Dir.glob("/etc/rc**/S*#{@current_resource.service_name}").empty? @current_resource.enabled false else - @current_resource.enabled true + @current_resource.enabled true end - + @current_resource end diff --git a/lib/chef/provider/service/invokercd.rb b/lib/chef/provider/service/invokercd.rb index 69a17bb4fb..ee2719d75a 100644 --- a/lib/chef/provider/service/invokercd.rb +++ b/lib/chef/provider/service/invokercd.rb @@ -24,7 +24,7 @@ class Chef class Provider class Service class Invokercd < Chef::Provider::Service::Init - + def initialize(new_resource, run_context) super @init_command = "/usr/sbin/invoke-rc.d #{@new_resource.service_name}" diff --git a/lib/chef/provider/service/redhat.rb b/lib/chef/provider/service/redhat.rb index 629e4ee0c3..06be9f3207 100644 --- a/lib/chef/provider/service/redhat.rb +++ b/lib/chef/provider/service/redhat.rb @@ -48,7 +48,7 @@ class Chef requirements.assert(:start, :enable, :reload, :restart) do |a| a.assertion { !@service_missing } a.failure_message Chef::Exceptions::Service, "#{@new_resource}: unable to locate the init.d script!" - a.whyrun "Assuming service would be disabled. The init script is not presently installed." + a.whyrun "Assuming service would be disabled. The init script is not presently installed." end end @@ -59,7 +59,7 @@ class Chef chkconfig = shell_out!("/sbin/chkconfig --list #{@current_resource.service_name}", :returns => [0,1]) @current_resource.enabled(!!(chkconfig.stdout =~ CHKCONFIG_ON)) @service_missing = !!(chkconfig.stderr =~ CHKCONFIG_MISSING) - end + end @current_resource end diff --git a/lib/chef/provider/service/simple.rb b/lib/chef/provider/service/simple.rb index bcb85230d0..288b5f5456 100644 --- a/lib/chef/provider/service/simple.rb +++ b/lib/chef/provider/service/simple.rb @@ -45,8 +45,8 @@ class Chef def shared_resource_requirements super - requirements.assert(:all_actions) do |a| - a.assertion { @status_load_success } + requirements.assert(:all_actions) do |a| + a.assertion { @status_load_success } a.whyrun ["Service status not available. Assuming a prior action would have installed the service.", "Assuming status of not running."] end end @@ -74,12 +74,12 @@ class Chef end requirements.assert(:all_actions) do |a| - a.assertion { @new_resource.status_command or @new_resource.supports[:status] or - (!ps_cmd.nil? and !ps_cmd.empty?) } + a.assertion { @new_resource.status_command or @new_resource.supports[:status] or + (!ps_cmd.nil? and !ps_cmd.empty?) } a.failure_message Chef::Exceptions::Service, "#{@new_resource} could not determine how to inspect the process table, please set this node's 'command.ps' attribute" end - requirements.assert(:all_actions) do |a| - a.assertion { !@ps_command_failed } + requirements.assert(:all_actions) do |a| + a.assertion { !@ps_command_failed } a.failure_message Chef::Exceptions::Service, "Command #{ps_cmd} failed to execute, cannot determine service current status" end end diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb index 33a29da109..4bdb6fbfd1 100644 --- a/lib/chef/provider/service/solaris.rb +++ b/lib/chef/provider/service/solaris.rb @@ -31,7 +31,7 @@ class Chef @init_command = "/usr/sbin/svcadm" @status_command = "/bin/svcs -l" end - + def load_current_resource @current_resource = Chef::Resource::Service.new(@new_resource.name) diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb index 59b4fe1564..89077c5feb 100644 --- a/lib/chef/provider/service/systemd.rb +++ b/lib/chef/provider/service/systemd.rb @@ -50,7 +50,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple def define_resource_requirements shared_resource_requirements requirements.assert(:all_actions) do |a| - a.assertion { @status_check_success } + a.assertion { @status_check_success } # We won't stop in any case, but in whyrun warn and tell what we're doing. a.whyrun ["Failed to determine status of #{@new_resource}, using command #{@new_resource.status_command}.", "Assuming service would have been installed and is disabled"] @@ -99,11 +99,11 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple def enable_service run_command_with_systems_locale(:command => "/bin/systemctl enable #{@new_resource.service_name}") - end + end def disable_service run_command_with_systems_locale(:command => "/bin/systemctl disable #{@new_resource.service_name}") - end + end def is_active? run_command_with_systems_locale({:command => "/bin/systemctl is-active #{@new_resource.service_name}", :ignore_failure => true}) == 0 diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb index 763a2aa92b..67ca649b6d 100644 --- a/lib/chef/provider/service/upstart.rb +++ b/lib/chef/provider/service/upstart.rb @@ -26,7 +26,7 @@ class Chef class Service class Upstart < Chef::Provider::Service::Simple UPSTART_STATE_FORMAT = /\w+ \(?(\w+)\)?[\/ ](\w+)/ - + # Upstart does more than start or stop a service, creating multiple 'states' [1] that a service can be in. # In chef, when we ask a service to start, we expect it to have started before performing the next step # since we have top down dependencies. Which is to say we may follow witha resource next that requires @@ -40,17 +40,17 @@ class Chef # TODO: re-evaluate if this is needed after integrating cookbook fix raise ArgumentError, "run_context cannot be nil" unless run_context super - + run_context.node - + @job = @new_resource.service_name - + if @new_resource.parameters @new_resource.parameters.each do |key, value| @job << " #{key}=#{value}" end end - + platform, version = Chef::Platform.find_platform_and_version(run_context.node) if platform == "ubuntu" && (8.04..9.04).include?(version.to_f) @upstart_job_dir = "/etc/event.d" @@ -60,8 +60,8 @@ class Chef @upstart_conf_suffix = ".conf" end - @command_success = true # new_resource.status_command= false, means upstart used - @config_file_found = true + @command_success = true # new_resource.status_command= false, means upstart used + @config_file_found = true @upstart_command_success = true end @@ -70,18 +70,18 @@ class Chef shared_resource_requirements requirements.assert(:all_actions) do |a| if !@command_success - whyrun_msg = @new_resource.status_command ? "Provided status command #{@new_resource.status_command} failed." : + whyrun_msg = @new_resource.status_command ? "Provided status command #{@new_resource.status_command} failed." : "Could not determine upstart state for service" end a.assertion { @command_success } - # no failure here, just document the assumptions made. - a.whyrun "#{whyrun_msg} Assuming service installed and not running." + # no failure here, just document the assumptions made. + a.whyrun "#{whyrun_msg} Assuming service installed and not running." end - requirements.assert(:all_actions) do |a| - a.assertion { @config_file_found } - # no failure here, just document the assumptions made. - a.whyrun "Could not find #{@upstart_job_dir}/#{@new_resource.service_name}#{@upstart_conf_suffix}. Assuming service is disabled." + requirements.assert(:all_actions) do |a| + a.assertion { @config_file_found } + # no failure here, just document the assumptions made. + a.whyrun "Could not find #{@upstart_job_dir}/#{@new_resource.service_name}#{@upstart_conf_suffix}. Assuming service is disabled." end end @@ -176,7 +176,7 @@ class Chef super # Upstart always provides restart functionality so we don't need to mimic it with stop/sleep/start. # Older versions of upstart would fail on restart if the service was currently stopped, check for that. LP:430883 - else @new_resource.supports[:restart] + else if @current_resource.running run_command_with_systems_locale(:command => "/sbin/restart #{@job}") else diff --git a/lib/chef/provider/subversion.rb b/lib/chef/provider/subversion.rb index e1f87b4dd8..6ceb3e592a 100644 --- a/lib/chef/provider/subversion.rb +++ b/lib/chef/provider/subversion.rb @@ -17,7 +17,7 @@ # -#TODO subversion and git should both extend from a base SCM provider. +#TODO subversion and git should both extend from a base SCM provider. require 'chef/log' require 'chef/provider' @@ -52,7 +52,7 @@ class Chef # for why run, print a message explaining the potential error. parent_directory = ::File.dirname(@new_resource.destination) a.assertion { ::File.directory?(parent_directory) } - a.failure_message(Chef::Exceptions::MissingParentDirectory, + a.failure_message(Chef::Exceptions::MissingParentDirectory, "Cannot clone #{@new_resource} to #{@new_resource.destination}, the enclosing directory #{parent_directory} does not exist") a.whyrun("Directory #{parent_directory} does not exist, assuming it would have been created") end @@ -91,13 +91,13 @@ class Chef converge_by("sync #{@new_resource.destination} from #{@new_resource.repository}") do run_command(run_options(:command => sync_command)) Chef::Log.info "#{@new_resource} updated to revision: #{revision_int}" - end + end end else action_checkout end end - + def sync_command c = scm :update, @new_resource.svn_arguments, verbose, authentication, "-r#{revision_int}", @new_resource.destination Chef::Log.debug "#{@new_resource} updated working copy #{@new_resource.destination} to revision #{@new_resource.revision}" @@ -156,6 +156,7 @@ class Chef def run_options(run_opts={}) run_opts[:user] = @new_resource.user if @new_resource.user run_opts[:group] = @new_resource.group if @new_resource.group + run_opts[:timeout] = @new_resource.timeout if @new_resource.timeout run_opts end @@ -197,7 +198,7 @@ class Chef def scm(*args) ['svn', *args].compact.join(" ") end - + def target_dir_non_existent_or_empty? !::File.exist?(@new_resource.destination) || Dir.entries(@new_resource.destination).sort == ['.','..'] diff --git a/lib/chef/provider/user.rb b/lib/chef/provider/user.rb index e815ba9c9e..738f7660f8 100644 --- a/lib/chef/provider/user.rb +++ b/lib/chef/provider/user.rb @@ -6,9 +6,9 @@ # 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. @@ -79,9 +79,7 @@ class Chef end end - if @new_resource.gid - convert_group_name - end + convert_group_name if @new_resource.gid end @current_resource @@ -89,14 +87,14 @@ class Chef def define_resource_requirements requirements.assert(:all_actions) do |a| - a.assertion { @group_name_resolved } + a.assertion { @group_name_resolved } a.failure_message Chef::Exceptions::User, "Couldn't lookup integer GID for group name #{@new_resource.gid}" a.whyrun "group name #{@new_resource.gid} does not exist. This will cause group assignment to fail. Assuming this group will have been created previously." end requirements.assert(:all_actions) do |a| - a.assertion { @shadow_lib_ok } + a.assertion { @shadow_lib_ok } a.failure_message Chef::Exceptions::MissingLibrary, "You must have ruby-shadow installed for password support!" - a.whyrun "ruby-shadow is not installed. Attempts to set user password will cause failure. Assuming that this gem will have been previously installed." + + a.whyrun "ruby-shadow is not installed. Attempts to set user password will cause failure. Assuming that this gem will have been previously installed." + "Note that user update converge may report false-positive on the basis of mismatched password. " end requirements.assert(:modify, :lock, :unlock) do |a| @@ -112,9 +110,15 @@ class Chef # <true>:: If a change is required # <false>:: If the users are identical def compare_user - [ :uid, :gid, :comment, :home, :shell, :password ].any? do |user_attrib| + changed = [ :comment, :home, :shell, :password ].select do |user_attrib| !@new_resource.send(user_attrib).nil? && @new_resource.send(user_attrib) != @current_resource.send(user_attrib) end + + changed += [ :uid, :gid ].select do |user_attrib| + !@new_resource.send(user_attrib).nil? && @new_resource.send(user_attrib).to_s != @current_resource.send(user_attrib).to_s + end + + changed.any? end def action_create diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb index 94e8420c43..b01931609e 100644 --- a/lib/chef/provider/user/dscl.rb +++ b/lib/chef/provider/user/dscl.rb @@ -6,9 +6,9 @@ # 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. @@ -25,10 +25,10 @@ class Chef class User class Dscl < Chef::Provider::User include Chef::Mixin::ShellOut - + NFS_HOME_DIRECTORY = %r{^NFSHomeDirectory: (.*)$} AUTHENTICATION_AUTHORITY = %r{^AuthenticationAuthority: (.*)$} - + def dscl(*args) shell_out("dscl . -#{args.join(' ')}") end @@ -80,7 +80,7 @@ class Chef return safe_dscl("delete /Users/#{@new_resource.username} NFSHomeDirectory") if (@new_resource.home.nil? || @new_resource.home.empty?) if @new_resource.supports[:manage_home] validate_home_dir_specification! - + if (@current_resource.home == @new_resource.home) && !new_home_exists? ditto_home elsif !current_home_exists? && !new_home_exists? @@ -105,7 +105,7 @@ class Chef end def shadow_hash_set? - user_data = safe_dscl("read /Users/#{@new_resource.username}") + user_data = safe_dscl("read /Users/#{@new_resource.username}") if user_data =~ /AuthenticationAuthority: / && user_data =~ /ShadowHash/ true else @@ -116,7 +116,7 @@ class Chef def modify_password if @new_resource.password shadow_hash = nil - + Chef::Log.debug("#{new_resource} updating password") if osx_shadow_hash?(@new_resource.password) shadow_hash = @new_resource.password.upcase @@ -134,11 +134,11 @@ class Chef shadow_hash = String.new("00000000"*155) shadow_hash[168] = salted_sha1 end - + ::File.open("/var/db/shadow/hash/#{guid}",'w',0600) do |output| output.puts shadow_hash end - + unless shadow_hash_set? safe_dscl("append /Users/#{@new_resource.username} AuthenticationAuthority ';ShadowHash;'") end @@ -159,7 +159,7 @@ class Chef dscl_set_shell modify_password end - + def manage_user dscl_create_user if diverged?(:username) dscl_create_comment if diverged?(:comment) @@ -169,15 +169,15 @@ class Chef dscl_set_shell if diverged?(:shell) modify_password if diverged?(:password) end - + def dscl_create_user - safe_dscl("create /Users/#{@new_resource.username}") + safe_dscl("create /Users/#{@new_resource.username}") end - + def dscl_create_comment safe_dscl("create /Users/#{@new_resource.username} RealName '#{@new_resource.comment}'") end - + def dscl_set_gid unless @new_resource.gid && @new_resource.gid.to_s.match(/^\d+$/) begin @@ -189,7 +189,7 @@ class Chef end safe_dscl("create /Users/#{@new_resource.username} PrimaryGroupID '#{@new_resource.gid}'") end - + def dscl_set_shell if @new_resource.password || ::File.exists?("#{@new_resource.shell}") safe_dscl("create /Users/#{@new_resource.username} UserShell '#{@new_resource.shell}'") @@ -197,10 +197,10 @@ class Chef safe_dscl("create /Users/#{@new_resource.username} UserShell '/usr/bin/false'") end end - + def remove_user if @new_resource.supports[:manage_home] - user_info = safe_dscl("read /Users/#{@new_resource.username}") + user_info = safe_dscl("read /Users/#{@new_resource.username}") if nfs_home_match = user_info.match(NFS_HOME_DIRECTORY) #nfs_home = safe_dscl("read /Users/#{@new_resource.username} NFSHomeDirectory") #nfs_home.gsub!(/NFSHomeDirectory: /,"").gsub!(/\n$/,"") @@ -228,7 +228,7 @@ class Chef false end end - + def check_lock return @locked = locked? end @@ -236,27 +236,27 @@ class Chef def lock_user safe_dscl("append /Users/#{@new_resource.username} AuthenticationAuthority ';DisabledUser;'") end - + def unlock_user auth_info = safe_dscl("read /Users/#{@new_resource.username} AuthenticationAuthority") auth_string = auth_info.gsub(/AuthenticationAuthority: /,"").gsub(/;DisabledUser;/,"").strip#.gsub!(/[; ]*$/,"") safe_dscl("create /Users/#{@new_resource.username} AuthenticationAuthority '#{auth_string}'") end - + def validate_home_dir_specification! unless @new_resource.home =~ /^\// - raise(Chef::Exceptions::InvalidHomeDirectory,"invalid path spec for User: '#{@new_resource.username}', home directory: '#{@new_resource.home}'") + raise(Chef::Exceptions::InvalidHomeDirectory,"invalid path spec for User: '#{@new_resource.username}', home directory: '#{@new_resource.home}'") end end - + def current_home_exists? ::File.exist?("#{@current_resource.home}") end - + def new_home_exists? - ::File.exist?("#{@new_resource.home}") + ::File.exist?("#{@new_resource.home}") end - + def ditto_home skel = "/System/Library/User Template/English.lproj" raise(Chef::Exceptions::User,"can't find skel at: #{skel}") unless ::File.exists?(skel) @@ -266,7 +266,7 @@ class Chef def move_home Chef::Log.debug("#{@new_resource} moving #{self} home from #{@current_resource.home} to #{@new_resource.home}") - + src = @current_resource.home FileUtils.mkdir_p(@new_resource.home) files = ::Dir.glob("#{src}/*", ::File::FNM_DOTMATCH) - ["#{src}/.","#{src}/.."] @@ -274,11 +274,11 @@ class Chef ::FileUtils.rmdir(src) ::FileUtils.chown_R(@new_resource.username,@new_resource.gid.to_s,@new_resource.home) end - + def diverged?(parameter) parameter_updated?(parameter) && (not @new_resource.send(parameter).nil?) end - + def parameter_updated?(parameter) not (@new_resource.send(parameter) == @current_resource.send(parameter)) end diff --git a/lib/chef/provider/user/pw.rb b/lib/chef/provider/user/pw.rb index 4f6393da89..9f7a169892 100644 --- a/lib/chef/provider/user/pw.rb +++ b/lib/chef/provider/user/pw.rb @@ -6,9 +6,9 @@ # 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. @@ -34,20 +34,20 @@ class Chef run_command(:command => command) modify_password end - + def manage_user command = "pw usermod" command << set_options run_command(:command => command) modify_password end - + def remove_user command = "pw userdel #{@new_resource.username}" command << " -r" if @new_resource.supports[:manage_home] run_command(:command => command) end - + def check_lock case @current_resource.password when /^\*LOCKED\*/ @@ -57,18 +57,18 @@ class Chef end @locked end - + def lock_user run_command(:command => "pw lock #{@new_resource.username}") end - + def unlock_user run_command(:command => "pw unlock #{@new_resource.username}") end - + def set_options opts = " #{@new_resource.username}" - + field_list = { 'comment' => "-c", 'home' => "-d", @@ -91,7 +91,7 @@ class Chef end opts end - + def modify_password if @current_resource.password != @new_resource.password Chef::Log.debug("#{new_resource} updating password") @@ -99,7 +99,7 @@ class Chef status = popen4(command, :waitlast => true) do |pid, stdin, stdout, stderr| stdin.puts "#{@new_resource.password}" end - + unless status.exitstatus == 0 raise Chef::Exceptions::User, "pw failed - #{status.inspect}!" end diff --git a/lib/chef/provider/user/useradd.rb b/lib/chef/provider/user/useradd.rb index 41455007dc..1789a4e5ff 100644 --- a/lib/chef/provider/user/useradd.rb +++ b/lib/chef/provider/user/useradd.rb @@ -124,7 +124,7 @@ class Chef end def update_options(field, option, opts) - if @current_resource.send(field) != new_resource.send(field) + if @current_resource.send(field).to_s != new_resource.send(field).to_s if new_resource.send(field) Chef::Log.debug("#{new_resource} setting #{field} to #{new_resource.send(field)}") opts << option << new_resource.send(field).to_s diff --git a/lib/chef/provider/user/windows.rb b/lib/chef/provider/user/windows.rb index 6bbb2a088c..350f3ff4c0 100644 --- a/lib/chef/provider/user/windows.rb +++ b/lib/chef/provider/user/windows.rb @@ -6,9 +6,9 @@ # 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. @@ -71,23 +71,23 @@ class Chef def create_user @net_user.add(set_options) end - + def manage_user @net_user.update(set_options) end - + def remove_user @net_user.delete end - + def check_lock @net_user.check_enabled end - + def lock_user @net_user.disable_account end - + def unlock_user @net_user.enable_account end diff --git a/lib/chef/provider/windows_script.rb b/lib/chef/provider/windows_script.rb index 398e1aee6e..08a2ea74df 100644 --- a/lib/chef/provider/windows_script.rb +++ b/lib/chef/provider/windows_script.rb @@ -6,9 +6,9 @@ # 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. @@ -24,7 +24,7 @@ class Chef class WindowsScript < Chef::Provider::Script protected - + include Chef::Mixin::WindowsArchitectureHelper def initialize( new_resource, run_context, script_extension='') @@ -43,14 +43,14 @@ class Chef 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 @@ -61,11 +61,11 @@ class Chef 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 diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index e0039428f2..50099e8afc 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -21,6 +21,7 @@ require 'chef/provider/breakpoint' require 'chef/provider/cookbook_file' require 'chef/provider/cron' require 'chef/provider/cron/solaris' +require 'chef/provider/cron/aix' require 'chef/provider/deploy' require 'chef/provider/directory' require 'chef/provider/env' @@ -64,6 +65,7 @@ require 'chef/provider/package/yum' require 'chef/provider/package/zypper' require 'chef/provider/package/solaris' require 'chef/provider/package/smartos' +require 'chef/provider/package/aix' require 'chef/provider/service/arch' require 'chef/provider/service/debian' @@ -97,6 +99,7 @@ require 'chef/provider/group/usermod' require 'chef/provider/group/windows' require 'chef/provider/mount/mount' +require 'chef/provider/mount/aix' require 'chef/provider/mount/windows' require 'chef/provider/deploy/revision' @@ -117,3 +120,4 @@ require 'chef/provider/template/content' require 'chef/provider/ifconfig/redhat' require 'chef/provider/ifconfig/debian' +require 'chef/provider/ifconfig/aix' diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb index 6ea69360b8..0c688cb5f8 100644 --- a/lib/chef/recipe.rb +++ b/lib/chef/recipe.rb @@ -81,26 +81,9 @@ class Chef run_context.resource_collection.find(*args) end - # Sets a tag, or list of tags, for this node. Syntactic sugar for - # run_context.node[:tags]. - # - # With no arguments, returns the list of tags. - # - # === Parameters - # tags<Array>:: A list of tags to add - can be a single string - # - # === Returns - # tags<Array>:: The contents of run_context.node[:tags] + # This was moved to Chef::Node#tag, redirecting here for compatability def tag(*tags) - if tags.length > 0 - tags.each do |tag| - tag = tag.to_s - run_context.node.normal[:tags] << tag unless run_context.node[:tags].include?(tag) - end - run_context.node[:tags] - else - run_context.node[:tags] - end + run_context.node.tag(*tags) end # Returns true if the node is tagged with *all* of the supplied +tags+. diff --git a/lib/chef/resource/apt_package.rb b/lib/chef/resource/apt_package.rb index 524abbb370..050cf838ae 100644 --- a/lib/chef/resource/apt_package.rb +++ b/lib/chef/resource/apt_package.rb @@ -6,9 +6,9 @@ # 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. @@ -22,7 +22,7 @@ require 'chef/provider/package/apt' class Chef class Resource class AptPackage < Chef::Resource::Package - + def initialize(name, run_context=nil) super @resource_name = :apt_package diff --git a/lib/chef/resource/bash.rb b/lib/chef/resource/bash.rb index 374bca9e11..c56de5fe20 100644 --- a/lib/chef/resource/bash.rb +++ b/lib/chef/resource/bash.rb @@ -6,9 +6,9 @@ # 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. @@ -21,7 +21,7 @@ require 'chef/resource/script' class Chef class Resource class Bash < Chef::Resource::Script - + def initialize(name, run_context=nil) super @resource_name = :bash diff --git a/lib/chef/resource/batch.rb b/lib/chef/resource/batch.rb index 705260bbce..576e6b4c6b 100644 --- a/lib/chef/resource/batch.rb +++ b/lib/chef/resource/batch.rb @@ -6,9 +6,9 @@ # 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. @@ -21,11 +21,11 @@ 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/bff_package.rb b/lib/chef/resource/bff_package.rb new file mode 100644 index 0000000000..2d78483e4b --- /dev/null +++ b/lib/chef/resource/bff_package.rb @@ -0,0 +1,36 @@ +# +# Author:: Deepali Jagtap (<deepali.jagtap@clogeny.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/package' +require 'chef/provider/package/aix' + +class Chef + class Resource + class BffPackage < Chef::Resource::Package + + def initialize(name, run_context=nil) + super + @resource_name = :bff_package + @provider = Chef::Provider::Package::Aix + end + + end + end +end + + diff --git a/lib/chef/resource/breakpoint.rb b/lib/chef/resource/breakpoint.rb index 34aeae6b47..83c397bd5b 100644 --- a/lib/chef/resource/breakpoint.rb +++ b/lib/chef/resource/breakpoint.rb @@ -6,9 +6,9 @@ # 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. @@ -22,7 +22,7 @@ require 'chef/resource' class Chef class Resource class Breakpoint < Chef::Resource - + def initialize(action="break", *args) @name = caller.first super(@name, *args) diff --git a/lib/chef/resource/cron.rb b/lib/chef/resource/cron.rb index 5f858cec81..dfbb91f80c 100644 --- a/lib/chef/resource/cron.rb +++ b/lib/chef/resource/cron.rb @@ -7,9 +7,9 @@ # 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. @@ -22,7 +22,7 @@ require 'chef/resource' class Chef class Resource class Cron < Chef::Resource - + identity_attr :command state_attrs :minute, :hour, :day, :month, :weekday, :user @@ -186,9 +186,9 @@ class Chef :kind_of => Hash ) end - + private - + # On Ruby 1.8, Kernel#Integer will happily do this for you. On 1.9, no. def integerize(integerish) Integer(integerish) diff --git a/lib/chef/resource/csh.rb b/lib/chef/resource/csh.rb index 6e871e8605..95aa8afd7a 100644 --- a/lib/chef/resource/csh.rb +++ b/lib/chef/resource/csh.rb @@ -6,9 +6,9 @@ # 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. @@ -21,7 +21,7 @@ require 'chef/resource/script' class Chef class Resource class Csh < Chef::Resource::Script - + def initialize(name, run_context=nil) super @resource_name = :csh diff --git a/lib/chef/resource/deploy.rb b/lib/chef/resource/deploy.rb index 8b614028bf..76478ed07c 100644 --- a/lib/chef/resource/deploy.rb +++ b/lib/chef/resource/deploy.rb @@ -50,9 +50,9 @@ class Chef # release directory. Callback files can contain chef code (resources, etc.) # class Deploy < Chef::Resource - + provider_base Chef::Provider::Deploy - + identity_attr :repository state_attrs :deploy_to, :revision @@ -389,7 +389,7 @@ class Chef arg ||= block set_or_return(:after_restart, arg, :kind_of => [Proc, String]) end - + def additional_remotes(arg=nil) set_or_return( :additional_remotes, @@ -398,6 +398,19 @@ class Chef ) end + # FIXME The Deploy resource may be passed to an SCM provider as its + # resource. The SCM provider knows that SCM resources can specify a + # timeout for SCM operations. The deploy resource must therefore support + # a timeout method, but the timeout it describes is for SCM operations, + # not the overall deployment. This is potentially confusing. + def timeout(arg=nil) + set_or_return( + :timeout, + arg, + :kind_of => Integer + ) + end + end end end diff --git a/lib/chef/resource/deploy_revision.rb b/lib/chef/resource/deploy_revision.rb index 55a3e38130..ceac26e91a 100644 --- a/lib/chef/resource/deploy_revision.rb +++ b/lib/chef/resource/deploy_revision.rb @@ -6,9 +6,9 @@ # 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. @@ -18,9 +18,9 @@ class Chef class Resource - + # Convenience class for using the deploy resource with the revision - # deployment strategy (provider) + # deployment strategy (provider) class DeployRevision < Chef::Resource::Deploy def initialize(*args, &block) super @@ -28,13 +28,13 @@ class Chef @provider = Chef::Provider::Deploy::Revision end end - + class DeployBranch < Chef::Resource::DeployRevision def initialize(*args, &block) super @resource_name = :deploy_branch end end - + end end diff --git a/lib/chef/resource/directory.rb b/lib/chef/resource/directory.rb index a5d5ea7366..423c0bbe27 100644 --- a/lib/chef/resource/directory.rb +++ b/lib/chef/resource/directory.rb @@ -25,11 +25,11 @@ require 'chef/mixin/securable' class Chef class Resource class Directory < Chef::Resource - + identity_attr :path state_attrs :group, :mode, :owner - + include Chef::Mixin::Securable provides :directory, :on_platforms => :all diff --git a/lib/chef/resource/dpkg_package.rb b/lib/chef/resource/dpkg_package.rb index 02886e8649..2fb5b5c249 100644 --- a/lib/chef/resource/dpkg_package.rb +++ b/lib/chef/resource/dpkg_package.rb @@ -6,9 +6,9 @@ # 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. @@ -22,13 +22,13 @@ require 'chef/provider/package/dpkg' class Chef class Resource class DpkgPackage < Chef::Resource::Package - + def initialize(name, run_context=nil) super @resource_name = :dpkg_package @provider = Chef::Provider::Package::Dpkg end - + end end end diff --git a/lib/chef/resource/easy_install_package.rb b/lib/chef/resource/easy_install_package.rb index 10e80bdd3b..f25e1ac22f 100644 --- a/lib/chef/resource/easy_install_package.rb +++ b/lib/chef/resource/easy_install_package.rb @@ -21,7 +21,7 @@ require 'chef/resource/package' class Chef class Resource class EasyInstallPackage < Chef::Resource::Package - + def initialize(name, run_context=nil) super @resource_name = :easy_install_package diff --git a/lib/chef/resource/erl_call.rb b/lib/chef/resource/erl_call.rb index e0e38926bb..959856af66 100644 --- a/lib/chef/resource/erl_call.rb +++ b/lib/chef/resource/erl_call.rb @@ -24,7 +24,7 @@ class Chef class ErlCall < Chef::Resource # erl_call : http://erlang.org/doc/man/erl_call.html - + identity_attr :code def initialize(name, run_context=nil) diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb index 9a9a84900e..94286eae18 100644 --- a/lib/chef/resource/freebsd_package.rb +++ b/lib/chef/resource/freebsd_package.rb @@ -6,9 +6,9 @@ # 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. @@ -22,13 +22,13 @@ require 'chef/provider/package/freebsd' class Chef class Resource class FreebsdPackage < Chef::Resource::Package - + def initialize(name, run_context=nil) super @resource_name = :freebsd_package @provider = Chef::Provider::Package::Freebsd end - + end end end diff --git a/lib/chef/resource/group.rb b/lib/chef/resource/group.rb index 76f3a779ae..17f14c8387 100644 --- a/lib/chef/resource/group.rb +++ b/lib/chef/resource/group.rb @@ -7,9 +7,9 @@ # 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. @@ -20,7 +20,7 @@ class Chef class Resource class Group < Chef::Resource - + identity_attr :group_name state_attrs :members @@ -33,9 +33,10 @@ class Chef @members = [] @action = :create @append = false + @non_unique = false @allowed_actions.push(:create, :remove, :modify, :manage) end - + def group_name(arg=nil) set_or_return( :group_name, @@ -43,7 +44,7 @@ class Chef :kind_of => [ String ] ) end - + def gid(arg=nil) set_or_return( :gid, @@ -62,7 +63,7 @@ class Chef end alias_method :users, :members - + def append(arg=nil) set_or_return( :append, @@ -78,6 +79,14 @@ class Chef :kind_of => [ TrueClass, FalseClass ] ) end + + def non_unique(arg=nil) + set_or_return( + :non_unique, + arg, + :kind_of => [ TrueClass, FalseClass ] + ) + end end end end diff --git a/lib/chef/resource/http_request.rb b/lib/chef/resource/http_request.rb index fc64121f4e..47f6286fb4 100644 --- a/lib/chef/resource/http_request.rb +++ b/lib/chef/resource/http_request.rb @@ -7,9 +7,9 @@ # 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. @@ -22,7 +22,7 @@ require 'chef/resource' class Chef class Resource class HttpRequest < Chef::Resource - + identity_attr :url def initialize(name, run_context=nil) @@ -34,7 +34,7 @@ class Chef @headers = {} @allowed_actions.push(:get, :put, :post, :delete, :head, :options) end - + def url(args=nil) set_or_return( :url, @@ -42,7 +42,7 @@ class Chef :kind_of => String ) end - + def message(args=nil, &block) args = block if block_given? set_or_return( @@ -59,7 +59,7 @@ class Chef :kind_of => Hash ) end - + end end end diff --git a/lib/chef/resource/ifconfig.rb b/lib/chef/resource/ifconfig.rb index daa8a572a0..c289ddadbe 100644 --- a/lib/chef/resource/ifconfig.rb +++ b/lib/chef/resource/ifconfig.rb @@ -7,9 +7,9 @@ # 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. @@ -22,7 +22,7 @@ require 'chef/resource' class Chef class Resource class Ifconfig < Chef::Resource - + identity_attr :device state_attrs :inet_addr, :mask @@ -39,7 +39,7 @@ class Chef @bcast = nil @mtu = nil @metric = nil - @device = nil + @device = nil @onboot = nil @network = nil @bootproto = nil diff --git a/lib/chef/resource/ips_package.rb b/lib/chef/resource/ips_package.rb index f82e0877df..88c6e9a538 100644 --- a/lib/chef/resource/ips_package.rb +++ b/lib/chef/resource/ips_package.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/resource/log.rb b/lib/chef/resource/log.rb index 30a5bb93c6..391c3b5393 100644 --- a/lib/chef/resource/log.rb +++ b/lib/chef/resource/log.rb @@ -7,9 +7,9 @@ # 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. @@ -19,7 +19,7 @@ class Chef class Resource class Log < Chef::Resource - + identity_attr :message # Sends a string from a recipe to a log provider @@ -27,16 +27,16 @@ class Chef # log "some string to log" do # level :info # (default) also supports :warn, :debug, and :error # end - # + # # === Example - # log "your string to log" + # log "your string to log" # - # or + # or # # log "a debug string" { level :debug } # - - # Initialize log resource with a name as the string to log + + # Initialize log resource with a name as the string to log # # === Parameters # name<String>:: Message to log @@ -47,6 +47,7 @@ class Chef @resource_name = :log @level = :info @action = :write + @allowed_actions.push(:write) @message = name end @@ -57,7 +58,7 @@ class Chef :kind_of => String ) end - + # <Symbol> Log level, one of :debug, :info, :warn, :error or :fatal def level(arg=nil) set_or_return( @@ -66,9 +67,9 @@ class Chef :equal_to => [ :debug, :info, :warn, :error, :fatal ] ) end - + end - end + end end diff --git a/lib/chef/resource/macports_package.rb b/lib/chef/resource/macports_package.rb index 911d3c19cb..c9434c9e69 100644 --- a/lib/chef/resource/macports_package.rb +++ b/lib/chef/resource/macports_package.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/resource/mount.rb b/lib/chef/resource/mount.rb index ad68391fe4..49984630c0 100644 --- a/lib/chef/resource/mount.rb +++ b/lib/chef/resource/mount.rb @@ -7,9 +7,9 @@ # 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. @@ -22,7 +22,7 @@ require 'chef/resource' class Chef class Resource class Mount < Chef::Resource - + identity_attr :device state_attrs :mount_point, :device_type, :fstype, :username, :password, :domain @@ -46,7 +46,7 @@ class Chef @password = nil @domain = nil end - + def mount_point(arg=nil) set_or_return( :mount_point, @@ -54,7 +54,7 @@ class Chef :kind_of => [ String ] ) end - + def device(arg=nil) set_or_return( :device, @@ -62,7 +62,7 @@ class Chef :kind_of => [ String ] ) end - + def device_type(arg=nil) real_arg = arg.kind_of?(String) ? arg.to_sym : arg set_or_return( @@ -79,7 +79,7 @@ class Chef :kind_of => [ String ] ) end - + def options(arg=nil) if arg.is_a?(String) converted_arg = arg.gsub(/,/, ' ').split(/ /) @@ -92,7 +92,7 @@ class Chef :kind_of => [ Array ] ) end - + def dump(arg=nil) set_or_return( :dump, @@ -100,7 +100,7 @@ class Chef :kind_of => [ Integer, FalseClass ] ) end - + def pass(arg=nil) set_or_return( :pass, @@ -108,7 +108,7 @@ class Chef :kind_of => [ Integer, FalseClass ] ) end - + def mounted(arg=nil) set_or_return( :mounted, @@ -124,7 +124,7 @@ class Chef :kind_of => [ TrueClass, FalseClass ] ) end - + def supports(args={}) if args.is_a? Array args.each { |arg| @supports[arg] = true } @@ -163,4 +163,3 @@ class Chef end end - diff --git a/lib/chef/resource/ohai.rb b/lib/chef/resource/ohai.rb index 48e55e9f01..b567db40f9 100644 --- a/lib/chef/resource/ohai.rb +++ b/lib/chef/resource/ohai.rb @@ -7,9 +7,9 @@ # 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. @@ -20,7 +20,7 @@ class Chef class Resource class Ohai < Chef::Resource - + identity_attr :name state_attrs :plugin diff --git a/lib/chef/resource/pacman_package.rb b/lib/chef/resource/pacman_package.rb index d66c93be66..2894e415ac 100644 --- a/lib/chef/resource/pacman_package.rb +++ b/lib/chef/resource/pacman_package.rb @@ -6,9 +6,9 @@ # 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. @@ -21,13 +21,13 @@ require 'chef/resource/package' class Chef class Resource class PacmanPackage < Chef::Resource::Package - + def initialize(name, run_context=nil) super @resource_name = :pacman_package @provider = Chef::Provider::Package::Pacman end - + end end end diff --git a/lib/chef/resource/perl.rb b/lib/chef/resource/perl.rb index d3cf696cbb..546f639e1f 100644 --- a/lib/chef/resource/perl.rb +++ b/lib/chef/resource/perl.rb @@ -6,9 +6,9 @@ # 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. @@ -21,7 +21,7 @@ require 'chef/resource/script' class Chef class Resource class Perl < Chef::Resource::Script - + def initialize(name, run_context=nil) super @resource_name = :perl diff --git a/lib/chef/resource/portage_package.rb b/lib/chef/resource/portage_package.rb index fc72381482..42c03560b6 100644 --- a/lib/chef/resource/portage_package.rb +++ b/lib/chef/resource/portage_package.rb @@ -6,9 +6,9 @@ # 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. @@ -21,13 +21,13 @@ require 'chef/resource/package' class Chef class Resource class PortagePackage < Chef::Resource::Package - + def initialize(name, run_context=nil) super @resource_name = :portage_package @provider = Chef::Provider::Package::Portage end - + end end end diff --git a/lib/chef/resource/powershell_script.rb b/lib/chef/resource/powershell_script.rb index e257eb2fb1..cbd81b1259 100644 --- a/lib/chef/resource/powershell_script.rb +++ b/lib/chef/resource/powershell_script.rb @@ -6,9 +6,9 @@ # 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. @@ -25,7 +25,7 @@ class Chef def initialize(name, run_context=nil) super(name, run_context, :powershell_script, "powershell.exe") end - + end end end diff --git a/lib/chef/resource/python.rb b/lib/chef/resource/python.rb index 85a5348d27..f340afdb39 100644 --- a/lib/chef/resource/python.rb +++ b/lib/chef/resource/python.rb @@ -6,9 +6,9 @@ # 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. @@ -21,7 +21,7 @@ require 'chef/resource/script' class Chef class Resource class Python < Chef::Resource::Script - + def initialize(name, run_context=nil) super @resource_name = :python diff --git a/lib/chef/resource/route.rb b/lib/chef/resource/route.rb index c8680697af..942905d138 100644 --- a/lib/chef/resource/route.rb +++ b/lib/chef/resource/route.rb @@ -7,9 +7,9 @@ # 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. @@ -26,7 +26,7 @@ class Chef identity_attr :target state_attrs :netmask, :gateway - + def initialize(name, run_context=nil) super @resource_name = :route @@ -36,7 +36,7 @@ class Chef @netmask = nil @gateway = nil @metric = nil - @device = nil + @device = nil @route_type = :host @networking = nil @networking_ipv6 = nil diff --git a/lib/chef/resource/rpm_package.rb b/lib/chef/resource/rpm_package.rb index 7ab1202ef2..200a9633ce 100644 --- a/lib/chef/resource/rpm_package.rb +++ b/lib/chef/resource/rpm_package.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/resource/ruby.rb b/lib/chef/resource/ruby.rb index 7617839bab..605d27b00d 100644 --- a/lib/chef/resource/ruby.rb +++ b/lib/chef/resource/ruby.rb @@ -6,9 +6,9 @@ # 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. @@ -21,7 +21,7 @@ require 'chef/resource/script' class Chef class Resource class Ruby < Chef::Resource::Script - + def initialize(name, run_context=nil) super @resource_name = :ruby diff --git a/lib/chef/resource/ruby_block.rb b/lib/chef/resource/ruby_block.rb index 296345bde3..d9b8954a90 100644 --- a/lib/chef/resource/ruby_block.rb +++ b/lib/chef/resource/ruby_block.rb @@ -7,9 +7,9 @@ # 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. @@ -20,7 +20,7 @@ class Chef class Resource class RubyBlock < Chef::Resource - + identity_attr :block_name def initialize(name, run_context=nil) diff --git a/lib/chef/resource/scm.rb b/lib/chef/resource/scm.rb index 781e09a2c9..d9a372900e 100644 --- a/lib/chef/resource/scm.rb +++ b/lib/chef/resource/scm.rb @@ -23,8 +23,8 @@ class Chef class Resource class Scm < Chef::Resource - identity_attr :destination - + identity_attr :destination + state_attrs :revision def initialize(name, run_context=nil) @@ -146,6 +146,14 @@ class Chef ) end + def timeout(arg=nil) + set_or_return( + :timeout, + arg, + :kind_of => Integer + ) + end + end end end diff --git a/lib/chef/resource/script.rb b/lib/chef/resource/script.rb index 6a7c8e0d5e..8cc9c6f0c5 100644 --- a/lib/chef/resource/script.rb +++ b/lib/chef/resource/script.rb @@ -7,9 +7,9 @@ # 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. @@ -22,7 +22,7 @@ require 'chef/resource/execute' class Chef class Resource class Script < Chef::Resource::Execute - + identity_attr :command def initialize(name, run_context=nil) @@ -33,7 +33,7 @@ class Chef @interpreter = nil @flags = nil end - + def code(arg=nil) set_or_return( :code, @@ -41,7 +41,7 @@ class Chef :kind_of => [ String ] ) end - + def interpreter(arg=nil) set_or_return( :interpreter, diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb index ea43baa414..befa4be1c9 100644 --- a/lib/chef/resource/service.rb +++ b/lib/chef/resource/service.rb @@ -7,9 +7,9 @@ # 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. @@ -22,7 +22,7 @@ require 'chef/resource' class Chef class Resource class Service < Chef::Resource - + identity_attr :service_name state_attrs :enabled, :running @@ -47,7 +47,7 @@ class Chef @supports = { :restart => false, :reload => false, :status => false } @allowed_actions.push(:enable, :disable, :start, :stop, :restart, :reload) end - + def service_name(arg=nil) set_or_return( :service_name, @@ -55,7 +55,7 @@ class Chef :kind_of => [ String ] ) end - + # regex for match against ps -ef when !supports[:has_status] && status == nil def pattern(arg=nil) set_or_return( diff --git a/lib/chef/resource/smartos_package.rb b/lib/chef/resource/smartos_package.rb index 315481bd93..0f4f6d8b0a 100644 --- a/lib/chef/resource/smartos_package.rb +++ b/lib/chef/resource/smartos_package.rb @@ -6,9 +6,9 @@ # 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. @@ -21,16 +21,18 @@ require 'chef/provider/package/smartos' class Chef class Resource - class SmartOSPackage < Chef::Resource::Package - + class SmartosPackage < Chef::Resource::Package + def initialize(name, run_context=nil) super @resource_name = :smartos_package @provider = Chef::Provider::Package::SmartOS end - + end end end - +# Backwards compatability +# @todo remove in Chef 12 +Chef::Resource::SmartOSPackage = Chef::Resource::SmartosPackage diff --git a/lib/chef/resource/solaris_package.rb b/lib/chef/resource/solaris_package.rb index becf0236ad..3513703076 100644 --- a/lib/chef/resource/solaris_package.rb +++ b/lib/chef/resource/solaris_package.rb @@ -1,14 +1,15 @@ # # Author:: Toomas Pelberg (<toomasp@gmx.net>) -# Copyright:: Copyright (c) 2010 Opscode, Inc. +# Author:: Prabhu Das (<prabhu.das@clogeny.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. @@ -22,13 +23,13 @@ require 'chef/provider/package/solaris' class Chef class Resource class SolarisPackage < Chef::Resource::Package - - def initialize(name, collection=nil, node=nil) - super(name, collection, node) + + def initialize(name, run_context=nil) + super @resource_name = :solaris_package @provider = Chef::Provider::Package::Solaris end - + end end end diff --git a/lib/chef/resource/subversion.rb b/lib/chef/resource/subversion.rb index e3226d8b3b..04fec9b1d8 100644 --- a/lib/chef/resource/subversion.rb +++ b/lib/chef/resource/subversion.rb @@ -7,9 +7,9 @@ # 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. @@ -31,7 +31,7 @@ class Chef @provider = Chef::Provider::Subversion allowed_actions << :force_export end - + end end end diff --git a/lib/chef/resource/timestamped_deploy.rb b/lib/chef/resource/timestamped_deploy.rb index d89274bb44..4032ae9854 100644 --- a/lib/chef/resource/timestamped_deploy.rb +++ b/lib/chef/resource/timestamped_deploy.rb @@ -6,9 +6,9 @@ # 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. @@ -18,9 +18,9 @@ class Chef class Resource - + # Convenience class for using the deploy resource with the timestamped - # deployment strategy (provider) + # deployment strategy (provider) class TimestampedDeploy < Chef::Resource::Deploy def initialize(*args, &block) super(*args, &block) diff --git a/lib/chef/resource/user.rb b/lib/chef/resource/user.rb index 4d8c4ac11b..357d6d12ea 100644 --- a/lib/chef/resource/user.rb +++ b/lib/chef/resource/user.rb @@ -6,9 +6,9 @@ # 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. @@ -25,7 +25,7 @@ class Chef identity_attr :username state_attrs :uid, :gid, :home - + def initialize(name, run_context=nil) super @resource_name = :user @@ -40,13 +40,13 @@ class Chef @manage_home = false @non_unique = false @action = :create - @supports = { + @supports = { :manage_home => false, :non_unique => false } @allowed_actions.push(:create, :remove, :modify, :manage, :lock, :unlock) end - + def username(arg=nil) set_or_return( :username, @@ -54,7 +54,7 @@ class Chef :kind_of => [ String ] ) end - + def comment(arg=nil) set_or_return( :comment, @@ -62,7 +62,7 @@ class Chef :kind_of => [ String ] ) end - + def uid(arg=nil) set_or_return( :uid, @@ -70,7 +70,7 @@ class Chef :kind_of => [ String, Integer ] ) end - + def gid(arg=nil) set_or_return( :gid, @@ -78,9 +78,9 @@ class Chef :kind_of => [ String, Integer ] ) end - + alias_method :group, :gid - + def home(arg=nil) set_or_return( :home, @@ -88,7 +88,7 @@ class Chef :kind_of => [ String ] ) end - + def shell(arg=nil) set_or_return( :shell, @@ -96,7 +96,7 @@ class Chef :kind_of => [ String ] ) end - + def password(arg=nil) set_or_return( :password, @@ -128,7 +128,7 @@ class Chef :kind_of => [ TrueClass, FalseClass ] ) end - + end end end diff --git a/lib/chef/resource/windows_script.rb b/lib/chef/resource/windows_script.rb index 5f2311a5bb..2b563f5bec 100644 --- a/lib/chef/resource/windows_script.rb +++ b/lib/chef/resource/windows_script.rb @@ -6,9 +6,9 @@ # 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. @@ -27,14 +27,14 @@ class Chef def initialize(name, run_context, resource_name, interpreter_command) super(name, run_context) - @interpreter = interpreter_command + @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( @@ -43,7 +43,7 @@ class Chef :kind_of => Symbol ) end - + protected def assert_architecture_compatible!(desired_architecture) @@ -56,7 +56,7 @@ class Chef def node run_context && run_context.node end - + end end end diff --git a/lib/chef/resource/yum_package.rb b/lib/chef/resource/yum_package.rb index bcb1f65667..dff70bcf62 100644 --- a/lib/chef/resource/yum_package.rb +++ b/lib/chef/resource/yum_package.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/resource_collection.rb b/lib/chef/resource_collection.rb index 7460a185b4..a528a18aed 100644 --- a/lib/chef/resource_collection.rb +++ b/lib/chef/resource_collection.rb @@ -183,7 +183,7 @@ class Chef "The string `#{query_object}' is not valid for resource collection lookup. Correct syntax is `resource_type[resource_name]'" else raise Chef::Exceptions::InvalidResourceSpecification, - "The object `#{query_object.inspect}' is not valid for resource collection lookup. " + + "The object `#{query_object.inspect}' is not valid for resource collection lookup. " + "Use a String like `resource_type[resource_name]' or a Chef::Resource object" end end diff --git a/lib/chef/resource_collection/stepable_iterator.rb b/lib/chef/resource_collection/stepable_iterator.rb index ec1e244758..4d5fc1f497 100644 --- a/lib/chef/resource_collection/stepable_iterator.rb +++ b/lib/chef/resource_collection/stepable_iterator.rb @@ -5,9 +5,9 @@ # 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. @@ -18,94 +18,94 @@ class Chef class ResourceCollection class StepableIterator - + def self.for_collection(new_collection) instance = new(new_collection) instance end - + attr_accessor :collection attr_reader :position - + def initialize(collection=[]) @position = 0 @paused = false @collection = collection end - + def size collection.size end - + def each(&block) reset_iteration(block) @iterator_type = :element iterate end - + def each_index(&block) reset_iteration(block) @iterator_type = :index iterate end - + def each_with_index(&block) reset_iteration(block) @iterator_type = :element_with_index iterate end - + def paused? @paused end - + def pause @paused = true end - + def resume @paused = false iterate end - + def rewind @position = 0 end - + def skip_back(skips=1) @position -= skips end - + def skip_forward(skips=1) @position += skips end - + def step return nil if @position == size call_iterator_block @position += 1 end - + def iterate_on(iteration_type, &block) @iterator_type = iteration_type @iterator_block = block end - + private - + def reset_iteration(iterator_block) @iterator_block = iterator_block @position = 0 @paused = false end - + def iterate while @position < size && !paused? step end collection end - + def call_iterator_block case @iterator_type when :element @@ -118,7 +118,7 @@ class Chef raise "42error: someone forgot to set @iterator_type, wtf?" end end - + end end end diff --git a/lib/chef/resource_definition.rb b/lib/chef/resource_definition.rb index a0160c5885..278114e209 100644 --- a/lib/chef/resource_definition.rb +++ b/lib/chef/resource_definition.rb @@ -6,9 +6,9 @@ # 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. @@ -21,19 +21,19 @@ require 'chef/mixin/params_validate' class Chef class ResourceDefinition - + include Chef::Mixin::FromFile include Chef::Mixin::ParamsValidate - + attr_accessor :name, :params, :recipe, :node - + def initialize(node=nil) @name = nil @params = Hash.new @recipe = nil @node = node end - + def define(resource_name, prototype_params=nil, &block) unless resource_name.kind_of?(Symbol) raise ArgumentError, "You must use a symbol when defining a new resource!" @@ -52,14 +52,14 @@ class Chef end true end - + # When we do the resource definition, we're really just setting new values for # the paramaters we prototyped at the top. This method missing is as simple as # it gets. def method_missing(symbol, *args) @params[symbol] = args.length == 1 ? args[0] : args end - + def to_s "#{name.to_s}" end diff --git a/lib/chef/resource_definition_list.rb b/lib/chef/resource_definition_list.rb index b958624208..55014090d4 100644 --- a/lib/chef/resource_definition_list.rb +++ b/lib/chef/resource_definition_list.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/resource_reporter.rb b/lib/chef/resource_reporter.rb index 434150e83d..d29949086e 100644 --- a/lib/chef/resource_reporter.rb +++ b/lib/chef/resource_reporter.rb @@ -52,8 +52,8 @@ class Chef as_hash["type"] = new_resource.class.dsl_name as_hash["name"] = new_resource.name as_hash["id"] = new_resource.identity - as_hash["after"] = new_resource.state - as_hash["before"] = current_resource ? current_resource.state : {} + as_hash["after"] = state(new_resource) + as_hash["before"] = current_resource ? state(current_resource) : {} as_hash["duration"] = (elapsed_time * 1000).to_i.to_s as_hash["delta"] = new_resource.diff if new_resource.respond_to?("diff") as_hash["delta"] = "" if as_hash["delta"].nil? @@ -80,6 +80,12 @@ class Chef !self.exception end + def state(r) + r.class.state_attrs.inject({}) do |state_attrs, attr_name| + state_attrs[attr_name] = r.send(attr_name) + state_attrs + end + end end # End class ResouceReport attr_reader :updated_resources diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb index 55c6a0dbf3..d0a27d8922 100644 --- a/lib/chef/resources.rb +++ b/lib/chef/resources.rb @@ -56,6 +56,7 @@ require 'chef/resource/registry_key' require 'chef/resource/remote_directory' require 'chef/resource/remote_file' require 'chef/resource/rpm_package' +require 'chef/resource/solaris_package' require 'chef/resource/route' require 'chef/resource/ruby' require 'chef/resource/ruby_block' @@ -69,3 +70,4 @@ require 'chef/resource/timestamped_deploy' require 'chef/resource/user' require 'chef/resource/yum_package' require 'chef/resource/lwrp_base' +require 'chef/resource/bff_package' diff --git a/lib/chef/rest.rb b/lib/chef/rest.rb index 6c74412839..4168cd63be 100644 --- a/lib/chef/rest.rb +++ b/lib/chef/rest.rb @@ -20,15 +20,18 @@ # limitations under the License. # -require 'zlib' -require 'net/https' -require 'uri' -require 'chef/json_compat' require 'tempfile' -require 'chef/rest/auth_credentials' -require 'chef/rest/rest_request' -require 'chef/monkey_patches/string' -require 'chef/monkey_patches/net_http' +require 'chef/http' +class Chef + class HTTP; end + class REST < HTTP; end +end + +require 'chef/http/authenticator' +require 'chef/http/decompressor' +require 'chef/http/json_input' +require 'chef/http/json_to_model_output' +require 'chef/http/cookie_manager' require 'chef/config' require 'chef/exceptions' require 'chef/platform/query_helpers' @@ -37,54 +40,53 @@ class Chef # == Chef::REST # Chef's custom REST client with built-in JSON support and RSA signed header # authentication. - class REST + class REST < HTTP - class NoopInflater - def inflate(chunk) - chunk - end - end + # Backwards compatibility for things that use + # Chef::REST::RESTRequest or its constants + RESTRequest = HTTP::HTTPRequest - attr_reader :auth_credentials attr_accessor :url, :cookies, :sign_on_redirect, :redirect_limit - CONTENT_ENCODING = "content-encoding".freeze - GZIP = "gzip".freeze - DEFLATE = "deflate".freeze - IDENTITY = "identity".freeze + attr_reader :authenticator # Create a REST client object. The supplied +url+ is used as the base for # all subsequent requests. For example, when initialized with a base url # http://localhost:4000, a call to +get_rest+ with 'nodes' will make an # HTTP GET request to http://localhost:4000/nodes def initialize(url, client_name=Chef::Config[:node_name], signing_key_filename=Chef::Config[:client_key], options={}) - @url = url - @cookies = CookieJar.instance - @default_headers = options[:headers] || {} - @signing_key_filename = signing_key_filename - @key = load_signing_key(@signing_key_filename, options[:raw_key]) - @auth_credentials = AuthCredentials.new(client_name, @key) - @sign_on_redirect, @sign_request = true, true - @redirects_followed = 0 - @redirect_limit = 10 - @disable_gzip = false - handle_options(options) + options[:client_name] = client_name + options[:signing_key_filename] = signing_key_filename + super(url, options) + + @decompressor = Decompressor.new(options) + @authenticator = Authenticator.new(options) + + @middlewares << JSONInput.new(options) + @middlewares << JSONToModelOutput.new(options) + @middlewares << CookieManager.new(options) + @middlewares << @decompressor + @middlewares << @authenticator end def signing_key_filename - @signing_key_filename + authenticator.signing_key_filename + end + + def auth_credentials + authenticator.auth_credentials end def client_name - @auth_credentials.client_name + authenticator.client_name end def signing_key - @raw_key + authenticator.raw_key end - def last_response - @last_response + def sign_requests? + authenticator.sign_requests? end # Send an HTTP GET request to the path @@ -97,37 +99,18 @@ class Chef # to JSON inflated. def get(path, raw=false, headers={}) if raw - streaming_request(create_url(path), headers) + streaming_request(path, headers) else - api_request(:GET, create_url(path), headers) + request(:GET, path, headers) end end - def head(path, headers={}) - api_request(:HEAD, create_url(path), headers) - end - alias :get_rest :get - # Send an HTTP DELETE request to the path - def delete(path, headers={}) - api_request(:DELETE, create_url(path), headers) - end - alias :delete_rest :delete - # Send an HTTP POST request to the path - def post(path, json, headers={}) - api_request(:POST, create_url(path), headers, json) - end - alias :post_rest :post - # Send an HTTP PUT request to the path - def put(path, json, headers={}) - api_request(:PUT, create_url(path), headers, json) - end - alias :put_rest :put # Streams a download to a tempfile, then yields the tempfile to a block. @@ -139,308 +122,59 @@ class Chef streaming_request(create_url(path), headers) {|tmp_file| yield tmp_file } end - def create_url(path) - if path =~ /^(http|https):\/\// - URI.parse(path) - else - URI.parse("#{@url}/#{path}") - end - end - - def sign_requests? - auth_credentials.sign_requests? && @sign_request - end - - # Runs an HTTP request to a JSON API with JSON body. File Download not supported. - def api_request(method, url, headers={}, data=false) - json_body = data ? Chef::JSONCompat.to_json(data) : nil - # Force encoding to binary to fix SSL related EOFErrors - # cf. http://tickets.opscode.com/browse/CHEF-2363 - # http://redmine.ruby-lang.org/issues/5233 - json_body.force_encoding(Encoding::BINARY) if json_body.respond_to?(:force_encoding) - raw_http_request(method, url, headers, json_body) - end - - # Runs an HTTP request to a JSON API with raw body. File Download not supported. - def raw_http_request(method, url, headers, body) - headers = build_headers(method, url, headers, body) - retriable_rest_request(method, url, body, headers) do |rest_request| - begin - response = rest_request.call {|r| r.read_body} - @last_response = response - - Chef::Log.debug("---- HTTP Status and Header Data: ----") - Chef::Log.debug("HTTP #{response.http_version} #{response.code} #{response.msg}") - - response.each do |header, value| - Chef::Log.debug("#{header}: #{value}") - end - Chef::Log.debug("---- End HTTP Status/Header Data ----") - - response_body = decompress_body(response) - - if response.kind_of?(Net::HTTPSuccess) - if response['content-type'] =~ /json/ - Chef::JSONCompat.from_json(response_body.chomp) - else - Chef::Log.warn("Expected JSON response, but got content-type '#{response['content-type']}'") - response_body.to_s - end - elsif response.kind_of?(Net::HTTPNotModified) # Must be tested before Net::HTTPRedirection because it's subclass. - false - elsif redirect_location = redirected_to(response) - if [:GET, :HEAD].include?(method) - follow_redirect {api_request(method, create_url(redirect_location))} - else - raise Exceptions::InvalidRedirect, "#{method} request was redirected from #{url} to #{redirect_location}. Only GET and HEAD support redirects." - end - else - # have to decompress the body before making an exception for it. But the body could be nil. - response.body.replace(response_body) if response.body.respond_to?(:replace) - - if response['content-type'] =~ /json/ - exception = Chef::JSONCompat.from_json(response_body) - msg = "HTTP Request Returned #{response.code} #{response.message}: " - msg << (exception["error"].respond_to?(:join) ? exception["error"].join(", ") : exception["error"].to_s) - Chef::Log.info(msg) - end - response.error! - end - rescue Exception => e - if e.respond_to?(:chef_rest_request=) - e.chef_rest_request = rest_request - end - raise - end - end - end - - def decompress_body(response) - if gzip_disabled? || response.body.nil? - response.body - else - case response[CONTENT_ENCODING] - when GZIP - Chef::Log.debug "decompressing gzip response" - Zlib::Inflate.new(Zlib::MAX_WBITS + 16).inflate(response.body) - when DEFLATE - Chef::Log.debug "decompressing deflate response" - Zlib::Inflate.inflate(response.body) - else - response.body - end - end - end + alias :api_request :request - # Makes a streaming download request. <b>Doesn't speak JSON.</b> - # Streams the response body to a tempfile. If a block is given, it's - # passed to Tempfile.open(), which means that the tempfile will automatically - # be unlinked after the block is executed. - # - # If no block is given, the tempfile is returned, which means it's up to - # you to unlink the tempfile when you're done with it. - def streaming_request(url, headers, &block) - headers = build_headers(:GET, url, headers, nil, true) - retriable_rest_request(:GET, url, nil, headers) do |rest_request| - begin - tempfile = nil - response = rest_request.call do |r| - if block_given? && r.kind_of?(Net::HTTPSuccess) - begin - tempfile = stream_to_tempfile(url, r, &block) - yield tempfile - ensure - tempfile.close! - end - else - tempfile = stream_to_tempfile(url, r) - end - end - @last_response = response - if response.kind_of?(Net::HTTPSuccess) - tempfile - elsif redirect_location = redirected_to(response) - # TODO: test tempfile unlinked when following redirects. - tempfile && tempfile.close! - follow_redirect {streaming_request(create_url(redirect_location), {}, &block)} - else - tempfile && tempfile.close! - response.error! - end - rescue Exception => e - if e.respond_to?(:chef_rest_request=) - e.chef_rest_request = rest_request - end - raise - end - end - end + alias :raw_http_request :send_http_request - def retriable_rest_request(method, url, req_body, headers) - rest_request = Chef::REST::RESTRequest.new(method, url, req_body, headers) + # Deprecated: + # Responsibilities of this method have been split up. The #http_client is + # now responsible for making individual requests, while + # #retrying_http_errors handles error/retry logic. + def retriable_http_request(method, url, req_body, headers) + rest_request = Chef::HTTP::HTTPRequest.new(method, url, req_body, headers) Chef::Log.debug("Sending HTTP Request via #{method} to #{url.host}:#{url.port}#{rest_request.path}") - http_attempts = 0 - - begin - http_attempts += 1 - + retrying_http_errors(url) do yield rest_request - - rescue SocketError, Errno::ETIMEDOUT => e - e.message.replace "Error connecting to #{url} - #{e.message}" - raise e - rescue Errno::ECONNREFUSED - if http_retry_count - http_attempts + 1 > 0 - Chef::Log.error("Connection refused connecting to #{url.host}:#{url.port} for #{rest_request.path}, retry #{http_attempts}/#{http_retry_count}") - sleep(http_retry_delay) - retry - end - raise Errno::ECONNREFUSED, "Connection refused connecting to #{url.host}:#{url.port} for #{rest_request.path}, giving up" - rescue Timeout::Error - if http_retry_count - http_attempts + 1 > 0 - Chef::Log.error("Timeout connecting to #{url.host}:#{url.port} for #{rest_request.path}, retry #{http_attempts}/#{http_retry_count}") - sleep(http_retry_delay) - retry - end - raise Timeout::Error, "Timeout connecting to #{url.host}:#{url.port} for #{rest_request.path}, giving up" - rescue Net::HTTPFatalError => e - if http_retry_count - http_attempts + 1 > 0 - sleep_time = 1 + (2 ** http_attempts) + rand(2 ** http_attempts) - Chef::Log.error("Server returned error for #{url}, retrying #{http_attempts}/#{http_retry_count} in #{sleep_time}s") - sleep(sleep_time) - retry - end - raise end end - def authentication_headers(method, url, json_body=nil) - request_params = {:http_method => method, :path => url.path, :body => json_body, :host => "#{url.host}:#{url.port}"} - request_params[:body] ||= "" - auth_credentials.signature_headers(request_params) - end - - def http_retry_delay - config[:http_retry_delay] - end - - def http_retry_count - config[:http_retry_count] + # Customized streaming behavior; sets the accepted content type to "*/*" + # if not otherwise specified for compatibility purposes + def streaming_request(url, headers, &block) + headers["Accept"] ||= "*/*" + super end - def config - Chef::Config - end + alias :retriable_rest_request :retriable_http_request def follow_redirect - raise Chef::Exceptions::RedirectLimitExceeded if @redirects_followed >= redirect_limit - @redirects_followed += 1 - Chef::Log.debug("Following redirect #{@redirects_followed}/#{redirect_limit}") - if @sign_on_redirect - yield - else - @sign_request = false - yield + unless @sign_on_redirect + @authenticator.sign_request = false end + super ensure - @redirects_followed = 0 - @sign_request = true + @authenticator.sign_request = true end - private + public :create_url - def redirected_to(response) - return nil unless response.kind_of?(Net::HTTPRedirection) - # Net::HTTPNotModified is undesired subclass of Net::HTTPRedirection so test for this - return nil if response.kind_of?(Net::HTTPNotModified) - response['location'] + def http_client(base_url=nil) + base_url ||= url + BasicClient.new(base_url, :ssl_policy => Chef::HTTP::APISSLPolicy) end - def build_headers(method, url, headers={}, json_body=false, raw=false) - headers = @default_headers.merge(headers) - #headers['Accept'] = "application/json" unless raw - headers['Accept'] = "application/json" unless raw - headers["Content-Type"] = 'application/json' if json_body - headers['Content-Length'] = json_body.bytesize.to_s if json_body - headers[RESTRequest::ACCEPT_ENCODING] = RESTRequest::ENCODING_GZIP_DEFLATE unless gzip_disabled? - headers.merge!(authentication_headers(method, url, json_body)) if sign_requests? - headers.merge!(Chef::Config[:custom_http_headers]) if Chef::Config[:custom_http_headers] - headers - end - - def stream_to_tempfile(url, response) - tf = Tempfile.open("chef-rest") - if Chef::Platform.windows? - tf.binmode # required for binary files on Windows platforms - end - Chef::Log.debug("Streaming download from #{url.to_s} to tempfile #{tf.path}") - # Stolen from http://www.ruby-forum.com/topic/166423 - # Kudos to _why! - - inflater = if gzip_disabled? - NoopInflater.new - else - case response[CONTENT_ENCODING] - when GZIP - Chef::Log.debug "decompressing gzip stream" - Zlib::Inflate.new(Zlib::MAX_WBITS + 16) - when DEFLATE - Chef::Log.debug "decompressing inflate stream" - Zlib::Inflate.new - else - NoopInflater.new - end - end + ############################################################################ + # DEPRECATED + ############################################################################ - response.read_body do |chunk| - tf.write(inflater.inflate(chunk)) - end - tf.close - tf - rescue Exception - tf.close! - raise + def decompress_body(body) + @decompressor.decompress_body(body) end - # gzip is disabled using the disable_gzip => true option in the - # constructor. When gzip is disabled, no 'Accept-Encoding' header will be - # set, and the response will not be decompressed, no matter what the - # Content-Encoding header of the response is. The intended use case for - # this is to work around situations where you request +file.tar.gz+, but - # the server responds with a content type of tar and a content encoding of - # gzip, tricking the client into decompressing the response so you end up - # with a tar archive (no gzip) named file.tar.gz - def gzip_disabled? - @disable_gzip - end - - def handle_options(opts) - opts.each do |name, value| - case name.to_s - when 'disable_gzip' - @disable_gzip = value - end - end - end - - def load_signing_key(key_file, raw_key = nil) - if (!!key_file) - @raw_key = IO.read(key_file).strip - elsif (!!raw_key) - @raw_key = raw_key.strip - else - return nil - end - @key = OpenSSL::PKey::RSA.new(@raw_key) - rescue SystemCallError, IOError => e - Chef::Log.warn "Failed to read the private key #{key_file}: #{e.inspect}" - raise Chef::Exceptions::PrivateKeyMissing, "I cannot read #{key_file}, which you told me to use to sign requests!" - rescue OpenSSL::PKey::RSAError - msg = "The file #{key_file} or :raw_key option does not contain a correctly formatted private key.\n" - msg << "The key file should begin with '-----BEGIN RSA PRIVATE KEY-----' and end with '-----END RSA PRIVATE KEY-----'" - raise Chef::Exceptions::InvalidPrivateKey, msg + def authentication_headers(method, url, json_body=nil) + authenticator.authentication_headers(method, url, json_body) end end diff --git a/lib/chef/role.rb b/lib/chef/role.rb index 78bbfadb88..6ad58b816d 100644 --- a/lib/chef/role.rb +++ b/lib/chef/role.rb @@ -233,20 +233,24 @@ class Chef # Load a role from disk - prefers to load the JSON, but will happily load # the raw rb files as well. def self.from_disk(name, force=nil) - js_file = File.join(Chef::Config[:role_path], "#{name}.json") - rb_file = File.join(Chef::Config[:role_path], "#{name}.rb") - - if File.exists?(js_file) || force == "json" - # from_json returns object.class => json_class in the JSON. - Chef::JSONCompat.from_json(IO.read(js_file)) - elsif File.exists?(rb_file) || force == "ruby" - role = Chef::Role.new - role.name(name) - role.from_file(rb_file) - role - else - raise Chef::Exceptions::RoleNotFound, "Role '#{name}' could not be loaded from disk" + paths = Array(Chef::Config[:role_path]) + + paths.each do |p| + js_file = File.join(p, "#{name}.json") + rb_file = File.join(p, "#{name}.rb") + + if File.exists?(js_file) || force == "json" + # from_json returns object.class => json_class in the JSON. + return Chef::JSONCompat.from_json(IO.read(js_file)) + elsif File.exists?(rb_file) || force == "ruby" + role = Chef::Role.new + role.name(name) + role.from_file(rb_file) + return role + end end + + raise Chef::Exceptions::RoleNotFound, "Role '#{name}' could not be loaded from disk" end end diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index 6477431967..4d431116f9 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -204,6 +204,20 @@ class Chef @loaded_attributes["#{cookbook}::#{attribute_file}"] = true end + ## + # Cookbook File Introspection + + def has_template_in_cookbook?(cookbook, template_name) + cookbook = cookbook_collection[cookbook] + cookbook.has_template_for_node?(node, template_name) + end + + def has_cookbook_file_in_cookbook?(cookbook, cb_file_name) + cookbook = cookbook_collection[cookbook] + cookbook.has_cookbook_file_for_node?(node, cb_file_name) + end + + private def loaded_recipe(cookbook, recipe) diff --git a/lib/chef/run_context/cookbook_compiler.rb b/lib/chef/run_context/cookbook_compiler.rb index d1b93f6652..0a05061152 100644 --- a/lib/chef/run_context/cookbook_compiler.rb +++ b/lib/chef/run_context/cookbook_compiler.rb @@ -6,9 +6,9 @@ # 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. @@ -259,7 +259,7 @@ class Chef cookbook_collection[cookbook].segment_filenames(segment).sort end - # Yields the name, as a symbol, of each cookbook depended on by + # Yields the name, as a symbol, of each cookbook depended on by # +cookbook_name+ in lexical sort order. def each_cookbook_dep(cookbook_name, &block) cookbook = cookbook_collection[cookbook_name] diff --git a/lib/chef/run_lock.rb b/lib/chef/run_lock.rb index 50046c2396..972db1a4e1 100644 --- a/lib/chef/run_lock.rb +++ b/lib/chef/run_lock.rb @@ -17,6 +17,9 @@ require 'chef/mixin/create_path' require 'fcntl' +if Chef::Platform.windows? + require 'chef/win32/mutex' +end class Chef @@ -30,20 +33,16 @@ class Chef include Chef::Mixin::CreatePath attr_reader :runlock + attr_reader :mutex attr_reader :runlock_file # Create a new instance of RunLock # === Arguments - # * config::: This will generally be the `Chef::Config`, but any Hash-like - # object with Symbol keys will work. See 'Parameters' section. - # === Parameters/Config - # * :lockfile::: if set, this will be used as the full path to the lockfile. - # * :file_cache_path::: if `:lockfile` is not set, the lock file will be - # named "chef-client-running.pid" and be placed in the directory given by - # `:file_cache_path` - def initialize(config) - @runlock_file = config[:lockfile] || "#{config[:file_cache_path]}/chef-client-running.pid" + # * :lockfile::: the full path to the lockfile. + def initialize(lockfile) + @runlock_file = lockfile @runlock = nil + @mutex = nil end # Acquire the system-wide lock. Will block indefinitely if another process @@ -52,31 +51,73 @@ class Chef # Each call to acquire should have a corresponding call to #release. # # The implementation is based on File#flock (see also: flock(2)). + # + # Either acquire() or test() methods should be called in order to + # get the ownership of run_lock. def acquire + wait unless test + end + + # + # Tests and if successful acquires the system-wide lock. + # Returns true if the lock is acquired, false otherwise. + # + # Either acquire() or test() methods should be called in order to + # get the ownership of run_lock. + def test # ensure the runlock_file path exists create_path(File.dirname(runlock_file)) - @runlock = File.open(runlock_file,'w+') - # if we support FD_CLOEXEC (linux, !windows), then use it. - # NB: ruby-2.0.0-p195 sets FD_CLOEXEC by default, but not ruby-1.8.7/1.9.3 - if Fcntl.const_defined?('F_SETFD') && Fcntl.const_defined?('FD_CLOEXEC') - runlock.fcntl(Fcntl::F_SETFD, runlock.fcntl(Fcntl::F_GETFD, 0) | Fcntl::FD_CLOEXEC) + @runlock = File.open(runlock_file,'a+') + + if Chef::Platform.windows? + acquire_win32_mutex + else + # If we support FD_CLOEXEC, then use it. + # NB: ruby-2.0.0-p195 sets FD_CLOEXEC by default, but not + # ruby-1.8.7/1.9.3 + if Fcntl.const_defined?('F_SETFD') && Fcntl.const_defined?('FD_CLOEXEC') + runlock.fcntl(Fcntl::F_SETFD, runlock.fcntl(Fcntl::F_GETFD, 0) | Fcntl::FD_CLOEXEC) + end + # Flock will return 0 if it can acquire the lock otherwise it + # will return false + if runlock.flock(File::LOCK_NB|File::LOCK_EX) == 0 + true + else + false + end end - unless runlock.flock(File::LOCK_EX|File::LOCK_NB) - # Another chef client running... - runpid = runlock.read.strip.chomp - Chef::Log.warn("Chef client #{runpid} is running, will wait for it to finish and then run.") + end + + # + # Waits until acquiring the system-wide lock. + # + def wait + runpid = runlock.read.strip.chomp + Chef::Log.warn("Chef client #{runpid} is running, will wait for it to finish and then run.") + if Chef::Platform.windows? + mutex.wait + else runlock.flock(File::LOCK_EX) end - # We grabbed the run lock. Save the pid. + end + + def save_pid runlock.truncate(0) runlock.rewind # truncate doesn't reset position to 0. runlock.write(Process.pid.to_s) + # flush the file fsync flushes the system buffers + # in addition to ruby buffers + runlock.fsync end # Release the system-wide lock. def release if runlock - runlock.flock(File::LOCK_UN) + if Chef::Platform.windows? + mutex.release + else + runlock.flock(File::LOCK_UN) + end runlock.close # Don't unlink the pid file, if another chef-client was waiting, it # won't be recreated. Better to leave a "dead" pid file than not have @@ -89,8 +130,20 @@ class Chef def reset @runlock = nil + @mutex = nil end + # Since flock mechanism doesn't exist on windows we are using + # platform Mutex. + # We are creating a "Global" mutex here so that non-admin + # users can not DoS chef-client by creating the same named + # mutex we are using locally. + # Mutex name is case-sensitive contrary to other things in + # windows. "\" is the only invalid character. + def acquire_win32_mutex + @mutex = Chef::ReservedNames::Win32::Mutex.new("Global\\#{runlock_file.gsub(/[\\]/, "/").downcase}") + mutex.test + end end end diff --git a/lib/chef/server_api.rb b/lib/chef/server_api.rb new file mode 100644 index 0000000000..e9e7593dd6 --- /dev/null +++ b/lib/chef/server_api.rb @@ -0,0 +1,41 @@ +# +# Author:: John Keiser (<jkeiser@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/http' +require 'chef/http/authenticator' +require 'chef/http/cookie_manager' +require 'chef/http/decompressor' +require 'chef/http/json_input' +require 'chef/http/json_output' + +class Chef + class ServerAPI < Chef::HTTP + + def initialize(url = Chef::Config[:chef_server_url], options = {}) + options[:client_name] ||= Chef::Config[:node_name] + options[:signing_key_filename] ||= Chef::Config[:client_key] + super(url, options) + end + + use Chef::HTTP::JSONInput + use Chef::HTTP::JSONOutput + use Chef::HTTP::CookieManager + use Chef::HTTP::Decompressor + use Chef::HTTP::Authenticator + end +end
\ No newline at end of file diff --git a/lib/chef/shell.rb b/lib/chef/shell.rb index 4c86f96616..0788962e62 100644 --- a/lib/chef/shell.rb +++ b/lib/chef/shell.rb @@ -24,6 +24,7 @@ require 'chef' require 'chef/version' require 'chef/client' require 'chef/config' +require 'chef/config_fetcher' require 'chef/shell/shell_session' require 'chef/shell/ext' @@ -151,26 +152,9 @@ module Shell end def self.parse_json - # HACK: copied verbatim from chef/application/client, because it's not - # reusable as written there :( if Chef::Config[:json_attribs] - begin - json_io = open(Chef::Config[:json_attribs]) - rescue SocketError => error - fatal!("I cannot connect to #{Chef::Config[:json_attribs]}", 2) - rescue Errno::ENOENT => error - fatal!("I cannot find #{Chef::Config[:json_attribs]}", 2) - rescue Errno::EACCES => error - fatal!("Permissions are incorrect on #{Chef::Config[:json_attribs]}. Please chmod a+r #{Chef::Config[:json_attribs]}", 2) - rescue Exception => error - fatal!("Got an unexpected error reading #{Chef::Config[:json_attribs]}: #{error.message}", 2) - end - - begin - @json_attribs = Chef::JSONCompat.from_json(json_io.read) - rescue JSON::ParserError => error - fatal!("Could not parse the provided JSON file (#{Chef::Config[:json_attribs]})!: " + error.message, 2) - end + config_fetcher = Chef::ConfigFetcher.new(Chef::Config[:json_attribs]) + @json_attribs = config_fetcher.fetch_json end end diff --git a/lib/chef/shell/shell_session.rb b/lib/chef/shell/shell_session.rb index cf147e778d..2f4d9375eb 100644 --- a/lib/chef/shell/shell_session.rb +++ b/lib/chef/shell/shell_session.rb @@ -173,7 +173,7 @@ module Shell cl = Chef::CookbookLoader.new(Chef::Config[:cookbook_path]) cl.load_cookbooks cookbook_collection = Chef::CookbookCollection.new(cl) - @run_context = Chef::RunContext.new(node, cookbook_collection, @events) + @run_context = Chef::RunContext.new(node, cookbook_collection, @events) @run_context.load(Chef::RunList::RunListExpansionFromDisk.new("_default", [])) @run_status.run_context = run_context end diff --git a/lib/chef/streaming_cookbook_uploader.rb b/lib/chef/streaming_cookbook_uploader.rb index df90e0003d..9e638f6367 100644 --- a/lib/chef/streaming_cookbook_uploader.rb +++ b/lib/chef/streaming_cookbook_uploader.rb @@ -15,22 +15,23 @@ class Chef class StreamingCookbookUploader DefaultHeaders = { 'accept' => 'application/json', 'x-chef-version' => ::Chef::VERSION } - + class << self def post(to_url, user_id, secret_key_filename, params = {}, headers = {}) make_request(:post, to_url, user_id, secret_key_filename, params, headers) end - + def put(to_url, user_id, secret_key_filename, params = {}, headers = {}) make_request(:put, to_url, user_id, secret_key_filename, params, headers) end - + def make_request(http_verb, to_url, user_id, secret_key_filename, params = {}, headers = {}) + Chef::Log.warn('[DEPRECATED] StreamingCookbookUploader class is deprecated. It will be removed in Chef 12. Please use CookbookSiteStreamingUploader instead.') boundary = '----RubyMultipartClient' + rand(1000000).to_s + 'ZZZZZ' parts = [] content_file = nil - + timestamp = Time.now.utc.iso8601 secret_key = OpenSSL::PKey::RSA.new(File.read(secret_key_filename)) @@ -53,31 +54,31 @@ class Chef end parts << StringPart.new("--" + boundary + "--\r\n") end - + body_stream = MultipartStream.new(parts) - + timestamp = Time.now.utc.iso8601 - + url = URI.parse(to_url) - + Chef::Log.logger.debug("Signing: method: #{http_verb}, path: #{url.path}, file: #{content_file}, User-id: #{user_id}, Timestamp: #{timestamp}") - + # We use the body for signing the request if the file parameter - # wasn't a valid file or wasn't included. Extract the body (with + # wasn't a valid file or wasn't included. Extract the body (with # multi-part delimiters intact) to sign the request. # TODO: tim: 2009-12-28: It'd be nice to remove this special case, and # always hash the entire request body. In the file case it would just be # expanded multipart text - the entire body of the POST. content_body = parts.inject("") { |result,part| result + part.read(0, part.size) } content_file.rewind if content_file # we consumed the file for the above operation, so rewind it. - + signing_options = { :http_method=>http_verb, :path=>url.path, :user_id=>user_id, :timestamp=>timestamp} (content_file && signing_options[:file] = content_file) || (signing_options[:body] = (content_body || "")) - + headers.merge!(Mixlib::Authentication::SignedHeaderAuth.signing_object(signing_options).sign(secret_key)) content_file.rewind if content_file @@ -90,11 +91,11 @@ class Chef Net::HTTP::Put.new(url.path, headers) when :post Net::HTTP::Post.new(url.path, headers) - end + end req.content_length = body_stream.size req.content_type = 'multipart/form-data; boundary=' + boundary unless parts.empty? req.body_stream = body_stream - + http = Net::HTTP.new(url.host, url.port) if url.scheme == "https" http.use_ssl = true @@ -107,30 +108,31 @@ class Chef # TODO: stop the following madness! class << res alias :to_s :body - + # BUGBUG this makes the response compatible with what respsonse_steps expects to test headers (response.headers[] -> response[]) def headers self end - + def status code.to_i end end res end - + end class StreamPart def initialize(stream, size) + Chef::Log.warn('[DEPRECATED] StreamingCookbookUploader::StreamPart class is deprecated. It will be removed in Chef 12. Please use CookbookSiteStreamingUploader::StreamPart instead.') @stream, @size = stream, size end - + def size @size end - + # read the specified amount from the stream def read(offset, how_much) @stream.read(how_much) @@ -139,9 +141,10 @@ class Chef class StringPart def initialize(str) + Chef::Log.warn('[DEPRECATED] StreamingCookbookUploader::StringPart class is deprecated. It will be removed in Chef 12. Please use CookbookSiteStreamingUploader::StringPart instead.') @str = str end - + def size @str.length end @@ -154,30 +157,31 @@ class Chef class MultipartStream def initialize(parts) + Chef::Log.warn('[DEPRECATED] StreamingCookbookUploader::MultipartStream class is deprecated. It will be removed in Chef 12. Please use CookbookSiteStreamingUploader::MultipartStream instead.') @parts = parts @part_no = 0 @part_offset = 0 end - + def size @parts.inject(0) {|size, part| size + part.size} end - + def read(how_much) return nil if @part_no >= @parts.size how_much_current_part = @parts[@part_no].size - @part_offset - + how_much_current_part = if how_much_current_part > how_much how_much else how_much_current_part end - + how_much_next_part = how_much - how_much_current_part current_part = @parts[@part_no].read(@part_offset, how_much_current_part) - + # recurse into the next part if the current one was not large enough if how_much_next_part > 0 @part_no += 1 @@ -194,7 +198,7 @@ class Chef end end end - + end diff --git a/lib/chef/tasks/chef_repo.rake b/lib/chef/tasks/chef_repo.rake index 6f839a486f..704557ebb3 100644 --- a/lib/chef/tasks/chef_repo.rake +++ b/lib/chef/tasks/chef_repo.rake @@ -6,9 +6,9 @@ # 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. @@ -51,7 +51,7 @@ task :update do pull = true if line =~ /\[remote "origin"\]/ end if pull - sh %{git pull} + sh %{git pull} else puts "* Skipping git pull, no origin specified" end @@ -86,14 +86,14 @@ end def create_cookbook(dir) raise "Must provide a COOKBOOK=" unless ENV["COOKBOOK"] puts "** Creating cookbook #{ENV["COOKBOOK"]}" - sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "attributes")}" - sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "recipes")}" - sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "definitions")}" - sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "libraries")}" - sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "resources")}" - sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "providers")}" - sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "files", "default")}" - sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "templates", "default")}" + sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "attributes")}" + sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "recipes")}" + sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "definitions")}" + sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "libraries")}" + sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "resources")}" + sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "providers")}" + sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "files", "default")}" + sh "mkdir -p #{File.join(dir, ENV["COOKBOOK"], "templates", "default")}" unless File.exists?(File.join(dir, ENV["COOKBOOK"], "recipes", "default.rb")) open(File.join(dir, ENV["COOKBOOK"], "recipes", "default.rb"), "w") do |file| file.puts <<-EOH @@ -110,9 +110,9 @@ EOH # 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. @@ -156,7 +156,7 @@ end def create_metadata(dir) raise "Must provide a COOKBOOK=" unless ENV["COOKBOOK"] puts "** Creating metadata for cookbook: #{ENV["COOKBOOK"]}" - + case NEW_COOKBOOK_LICENSE when :apachev2 license = "Apache 2.0" @@ -188,8 +188,8 @@ task :ssl_cert do fqdn =~ /^(.+?)\.(.+)$/ hostname = $1 domain = $2 - keyfile = fqdn.gsub("*", "wildcard") raise "Must provide FQDN!" unless fqdn && hostname && domain + keyfile = fqdn.gsub("*", "wildcard") puts "** Creating self signed SSL Certificate for #{fqdn}" sh("(cd #{CADIR} && openssl genrsa 2048 > #{keyfile}.key)") sh("(cd #{CADIR} && chmod 644 #{keyfile}.key)") @@ -288,7 +288,7 @@ namespace :databag do end end else - puts "ERROR: Could not find any databags, skipping it" + puts "ERROR: Could not find any databags, skipping it" end end @@ -327,7 +327,7 @@ EOH end else puts "ERROR: Could not find your databag (#{databag}), skipping it" - end + end end end diff --git a/lib/chef/util/backup.rb b/lib/chef/util/backup.rb index 95c85d9751..43e3434050 100644 --- a/lib/chef/util/backup.rb +++ b/lib/chef/util/backup.rb @@ -47,7 +47,8 @@ class Chef def backup_filename @backup_filename ||= begin time = Time.now - savetime = time.strftime("%Y%m%d%H%M%S") + nanoseconds = sprintf("%6f", time.to_f).split('.')[1] + savetime = time.strftime("%Y%m%d%H%M%S.#{nanoseconds}") backup_filename = "#{path}.chef-#{savetime}" backup_filename = backup_filename.sub(/^([A-Za-z]:)/, "") #strip drive letter on Windows end diff --git a/lib/chef/util/diff.rb b/lib/chef/util/diff.rb index 6f76a2fabd..7bce52d874 100644 --- a/lib/chef/util/diff.rb +++ b/lib/chef/util/diff.rb @@ -14,14 +14,38 @@ # See the License for the specific language governing permissions and # limitations under the License. # - -require 'chef/mixin/shell_out' +# Some portions of this file are derived from material in the diff-lcs +# project licensed under the terms of the MIT license, provided below. +# +# Copyright:: Copyright (c) 2004-2013 Austin Ziegler +# License:: MIT +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of this Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OF OTHER DEALINGS IN THE +# SOFTWARE. + +require 'diff/lcs' +require 'diff/lcs/hunk' class Chef class Util class Diff - include Chef::Mixin::ShellOut - # @todo: to_a, to_s, to_json, inspect defs, accessors for @diff and @error # @todo: move coercion to UTF-8 into to_json # @todo: replace shellout to diff -u with diff-lcs gem @@ -58,6 +82,43 @@ class Chef end end end + + # produces a unified-output-format diff with 3 lines of context + # ChefFS uses udiff() directly + def udiff(old_file, new_file) + diff_str = "" + file_length_difference = 0 + + old_data = IO.readlines(old_file).map { |e| e.chomp } + new_data = IO.readlines(new_file).map { |e| e.chomp } + diff_data = ::Diff::LCS.diff(old_data, new_data) + + return diff_str if old_data.empty? && new_data.empty? + return "No differences encountered\n" if diff_data.empty? + + # write diff header (standard unified format) + ft = File.stat(old_file).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z') + diff_str << "--- #{old_file}\t#{ft}\n" + ft = File.stat(new_file).mtime.localtime.strftime('%Y-%m-%d %H:%M:%S.%N %z') + diff_str << "+++ #{new_file}\t#{ft}\n" + + # loop over diff hunks. if a hunk overlaps with the last hunk, + # join them. otherwise, print out the old one. + old_hunk = hunk = nil + diff_data.each do |piece| + begin + hunk = ::Diff::LCS::Hunk.new(old_data, new_data, piece, 3, file_length_difference) + file_length_difference = hunk.file_length_difference + next unless old_hunk + next if hunk.merge(old_hunk) + diff_str << old_hunk.diff(:unified) << "\n" + ensure + old_hunk = hunk + end + end + diff_str << old_hunk.diff(:unified) << "\n" + return diff_str + end private @@ -78,13 +139,8 @@ class Chef return "(new content is binary, diff output suppressed)" if is_binary?(new_file) begin - # -u: Unified diff format - # LC_ALL: in ruby 1.9 we want to set nil which is a magic option to mixlib-shellout to - # pass through the LC_ALL locale. in ruby 1.8 we force to 7-bit 'C' locale - # (which is the mixlib-shellout default for all rubies all the time). Chef::Log.debug("running: diff -u #{old_file} #{new_file}") - locale = ( Object.const_defined? :Encoding ) ? nil : 'C' - result = shell_out("diff -u #{old_file} #{new_file}", :env => {'LC_ALL' => locale}) + diff_str = udiff(old_file, new_file) rescue Exception => e # Should *not* receive this, but in some circumstances it seems that @@ -92,34 +148,14 @@ class Chef return "Could not determine diff. Error: #{e.message}" end - # diff will set a non-zero return code even when there's - # valid stdout results, if it encounters something unexpected - # So as long as we have output, we'll show it. - # - # Also on some platforms (Solaris) diff outputs a single line - # when there are no differences found. Look for this line - # before analyzing diff output. - if !result.stdout.empty? && result.stdout != "No differences encountered\n" - if result.stdout.length > diff_output_threshold + if !diff_str.empty? && diff_str != "No differences encountered\n" + if diff_str.length > diff_output_threshold return "(long diff of over #{diff_output_threshold} characters, diff output suppressed)" else - diff_str = result.stdout - if Object.const_defined? :Encoding # ruby >= 1.9 - if ( diff_str.encoding == Encoding::ASCII_8BIT && - diff_str.encoding != Encoding.default_external && - RUBY_VERSION.to_f < 2.0 ) - # @todo mixlib-shellout under ruby 1.9 hands back an ASCII-8BIT encoded string, which needs to - # be fixed to the default external encoding -- this should be moved into mixlib-shellout - diff_str = diff_str.force_encoding(Encoding.default_external) - end - diff_str.encode!('UTF-8', :invalid => :replace, :undef => :replace, :replace => '?') - end + diff_str = encode_diff_for_json(diff_str) @diff = diff_str.split("\n") - @diff.delete("\\ No newline at end of file") return "(diff available)" end - elsif !result.stderr.empty? - return "Could not determine diff. Error: #{result.stderr}" else return "(no diff)" end @@ -139,6 +175,13 @@ class Chef end end + def encode_diff_for_json(diff_str) + if Object.const_defined? :Encoding + diff_str.encode!('UTF-8', :invalid => :replace, :undef => :replace, :replace => '?') + end + return diff_str + end + end end end diff --git a/lib/chef/util/windows.rb b/lib/chef/util/windows.rb index cba2c2a1b7..777fe4adbb 100644 --- a/lib/chef/util/windows.rb +++ b/lib/chef/util/windows.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/util/windows/net_group.rb b/lib/chef/util/windows/net_group.rb index 9da0dc6557..817e47efa8 100644 --- a/lib/chef/util/windows/net_group.rb +++ b/lib/chef/util/windows/net_group.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/util/windows/net_use.rb b/lib/chef/util/windows/net_use.rb index 1979e095bd..37efc02fcc 100644 --- a/lib/chef/util/windows/net_use.rb +++ b/lib/chef/util/windows/net_use.rb @@ -6,9 +6,9 @@ # 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. diff --git a/lib/chef/util/windows/net_user.rb b/lib/chef/util/windows/net_user.rb index eb68f6cebc..5cca348c8e 100644 --- a/lib/chef/util/windows/net_user.rb +++ b/lib/chef/util/windows/net_user.rb @@ -6,9 +6,9 @@ # 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. @@ -198,7 +198,7 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows def enable_account user_modify do |user| user[:flags] &= ~UF_ACCOUNTDISABLE - #This does not set the password to nil. It (for some reason) means to ignore updating the field. + #This does not set the password to nil. It (for some reason) means to ignore updating the field. #See similar behavior for the logon_hours field documented at #http://msdn.microsoft.com/en-us/library/windows/desktop/aa371338%28v=vs.85%29.aspx user[:password] = nil diff --git a/lib/chef/util/windows/volume.rb b/lib/chef/util/windows/volume.rb index dff082e929..08c3a53793 100644 --- a/lib/chef/util/windows/volume.rb +++ b/lib/chef/util/windows/volume.rb @@ -6,9 +6,9 @@ # 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. @@ -35,7 +35,7 @@ class Chef::Util::Windows::Volume < Chef::Util::Windows name += "\\" unless name =~ /\\$/ #trailing slash required @name = name end - + def device buffer = 0.chr * 256 if GetVolumeNameForVolumeMountPoint(@name, buffer, buffer.size) diff --git a/lib/chef/version.rb b/lib/chef/version.rb index 70a22f7d27..259c267035 100644 --- a/lib/chef/version.rb +++ b/lib/chef/version.rb @@ -6,9 +6,9 @@ # 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. @@ -17,7 +17,7 @@ class Chef CHEF_ROOT = File.dirname(File.expand_path(File.dirname(__FILE__))) - VERSION = '11.6.0.hotfix.1' + VERSION = '11.8.0.alpha.0' end # NOTE: the Chef::Version class is defined in version_class.rb diff --git a/lib/chef/win32/api/file.rb b/lib/chef/win32/api/file.rb index afa746efce..7a8dafd8b5 100644 --- a/lib/chef/win32/api/file.rb +++ b/lib/chef/win32/api/file.rb @@ -474,7 +474,7 @@ BOOL WINAPI DeviceIoControl( # Workaround for CHEF-4419: # Make sure paths starting with "/" has a drive letter # assigned from the current working diretory. - # Note: In chef 11.8 and beyond this issue will be fixed with a + # Note: With CHEF-4427 this issue will be fixed with a # broader fix to map all the paths starting with "/" to # SYSTEM_DRIVE on windows. path = ::File.expand_path(path) if path.start_with? "/" diff --git a/lib/chef/win32/api/synchronization.rb b/lib/chef/win32/api/synchronization.rb new file mode 100644 index 0000000000..9c148d7e2b --- /dev/null +++ b/lib/chef/win32/api/synchronization.rb @@ -0,0 +1,89 @@ +# +# Author:: Serdar Sutay (<serdar@opscode.com>) +# Copyright:: Copyright 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 'chef/win32/api' + +class Chef + module ReservedNames::Win32 + module API + module Synchronization + extend Chef::ReservedNames::Win32::API + + ffi_lib 'kernel32' + + # Constant synchronization functions use to indicate wait + # forever. + INFINITE = 0xFFFFFFFF + + # Return codes + # http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx + WAIT_FAILED = 0xFFFFFFFF + WAIT_TIMEOUT = 0x00000102 + WAIT_OBJECT_0 = 0x00000000 + WAIT_ABANDONED = 0x00000080 + + # Security and access rights for synchronization objects + # http://msdn.microsoft.com/en-us/library/windows/desktop/ms686670(v=vs.85).aspx + DELETE = 0x00010000 + READ_CONTROL = 0x00020000 + SYNCHRONIZE = 0x00100000 + WRITE_DAC = 0x00040000 + WRITE_OWNER = 0x00080000 + + # Mutex specific rights + MUTEX_ALL_ACCESS = 0x001F0001 + MUTEX_MODIFY_STATE = 0x00000001 + +=begin +HANDLE WINAPI CreateMutex( + _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes, + _In_ BOOL bInitialOwner, + _In_opt_ LPCTSTR lpName +); +=end + safe_attach_function :CreateMutexW, [ :LPSECURITY_ATTRIBUTES, :BOOL, :LPCTSTR ], :HANDLE + safe_attach_function :CreateMutexA, [ :LPSECURITY_ATTRIBUTES, :BOOL, :LPCTSTR ], :HANDLE + +=begin +DWORD WINAPI WaitForSingleObject( + _In_ HANDLE hHandle, + _In_ DWORD dwMilliseconds +); +=end + safe_attach_function :WaitForSingleObject, [ :HANDLE, :DWORD ], :DWORD + +=begin +BOOL WINAPI ReleaseMutex( + _In_ HANDLE hMutex +); +=end + safe_attach_function :ReleaseMutex, [ :HANDLE ], :BOOL + +=begin +HANDLE WINAPI OpenMutex( + _In_ DWORD dwDesiredAccess, + _In_ BOOL bInheritHandle, + _In_ LPCTSTR lpName +); +=end + safe_attach_function :OpenMutexW, [ :DWORD, :BOOL, :LPCTSTR ], :HANDLE + safe_attach_function :OpenMutexA, [ :DWORD, :BOOL, :LPCTSTR ], :HANDLE + end + end + end +end diff --git a/lib/chef/win32/handle.rb b/lib/chef/win32/handle.rb index 3e92703db9..21a8fdf339 100644 --- a/lib/chef/win32/handle.rb +++ b/lib/chef/win32/handle.rb @@ -29,7 +29,7 @@ class Chef # 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)) diff --git a/lib/chef/win32/mutex.rb b/lib/chef/win32/mutex.rb new file mode 100644 index 0000000000..b0a9ba210e --- /dev/null +++ b/lib/chef/win32/mutex.rb @@ -0,0 +1,94 @@ +# +# Author:: Serdar Sutay (<serdar@opscode.com>) +# Copyright:: Copyright 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/win32/api/synchronization' + +class Chef + module ReservedNames::Win32 + class Mutex + include Chef::ReservedNames::Win32::API::Synchronization + extend Chef::ReservedNames::Win32::API::Synchronization + + def initialize(name) + @name = name + # First check if there exists a mutex in the system with the + # given name. + + # In the initial creation of the mutex initial_owner is set to + # false so that mutex will not be acquired until someone calls + # acquire. + # In order to call "*W" windows apis, strings needs to be + # encoded as wide strings. + @handle = CreateMutexW(nil, false, name.to_wstring) + + # Fail early if we can't get a handle to the named mutex + if @handle == 0 + Chef::Log.error("Failed to create system mutex with name'#{name}'") + Chef::ReservedNames::Win32::Error.raise! + end + end + + attr_reader :handle + attr_reader :name + + ##################################################### + # Attempts to grab the mutex. + # Returns true if the mutex is grabbed or if it's already + # owned; false otherwise. + def test + WaitForSingleObject(handle, 0) == WAIT_OBJECT_0 + end + + ##################################################### + # Attempts to grab the mutex and waits until it is acquired. + def wait + wait_result = WaitForSingleObject(handle, INFINITE) + case wait_result + when WAIT_ABANDONED + # Previous owner of the mutex died before it can release the + # mutex. Log a warning and continue. + Chef::Log.debug "Existing owner of the mutex exited prematurely." + when WAIT_OBJECT_0 + # Mutex is successfully acquired. + else + Chef::Log.error("Failed to acquire system mutex '#{name}'. Return code: #{wait_result}") + Chef::ReservedNames::Win32::Error.raise! + end + end + + ##################################################### + # Releaes the mutex + def release + # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685066(v=vs.85).aspx + # Note that release method needs to be called more than once + # if mutex is acquired more than once. + unless ReleaseMutex(handle) + # Don't fail things in here if we can't release the mutex. + # Because it will be automatically released when the owner + # of the process goes away and this class is only being used + # to synchronize chef-clients runs on a node. + Chef::Log.error("Can not release mutex '#{name}'. This might cause issues \ +if the mutex is attempted to be acquired by other threads.") + Chef::ReservedNames::Win32::Error.raise! + end + end + end + end +end + + diff --git a/lib/chef/win32/security/ace.rb b/lib/chef/win32/security/ace.rb index efd44b1c85..3aeae35532 100644 --- a/lib/chef/win32/security/ace.rb +++ b/lib/chef/win32/security/ace.rb @@ -122,4 +122,4 @@ class Chef end end end -end
\ No newline at end of file +end diff --git a/lib/chef/win32/security/sid.rb b/lib/chef/win32/security/sid.rb index 7ca21eee79..e1b20224bb 100644 --- a/lib/chef/win32/security/sid.rb +++ b/lib/chef/win32/security/sid.rb @@ -196,4 +196,4 @@ class Chef end end end -end
\ No newline at end of file +end diff --git a/lib/chef/win32/version.rb b/lib/chef/win32/version.rb index c8c923a6f2..62f817503e 100644 --- a/lib/chef/win32/version.rb +++ b/lib/chef/win32/version.rb @@ -30,14 +30,16 @@ class Chef # http://msdn.microsoft.com/en-us/library/ms724358(v=vs.85).aspx private - + def self.get_system_metrics(n_index) Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(n_index) end public - + WIN_VERSIONS = { + "Windows 8.1" => {:major => 6, :minor => 3, :callable => lambda{ @product_type == VER_NT_WORKSTATION }}, + "Windows Server 2012 R2" => {:major => 6, :minor => 3, :callable => lambda{ @product_type != VER_NT_WORKSTATION }}, "Windows 8" => {:major => 6, :minor => 2, :callable => lambda{ @product_type == VER_NT_WORKSTATION }}, "Windows Server 2012" => {:major => 6, :minor => 2, :callable => lambda{ @product_type != VER_NT_WORKSTATION }}, "Windows 7" => {:major => 6, :minor => 1, :callable => lambda{ @product_type == VER_NT_WORKSTATION }}, @@ -68,7 +70,7 @@ class Chef # The get_product_info API is not supported on Win2k3, # use an alternative to identify datacenter skus @sku = get_datacenter_product_info_windows_server_2003(ver_info) - end + end end marketing_names = Array.new diff --git a/spec/data/bootstrap/no_proxy.erb b/spec/data/bootstrap/no_proxy.erb new file mode 100644 index 0000000000..6945704386 --- /dev/null +++ b/spec/data/bootstrap/no_proxy.erb @@ -0,0 +1,2 @@ +bash -c ' +<%= config_content %>' diff --git a/spec/data/cookbooks/openldap/metadata.rb b/spec/data/cookbooks/openldap/metadata.rb new file mode 100644 index 0000000000..ab0dface9d --- /dev/null +++ b/spec/data/cookbooks/openldap/metadata.rb @@ -0,0 +1,8 @@ +name "openldap" +maintainer "Opscode, Inc." +maintainer_email "cookbooks@opscode.com" +license "Apache 2.0" +description "Installs and configures all aspects of openldap using Debian style symlinks with helper definitions" +long_description "The long description for the openldap cookbook from metadata.rb" +version "8.9.10" +recipe "openldap", "Main Open LDAP configuration" diff --git a/spec/data/cookbooks/preseed/files/default/preseed-template.seed b/spec/data/cookbooks/preseed/files/default/preseed-template.seed new file mode 100644 index 0000000000..011bc40f1b --- /dev/null +++ b/spec/data/cookbooks/preseed/files/default/preseed-template.seed @@ -0,0 +1,4 @@ +# This file should never be executed by the preseeding tests +# This is here to verify that templates are preferred over cookbook_files when +# preseeding packages. +chef-integration-test chef-integration-test/sample-var string "WRONG-cookbook file used instead of template!" diff --git a/spec/data/trusted_certs/example.crt b/spec/data/trusted_certs/example.crt new file mode 100644 index 0000000000..832aebe2ec --- /dev/null +++ b/spec/data/trusted_certs/example.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDkjCCAnoCCQDihI8kxGYTFTANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMRAwDgYDVQQKEwdZb3VD +b3JwMRMwEQYDVQQLEwpPcGVyYXRpb25zMRYwFAYDVQQDEw1leGFtcGxlLmxvY2Fs +MR0wGwYJKoZIhvcNAQkBFg5tZUBleGFtcGxlLmNvbTAeFw0xMzEwMTcxODAxMzVa +Fw0yMzEwMTUxODAxMzVaMIGKMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAO +BgNVBAcTB1NlYXR0bGUxEDAOBgNVBAoTB1lvdUNvcnAxEzARBgNVBAsTCk9wZXJh +dGlvbnMxFjAUBgNVBAMTDWV4YW1wbGUubG9jYWwxHTAbBgkqhkiG9w0BCQEWDm1l +QGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyKBo +U+Bdni0xZK/NCzdLdi2X+TyW5eahbYMx+r1GDcVqCICvrthBCVLVFsQ8rvOHwTPi +AxQJGxb9TLSXRgXQSlH6FLjIUceuOtpan3qYVJ1v7AxY4DgNvYBpbtJz5MQedJnT +g2F+rXzkwaD6CWBqWHeGU0oP3r7bq1AMD6XEsK2w2/zHtG7TEnL45ARv1PsyrU5M +ZAW/XyoMyq1k2Lpv7YR5kAvTq1+4RSt/it2RFE7R0AVbaQ0MeAnllfySiHHHlaOT +FVd/qPSiGISxsUmmzA3Z08+0sfJwkrnJXbLscCBYndd7gMGgtczGjJtul0Ch3GFa +/Pn5McjwF272+usJ1wIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQCzPePWifWNECsG +nL8on1AtFMkczE1/pdRS4YUl/Tc926MpezptSja8rL31+4Bom37/wYPG7HygtAQl +R4FHpAtuqJKPOfjUmDNsIXRFnytrnflTpctDu/Nbj4PDCy01k/sTDUQt+s+lEBL8 +M8ArmfLZ8PCfAwnXmJQ5rggDFKqegjt6z1RsSglbMiASE7+KkpBnzaqH6fET6IQz +WgAjv6WdRfwgfJjOTSX4XMpCSet9KaWmXExKrxiVng2Uu6E+ShVAyKaGMuc1B7VA +oxnnVaVapFv5lOWucQr4KkC7EgaUZnyt8duOc8+Yvd+y3Xd2dcHUnmegRxly4jRV +/lXbFAUb +-----END CERTIFICATE----- diff --git a/spec/data/trusted_certs/intermediate.pem b/spec/data/trusted_certs/intermediate.pem new file mode 100644 index 0000000000..78148b0fcf --- /dev/null +++ b/spec/data/trusted_certs/intermediate.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEjzCCA3egAwIBAgIQBp4dt3/PHfupevXlyaJANzANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaMEgxCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxIjAgBgNVBAMTGURpZ2lDZXJ0IFNlY3Vy +ZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7V+Qh +qdWbYDd+jqFhf4HiGsJ1ZNmRUAvkNkQkbjDSm3on+sJqrmpwCTi5IArIZRBKiKwx +8tyS8mOhXYBjWYCSIxzm73ZKUDXJ2HE4ue3w5kKu0zgmeTD5IpTG26Y/QXiQ2N5c +fml9+JAVOtChoL76srIZodgr0c6/a91Jq6OS/rWryME+7gEA2KlEuEJziMNh9atK +gygK0tRJ+mqxzd9XLJTl4sqDX7e6YlwvaKXwwLn9K9HpH9gaYhW9/z2m98vv5ttl +LyU47PvmIGZYljQZ0hXOIdMkzNkUb9j+Vcfnb7YPGoxJvinyulqagSY3JG/XSBJs +Lln1nBi72fZo4t9FAgMBAAGjggFaMIIBVjASBgNVHRMBAf8ECDAGAQH/AgEAMA4G +A1UdDwEB/wQEAwIBhjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6 +Ly9vY3NwLmRpZ2ljZXJ0LmNvbTB7BgNVHR8EdDByMDegNaAzhjFodHRwOi8vY3Js +My5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3JsMDegNaAzhjFo +dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3Js +MD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5k +aWdpY2VydC5jb20vQ1BTMB0GA1UdDgQWBBSQcds363PI79zVHhK2NLorWqCmkjAf +BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTANBgkqhkiG9w0BAQUFAAOC +AQEAMM7RlVEArgYLoQ4CwBestn+PIPZAdXQczHixpE/q9NDEnaLegQcmH0CIUfAf +z7dMQJnQ9DxxmHOIlywZ126Ej6QfnFog41FcsMWemWpPyGn3EP9OrRnZyVizM64M +2ZYpnnGycGOjtpkWQh1l8/egHn3F1GUUsmKE1GxcCAzYbJMrtHZZitF//wPYwl24 +LyLWOPD2nGt9RuuZdPfrSg6ppgTre87wXGuYMVqYQOtpxAX0IKjKCDplbDgV9Vws +slXkLGtB8L5cRspKKaBIXiDSRf8F3jSvcEuBOeLKB1d8tjHcISnivpcOd5AUUUDh +v+PMGxmcJcqnBrJT3yOyzxIZow== +-----END CERTIFICATE----- diff --git a/spec/data/trusted_certs/opscode.pem b/spec/data/trusted_certs/opscode.pem new file mode 100644 index 0000000000..d7d211c9da --- /dev/null +++ b/spec/data/trusted_certs/opscode.pem @@ -0,0 +1,38 @@ +-----BEGIN CERTIFICATE----- +MIIGqjCCBZKgAwIBAgIQCJlQhNSTz1z3zHZb972KvDANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSIwIAYDVQQDExlE +aWdpQ2VydCBTZWN1cmUgU2VydmVyIENBMB4XDTEzMDQxMjAwMDAwMFoXDTE0MDYx +NjEyMDAwMFowYzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO +BgNVBAcTB1NlYXR0bGUxFTATBgNVBAoTDE9wc2NvZGUsIEluYzEWMBQGA1UEAwwN +Ki5vcHNjb2RlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+U +HLAzObPRlmchlkJ2JFeReJRPXj5F27HuX8SXT+5WhVGunQf1swjASJ0utk1x9wGT +f9tnF8fYiwJIqWJopaPiwzNw1cD6CnIfhM3z4T3EzLAWWu2ZhfuaQk9Z6jhItkm7 +upO4CsFq1xw7IjqOq09PCAklYC/Y/8Qq5Qj8VoTp0ldVv6hbqTNkezhWcKU/07si +jAX1O+DYN6dlVNezfl4Xt5ccsu8Mp0s92IMVYLgY6bpb1b91ez9+XBE1v7zjaR0V +EP7Ix9av/pXjqMqHgjlsg46UpLa30f4FEi2xmXpCBpOP94rCrT7g+u8UlIrJ/QK/ +/lHyKBpCm0R9ftDbppsCAwEAAaOCA3MwggNvMB8GA1UdIwQYMBaAFJBx2zfrc8jv +3NUeErY0uitaoKaSMB0GA1UdDgQWBBTdhCU7MvQblxtWHlfHG4jPUTuh5DBLBgNV +HREERDBCgg0qLm9wc2NvZGUuY29tggtvcHNjb2RlLmNvbYIQY29ycC5vcHNjb2Rl +LmNvbYISKi5jb3JwLm9wc2NvZGUuY29tMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE +FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwYQYDVR0fBFowWDAqoCigJoYkaHR0cDov +L2NybDMuZGlnaWNlcnQuY29tL3NzY2EtZzEuY3JsMCqgKKAmhiRodHRwOi8vY3Js +NC5kaWdpY2VydC5jb20vc3NjYS1nMS5jcmwwggHEBgNVHSAEggG7MIIBtzCCAbMG +CWCGSAGG/WwBATCCAaQwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQu +Y29tL3NzbC1jcHMtcmVwb3NpdG9yeS5odG0wggFkBggrBgEFBQcCAjCCAVYeggFS +AEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABpAGYAaQBj +AGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBu +AGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQ +AFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQByAHQAeQAg +AEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0ACAAbABp +AGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwByAHAAbwBy +AGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBl +AC4weAYIKwYBBQUHAQEEbDBqMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp +Y2VydC5jb20wQgYIKwYBBQUHMAKGNmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv +bS9EaWdpQ2VydFNlY3VyZVNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqG +SIb3DQEBBQUAA4IBAQCNk1+7l+VlAZrKov7ugP7WuKS7IEUZRk8CVAFPtIrp+jFB +6W0ta1qMpYyItp5enTBCGOkTfPly06hZnFRQw3ZnkSsWDKIvCRks4kZt3oHLd3nO +G671JGRJI/qbs6F5l6c96kotlZkolYIPMhyK8Ex4LjMW6UrPWdpJrXTWPvLq4c85 +ZaN52yKu6tsLrBTPwPmK9t+zQ2drb1g8Eq9B+cuwD3Row6njsDQ1Ltry+KCnivki +E/ptgwyCkS4brkhjHMz5l5Co0KMsHylAb2XcBxFVFSl0aJIqK5Gr0nTlg26pNG7O +qxv6ncOHl3tmArETi36TQbTYvFc+6cNb8CqdWe95 +-----END CERTIFICATE----- diff --git a/spec/data/trusted_certs/root.pem b/spec/data/trusted_certs/root.pem new file mode 100644 index 0000000000..fd4341df26 --- /dev/null +++ b/spec/data/trusted_certs/root.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- diff --git a/spec/functional/assets/PkgA.1.0.0.0.bff b/spec/functional/assets/PkgA.1.0.0.0.bff Binary files differnew file mode 100644 index 0000000000..b157d080e8 --- /dev/null +++ b/spec/functional/assets/PkgA.1.0.0.0.bff diff --git a/spec/functional/assets/PkgA.2.0.0.0.bff b/spec/functional/assets/PkgA.2.0.0.0.bff Binary files differnew file mode 100644 index 0000000000..0afe7b7f12 --- /dev/null +++ b/spec/functional/assets/PkgA.2.0.0.0.bff diff --git a/spec/functional/assets/dummy-1-0.aix6.1.noarch.rpm b/spec/functional/assets/dummy-1-0.aix6.1.noarch.rpm Binary files differnew file mode 100644 index 0000000000..1c6f129a9a --- /dev/null +++ b/spec/functional/assets/dummy-1-0.aix6.1.noarch.rpm diff --git a/spec/functional/assets/dummy-2-0.aix6.1.noarch.rpm b/spec/functional/assets/dummy-2-0.aix6.1.noarch.rpm Binary files differnew file mode 100644 index 0000000000..650b7dd9ba --- /dev/null +++ b/spec/functional/assets/dummy-2-0.aix6.1.noarch.rpm diff --git a/spec/functional/assets/mytest-1.0-1.noarch.rpm b/spec/functional/assets/mytest-1.0-1.noarch.rpm Binary files differnew file mode 100644 index 0000000000..07334a0cc7 --- /dev/null +++ b/spec/functional/assets/mytest-1.0-1.noarch.rpm diff --git a/spec/functional/assets/mytest-2.0-1.noarch.rpm b/spec/functional/assets/mytest-2.0-1.noarch.rpm Binary files differnew file mode 100644 index 0000000000..7e7ba17839 --- /dev/null +++ b/spec/functional/assets/mytest-2.0-1.noarch.rpm diff --git a/spec/functional/knife/cookbook_delete_spec.rb b/spec/functional/knife/cookbook_delete_spec.rb index ef38cb2e1f..2d52fb91a3 100644 --- a/spec/functional/knife/cookbook_delete_spec.rb +++ b/spec/functional/knife/cookbook_delete_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -21,8 +21,6 @@ require 'tiny_server' describe Chef::Knife::CookbookDelete do before(:all) do - @original_config = Chef::Config.hash_dup - @server = TinyServer::Manager.new @server.start end @@ -38,11 +36,10 @@ describe Chef::Knife::CookbookDelete do end after(:all) do - Chef::Config.configuration = @original_config @server.stop end - context "when the the cookbook doesn't exist" do + context "when the cookbook doesn't exist" do before do @log_output = StringIO.new @@ -97,7 +94,7 @@ describe Chef::Knife::CookbookDelete do stdout.string.should match(/#{Regexp.escape('Are you sure you want to purge files')}/) stdout.string.should match(/#{Regexp.escape('Do you really want to delete obsolete-cookbook version 1.0.0? (Y/N)')}/) cb100_deleted.should be_true - + end end diff --git a/spec/functional/knife/exec_spec.rb b/spec/functional/knife/exec_spec.rb index 1bccbdeb7a..455160fd5c 100644 --- a/spec/functional/knife/exec_spec.rb +++ b/spec/functional/knife/exec_spec.rb @@ -21,8 +21,6 @@ require 'tiny_server' describe Chef::Knife::Exec do before(:all) do - @original_config = Chef::Config.hash_dup - @server = TinyServer::Manager.new#(:debug => true) @server.start end @@ -40,7 +38,6 @@ describe Chef::Knife::Exec do end after(:all) do - Chef::Config.configuration = @original_config @server.stop end diff --git a/spec/functional/knife/ssh_spec.rb b/spec/functional/knife/ssh_spec.rb index a853e8de19..fd8cfe0f7e 100644 --- a/spec/functional/knife/ssh_spec.rb +++ b/spec/functional/knife/ssh_spec.rb @@ -22,16 +22,12 @@ require 'tiny_server' describe Chef::Knife::Ssh do before(:all) do - @original_config = Chef::Config.hash_dup - @original_knife_config = Chef::Config[:knife].dup Chef::Knife::Ssh.load_deps @server = TinyServer::Manager.new @server.start end after(:all) do - Chef::Config.configuration = @original_config - Chef::Config[:knife] = @original_knife_config @server.stop end @@ -153,9 +149,9 @@ describe Chef::Knife::Ssh do Chef::Config[:knife][:ssh_user] = nil end - it "uses the default" do + it "uses the default (current user)" do @knife.run - @knife.config[:ssh_user].should == "root" + @knife.config[:ssh_user].should == nil end end end diff --git a/spec/functional/resource/base.rb b/spec/functional/resource/base.rb new file mode 100644 index 0000000000..13438c1759 --- /dev/null +++ b/spec/functional/resource/base.rb @@ -0,0 +1,41 @@ +# +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.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' + +def ohai + # provider is platform-dependent, we need platform ohai data: + @OHAI_SYSTEM ||= begin + ohai = Ohai::System.new + ohai.require_plugin("os") + ohai.require_plugin("platform") + ohai.require_plugin("passwd") + ohai + end +end + +def run_context + @run_context ||= begin + node = Chef::Node.new + node.default[:platform] = ohai[:platform] + node.default[:platform_version] = ohai[:platform_version] + events = Chef::EventDispatch::Dispatcher.new + Chef::RunContext.new(node, {}, events) + end +end + diff --git a/spec/functional/resource/batch_spec.rb b/spec/functional/resource/batch_spec.rb index 7f7125a91e..baa01ee5d9 100644 --- a/spec/functional/resource/batch_spec.rb +++ b/spec/functional/resource/batch_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -18,47 +18,20 @@ require 'spec_helper' -shared_context Chef::Resource::WindowsScript do - before(:all) do - - ohai_reader = Ohai::System.new - ohai_reader.require_plugin("os") - ohai_reader.require_plugin("windows::platform") - - new_node = Chef::Node.new - new_node.consume_external_attrs(ohai_reader.data,{}) - - events = Chef::EventDispatch::Dispatcher.new - - @run_context = Chef::RunContext.new(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 + include_context Chef::Resource::WindowsScript + 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 + describe "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 end diff --git a/spec/functional/resource/bff_spec.rb b/spec/functional/resource/bff_spec.rb new file mode 100644 index 0000000000..5e7cb8a168 --- /dev/null +++ b/spec/functional/resource/bff_spec.rb @@ -0,0 +1,122 @@ +# +# Author:: Prabhu Das (<prabhu.das@clogeny.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 'functional/resource/base' +require 'chef/mixin/shell_out' + +# Run the test only for AIX platform. +describe Chef::Resource::BffPackage, :external => ohai[:platform] != 'aix' do + include Chef::Mixin::ShellOut + + let(:new_resource) do + new_resource = Chef::Resource::BffPackage.new(@pkg_name, run_context) + new_resource.source @pkg_path + new_resource + end + + def bff_pkg_should_be_installed(resource) + expect(shell_out("lslpp -L #{resource.name}").exitstatus).to eq(0) + ::File.exists?("/usr/PkgA/bin/acommand") + end + + def bff_pkg_should_be_removed(resource) + expect(shell_out("lslpp -L #{resource.name}").exitstatus).to eq(1) + !::File.exists?("/usr/PkgA/bin/acommand") + end + + + before(:all) do + @pkg_name = "PkgA.rte" + @pkg_path = "/tmp/PkgA.1.0.0.0.bff" + FileUtils.cp 'spec/functional/assets/PkgA.1.0.0.0.bff' , @pkg_path + end + + after(:all) do + FileUtils.rm @pkg_path + end + + context "package install action" do + it "should install a package" do + new_resource.run_action(:install) + bff_pkg_should_be_installed(new_resource) + end + + after(:each) do + shell_out("installp -u #{@pkg_name}") + end + end + + context "package install action with options" do + it "should install a package" do + new_resource.options("-e/tmp/installp.log") + new_resource.run_action(:install) + bff_pkg_should_be_installed(new_resource) + end + + after(:each) do + shell_out("installp -u #{@pkg_name}") + FileUtils.rm "/tmp/installp.log" + end + end + + context "package upgrade action" do + before(:each) do + shell_out("installp -aYF -d #{@pkg_path} #{@pkg_name}") + @pkg_path = "/tmp/PkgA.2.0.0.0.bff" + FileUtils.cp 'spec/functional/assets/PkgA.2.0.0.0.bff' , @pkg_path + end + + it "should upgrade package" do + new_resource.run_action(:install) + bff_pkg_should_be_installed(new_resource) + end + + after(:each) do + shell_out("installp -u #{@pkg_name}") + FileUtils.rm @pkg_path + end + end + + context "package remove action" do + before(:each) do + shell_out("installp -aYF -d #{@pkg_path} #{@pkg_name}") + end + + it "should remove an installed package" do + new_resource.run_action(:remove) + bff_pkg_should_be_removed(new_resource) + end + end + + context "package remove action with options" do + before(:each) do + shell_out("installp -aYF -d #{@pkg_path} #{@pkg_name}") + end + + it "should remove an installed package" do + new_resource.options("-e/tmp/installp.log") + new_resource.run_action(:remove) + bff_pkg_should_be_removed(new_resource) + end + + after(:each) do + FileUtils.rm "/tmp/installp.log" + end + end +end + diff --git a/spec/functional/resource/cron_spec.rb b/spec/functional/resource/cron_spec.rb new file mode 100644 index 0000000000..4c20023d78 --- /dev/null +++ b/spec/functional/resource/cron_spec.rb @@ -0,0 +1,147 @@ +# encoding: UTF-8 +# +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.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 'functional/resource/base' +require 'chef/mixin/shell_out' + +describe Chef::Resource::Cron, :requires_root, :unix_only do + + include Chef::Mixin::ShellOut + + # Platform specific validation routines. + def cron_should_exists(cron_name, command) + case ohai[:platform] + when "aix", "solaris", "opensolaris", "solaris2", "omnios" + expect(shell_out("crontab -l #{new_resource.user} | grep \"#{cron_name}\"").exitstatus).to eq(0) + expect(shell_out("crontab -l #{new_resource.user} | grep \"#{command}\"").exitstatus).to eq(0) + else + expect(shell_out("crontab -l -u #{new_resource.user} | grep \"#{cron_name}\"").exitstatus).to eq(0) + expect(shell_out("crontab -l -u #{new_resource.user} | grep \"#{command}\"").exitstatus).to eq(0) + end + end + + def cron_should_not_exists(cron_name) + case ohai[:platform] + when "aix", "solaris", "opensolaris", "solaris2", "omnios" + expect(shell_out("crontab -l #{new_resource.user} | grep \"#{cron_name}\"").exitstatus).to eq(1) + else + expect(shell_out("crontab -l -u #{new_resource.user} | grep \"#{cron_name}\"").exitstatus).to eq(1) + end + end + + # Actual tests + let(:new_resource) do + new_resource = Chef::Resource::Cron.new("Chef functional test cron", run_context) + new_resource.user 'root' + new_resource.minute "30" + new_resource.command "/bin/true" + new_resource + end + + let(:provider) do + provider = new_resource.provider_for_action(new_resource.action) + provider + end + + describe "create action" do + after do + new_resource.run_action(:delete) + end + + it "should create a crontab entry" do + new_resource.run_action(:create) + cron_should_exists(new_resource.name, new_resource.command) + end + end + + describe "delete action" do + before do + new_resource.run_action(:create) + end + + it "should delete a crontab entry" do + # Note that test cron is created by previous test + new_resource.run_action(:delete) + + cron_should_not_exists(new_resource.name) + end + end + + exclude_solaris = ["solaris", "opensolaris", "solaris2", "omnios"].include?(ohai[:platform]) + describe "create action with various attributes", :external => exclude_solaris do + def create_and_validate_with_attribute(resource, attribute, value) + if ohai[:platform] == 'aix' + expect {resource.run_action(:create)}.to raise_error(Chef::Exceptions::Cron, /Aix cron entry does not support environment variables. Please set them in script and use script in cron./) + else + resource.run_action(:create) + # Verify if the cron is created successfully + cron_attribute_should_exists(resource.name, attribute, value) + end + end + + def cron_attribute_should_exists(cron_name, attribute, value) + return if ['aix', 'solaris'].include?(ohai[:platform]) + # Test if the attribute exists on newly created cron + cron_should_exists(cron_name, "") + expect(shell_out("crontab -l -u #{new_resource.user} | grep \"#{attribute.upcase}=#{value}\"").exitstatus).to eq(0) + end + + after do + new_resource.run_action(:delete) + end + + it "should create a crontab entry for mailto attribute" do + new_resource.mailto "cheftest@example.com" + create_and_validate_with_attribute(new_resource, "mailto", "cheftest@example.com") + end + + it "should create a crontab entry for path attribute" do + new_resource.path "/usr/local/bin" + create_and_validate_with_attribute(new_resource, "path", "/usr/local/bin") + end + + it "should create a crontab entry for shell attribute" do + new_resource.shell "/bin/bash" + create_and_validate_with_attribute(new_resource, "shell", "/bin/bash") + end + + it "should create a crontab entry for home attribute" do + new_resource.home "/home/opscode" + create_and_validate_with_attribute(new_resource, "home", "/home/opscode") + end + end + + describe "negative tests for create action" do + def cron_create_should_raise_exception + expect { new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::Cron, /Error updating state of #{new_resource.name}, exit: 1/) + cron_should_not_exists(new_resource.name) + end + + it "should not create cron with invalid minute" do + new_resource.minute "invalid" + cron_create_should_raise_exception + end + + it "should not create cron with invalid user" do + new_resource.user "1-really-really-invalid-user-name" + cron_create_should_raise_exception + end + + end +end diff --git a/spec/functional/resource/group_spec.rb b/spec/functional/resource/group_spec.rb new file mode 100644 index 0000000000..2c9a568979 --- /dev/null +++ b/spec/functional/resource/group_spec.rb @@ -0,0 +1,204 @@ +# +# Author:: Chirag Jog (<chirag@clogeny.com>) +# Author:: Siddheshwar More (<siddheshwar.more@clogeny.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/base' + +describe Chef::Resource::Group, :requires_root_or_running_windows do + + def group_should_exist(resource) + case ohai[:platform_family] + when "debian", "fedora", "rhel", "suse", "gentoo", "slackware", "arch" + expect { Etc::getgrnam(resource.name) }.to_not raise_error(ArgumentError, "can't find group for #{resource.name}") + expect(resource.name).to eq(Etc::getgrnam(resource.name).name) + when "windows" + expect { Chef::Util::Windows::NetGroup.new(resource.group_name).local_get_members }.to_not raise_error(ArgumentError, "The group name could not be found.") + end + end + + def user_exist_in_group?(resource, user) + case ohai[:platform_family] + when "debian", "fedora", "rhel", "suse", "gentoo", "slackware", "arch" + Etc::getgrnam(resource.name).mem.include?(user) + when "windows" + Chef::Util::Windows::NetGroup.new(resource.group_name).local_get_members.include?(user) + end + end + + def group_should_not_exist(resource) + case ohai[:platform_family] + when "debian", "fedora", "rhel", "suse", "gentoo", "slackware", "arch" + expect { Etc::getgrnam(resource.name) }.to raise_error(ArgumentError, "can't find group for #{resource.name}") + when "windows" + expect { Chef::Util::Windows::NetGroup.new(resource.group_name).local_get_members }.to raise_error(ArgumentError, "The group name could not be found.") + end + end + + def compare_gid(resource, gid) + return resource.gid == Etc::getgrnam(resource.name).gid if unix? + end + + def get_user_resource(username) + usr = Chef::Resource::User.new("#{username}", run_context) + usr.password("Jetsream123!") + usr + end + + def create_user(username) + get_user_resource(username).run_action(:create) + end + + def remove_user(username) + get_user_resource(username).run_action(:remove) + end + + before do + @grp_resource = Chef::Resource::Group.new("test-group-#{SecureRandom.random_number(9999)}", run_context) + end + + context "group create action" do + after(:each) do + @grp_resource.run_action(:remove) + end + + it "create a group" do + @grp_resource.run_action(:create) + group_should_exist(@grp_resource) + end + + context "group name with 256 characters", :windows_only do + before(:each) do + grp_name = "theoldmanwalkingdownthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestree" + @new_grp = Chef::Resource::Group.new(grp_name, run_context) + end + after do + @new_grp.run_action(:remove) + end + it " create a group" do + @new_grp.run_action(:create) + group_should_exist(@new_grp) + end + end + context "group name with more than 256 characters", :windows_only do + before(:each) do + grp_name = "theoldmanwalkingdownthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreeQQQQQQQQQQQQQQQQQ" + @new_grp = Chef::Resource::Group.new(grp_name, run_context) + end + it " not create a group" do + expect { @new_grp.run_action(:create) }.to raise_error + group_should_not_exist(@new_grp) + end + end + end + + context "group remove action" do + before(:each) do + @grp_resource.run_action(:create) + end + + it "remove a group" do + @grp_resource.run_action(:remove) + group_should_not_exist(@grp_resource) + end + end + + context "group modify action", :unsupported_group_provider_platform do + before(:each) do + @grp_resource.run_action(:create) + end + + after(:each) do + @grp_resource.run_action(:remove) + end + + it "add user to group" do + user1 = "user1-#{SecureRandom.random_number(9999)}" + user2 = "user2-#{SecureRandom.random_number(9999)}" + + create_user(user1) + @grp_resource.members(user1) + expect(user_exist_in_group?(@grp_resource, user1)).to be_false + @grp_resource.run_action(:modify) + group_should_exist(@grp_resource) + expect(user_exist_in_group?(@grp_resource, user1)).to be_true + + create_user(user2) + expect(user_exist_in_group?(@grp_resource, user2)).to be_false + @grp_resource.members(user2) + @grp_resource.run_action(:modify) + group_should_exist(@grp_resource) + + #default append is false, so modify action remove old member user1 from group and add new member user2 + expect(user_exist_in_group?(@grp_resource, user1)).to be_false + expect(user_exist_in_group?(@grp_resource, user2)).to be_true + remove_user(user1) + remove_user(user2) + end + + + it "append user to a group" do + user1 = "user1-#{SecureRandom.random_number(9999)}" + user2 = "user2-#{SecureRandom.random_number(9999)}" + create_user(user1) + @grp_resource.members(user1) + expect(user_exist_in_group?(@grp_resource, user1)).to be_false + #default append attribute is false + @grp_resource.run_action(:modify) + group_should_exist(@grp_resource) + expect(user_exist_in_group?(@grp_resource, user1)).to be_true + #set append attribute to true + @grp_resource.append(true) + create_user(user2) + expect(user_exist_in_group?(@grp_resource, user2)).to be_false + @grp_resource.members(user2) + @grp_resource.run_action(:modify) + group_should_exist(@grp_resource) + expect(user_exist_in_group?(@grp_resource, user1)).to be_true + expect(user_exist_in_group?(@grp_resource, user2)).to be_true + remove_user(user1) + remove_user(user2) + end + + it "raise error on add non-existent user to group" do + user1 = "user1-#{SecureRandom.random_number(9999)}" + @grp_resource.members(user1) + @grp_resource.append(true) + expect(user_exist_in_group?(@grp_resource, user1)).to be_false + expect { @grp_resource.run_action(:modify) }.to raise_error + end + end + + context "group manage action", :unix_only, :unsupported_group_provider_platform do + before(:each) do + @grp_resource.run_action(:create) + end + + after(:each) do + @grp_resource.run_action(:remove) + end + + it "change gid of the group" do + grp_id = 1234567890 + @grp_resource.gid(grp_id) + @grp_resource.run_action(:manage) + group_should_exist(@grp_resource) + expect(compare_gid(@grp_resource, grp_id)).to be_true + end + end +end diff --git a/spec/functional/resource/ifconfig_spec.rb b/spec/functional/resource/ifconfig_spec.rb new file mode 100644 index 0000000000..c36288498b --- /dev/null +++ b/spec/functional/resource/ifconfig_spec.rb @@ -0,0 +1,163 @@ +# +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.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 'functional/resource/base' +require 'chef/mixin/shell_out' + +# run this test only for following platforms. +include_flag = !(['ubuntu', 'centos', 'aix'].include?(ohai[:platform])) + +describe Chef::Resource::Ifconfig, :requires_root, :external => include_flag do + include Chef::Mixin::ShellOut + + let(:new_resource) do + new_resource = Chef::Resource::Ifconfig.new('10.10.0.1', run_context) + new_resource + end + + let(:provider) do + provider = new_resource.provider_for_action(new_resource.action) + provider + end + + let(:current_resource) do + provider.load_current_resource + end + + def lo_interface_for_test + # use loopback interface for tests + case ohai[:platform] + when "aix" + 'lo0' + else + 'lo' + end + end + + # **Caution: any updates to core interfaces can be risky. + def en0_interface_for_test + case ohai[:platform] + when "aix" + 'en0' + else + 'eth0' + end + end + + def network_interface_alias(interface) + case ohai[:platform] + when "aix" + interface + else + interface + ":10" + end + end + + # platform specific test setup and validation routines + + def setup_add_interface(resource) + resource.device network_interface_alias(en0_interface_for_test) + end + + def setup_enable_interface(resource) + resource.device network_interface_alias(en0_interface_for_test) + end + + def interface_should_exists(interface) + expect(shell_out("ifconfig #{@interface} | grep 10.10.0.1").exitstatus).to eq(0) + end + + def interface_should_not_exists(interface) + expect(shell_out("ifconfig #{@interface} | grep 10.10.0.1").exitstatus).to eq(1) + end + + def interface_persistence_should_exists(interface) + case ohai[:platform] + when "aix" + expect(shell_out("lsattr -E -l #{@interface} | grep 10.10.0.1").exitstatus).to eq(0) + else + end + end + + def interface_persistence_should_not_exists(interface) + case ohai[:platform] + when "aix" + expect(shell_out("lsattr -E -l #{@interface} | grep 10.10.0.1").exitstatus).to eq(1) + else + end + end + + # Actual tests + + describe "#load_current_resource" do + it 'should load given interface' do + new_resource.device lo_interface_for_test + expect(current_resource.device).to eql(lo_interface_for_test) + expect(current_resource.inet_addr).to match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) + end + end + + exclude_test = ohai[:platform] != 'ubuntu' + describe "#action_add", :external => exclude_test do + after do + new_resource.run_action(:delete) + end + it "should add interface (vip)" do + setup_add_interface(new_resource) + new_resource.run_action(:add) + interface_should_exists(network_interface_alias(en0_interface_for_test)) + interface_persistence_should_exists(network_interface_alias(en0_interface_for_test)) + end + end + + describe "#action_enable", :external => exclude_test do + after do + new_resource.run_action(:disable) + end + it "should enable interface (vip)" do + setup_enable_interface(new_resource) + new_resource.run_action(:enable) + interface_should_exists(network_interface_alias(en0_interface_for_test)) + end + end + + describe "#action_disable", :external => exclude_test do + before do + setup_enable_interface(new_resource) + new_resource.run_action(:enable) + end + it "should disable interface (vip)" do + new_resource.run_action(:disable) + new_resource.should be_updated_by_last_action + interface_should_not_exists(network_interface_alias(en0_interface_for_test)) + end + end + + describe "#action_delete", :external => exclude_test do + before do + setup_add_interface(new_resource) + new_resource.run_action(:add) + end + it "should delete interface (vip)" do + new_resource.run_action(:delete) + new_resource.should be_updated_by_last_action + interface_should_not_exists(network_interface_alias(en0_interface_for_test)) + interface_persistence_should_not_exists(network_interface_alias(en0_interface_for_test)) + end + end +end diff --git a/spec/functional/resource/link_spec.rb b/spec/functional/resource/link_spec.rb index fd13353bad..36bc858a74 100644 --- a/spec/functional/resource/link_spec.rb +++ b/spec/functional/resource/link_spec.rb @@ -340,7 +340,7 @@ describe Chef::Resource::Link do it 'create errors out' do if windows? lambda { resource.run_action(:create) }.should raise_error(Errno::EACCES) - elsif os_x? or solaris? or freebsd? + elsif os_x? or solaris? or freebsd? or aix? lambda { resource.run_action(:create) }.should raise_error(Errno::EPERM) else lambda { resource.run_action(:create) }.should raise_error(Errno::EISDIR) @@ -502,7 +502,7 @@ describe Chef::Resource::Link do it 'errors out' do if windows? lambda { resource.run_action(:create) }.should raise_error(Errno::EACCES) - elsif os_x? or solaris? or freebsd? + elsif os_x? or solaris? or freebsd? or aix? lambda { resource.run_action(:create) }.should raise_error(Errno::EPERM) else lambda { resource.run_action(:create) }.should raise_error(Errno::EISDIR) @@ -554,7 +554,7 @@ describe Chef::Resource::Link do resource.run_action(:create) File.exists?(target_file).should be_true # OS X gets angry about this sort of link. Bug in OS X, IMO. - pending('OS X/FreeBSD symlink? and readlink working on hard links to symlinks', :if => (os_x? or freebsd?)) do + pending('OS X/FreeBSD/AIX symlink? and readlink working on hard links to symlinks', :if => (os_x? or freebsd? or aix?)) do symlink?(target_file).should be_true readlink(target_file).should == canonicalize(@other_target) end @@ -571,7 +571,7 @@ describe Chef::Resource::Link do end context 'and the link does not yet exist' do it 'links to the target file' do - pending('OS X/FreeBSD fails to create hardlinks to broken symlinks', :if => (os_x? or freebsd?)) do + pending('OS X/FreeBSD/AIX fails to create hardlinks to broken symlinks', :if => (os_x? or freebsd? or aix?)) do resource.run_action(:create) # Windows and Unix have different definitions of exists? here, and that's OK. if windows? diff --git a/spec/functional/resource/mount_spec.rb b/spec/functional/resource/mount_spec.rb new file mode 100644 index 0000000000..199ccbd37e --- /dev/null +++ b/spec/functional/resource/mount_spec.rb @@ -0,0 +1,207 @@ +# +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.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 'functional/resource/base' +require 'chef/mixin/shell_out' +require 'tmpdir' + +# run this test only for following platforms. +include_flag = !(['ubuntu', 'centos', 'aix'].include?(ohai[:platform])) + +describe Chef::Resource::Mount, :requires_root, :external => include_flag do + + include Chef::Mixin::ShellOut + + # Platform specific setup, cleanup and validation helpers. + + def setup_device_for_mount + # use ramdisk for creating a test device for mount. + # This can cleaner if we have chef resource/provider for ramdisk. + case ohai[:platform] + when "aix" + ramdisk = shell_out!("mkramdisk 16M").stdout + + # identify device, for /dev/rramdisk0 it is /dev/ramdisk0 + device = ramdisk.tr("\n","").gsub(/\/rramdisk/, '/ramdisk') + + fstype = "jfs2" + shell_out!("mkfs -V #{fstype} #{device}") + when "ubuntu", "centos" + device = "/dev/ram1" + shell_out("ls -1 /dev/ram*").stdout.each_line do |d| + if shell_out("mount | grep #{d}").exitstatus == "1" + # this device is not mounted, so use it. + device = d + break + end + end + fstype = "tmpfs" + shell_out!("mkfs -q #{device} 512") + else + end + [device, fstype] + end + + def cleanup_device(device) + case ohai[:platform] + when "aix" + ramdisk = device.gsub(/\/ramdisk/, '/rramdisk') + shell_out("rmramdisk #{ramdisk}") + else + end + end + + def cleanup_mount(mount_point) + shell_out("umount #{mount_point}") + end + + # platform specific validations. + def mount_should_exists(mount_point, device, fstype = nil, options = nil) + validation_cmd = "mount | grep #{mount_point} | grep #{device} " + validation_cmd << " | grep #{fstype} " unless fstype.nil? + validation_cmd << " | grep #{options.join(',')} " unless options.nil? || options.empty? + puts "validation_cmd = #{validation_cmd}" + expect(shell_out(validation_cmd).exitstatus).to eq(0) + end + + def mount_should_not_exists(mount_point) + shell_out("mount").stdout.should_not include(mount_point) + end + + def unix_mount_config_file + case ohai[:platform] + when 'aix' + mount_config = "/etc/filesystems" + else + mount_config = "/etc/fstab" + end + end + + def mount_should_be_enabled(mount_point, device) + case ohai[:platform] + when 'aix' + expect(shell_out("cat #{unix_mount_config_file} | grep \"#{mount_point}:\" ").exitstatus).to eq(0) + else + expect(shell_out("cat #{unix_mount_config_file} | grep \"#{mount_point}\" | grep \"#{device}\" ").exitstatus).to eq(0) + end + end + + def mount_should_be_disabled(mount_point) + shell_out("cat #{unix_mount_config_file}").stdout.should_not include("#{mount_point}:") + end + + let(:new_resource) do + new_resource = Chef::Resource::Mount.new(@mount_point, run_context) + new_resource.device @device + new_resource.name @mount_point + new_resource.fstype @fstype + new_resource.options "log=NULL" if ohai[:platform] == 'aix' + new_resource + end + + let(:provider) do + provider = new_resource.provider_for_action(new_resource.action) + provider + end + + def current_resource + provider.load_current_resource + provider.current_resource + end + + # Actual tests begin here. + before(:all) do + @device, @fstype = setup_device_for_mount + + @mount_point = Dir.mktmpdir("testmount") + + # Make sure all the potentially leaked mounts are cleared up + shell_out("mount").stdout.each_line do |line| + if line.include? "testmount" + line.split(" ").each do |section| + cleanup_mount(section) if section.include? "testmount" + end + end + end + + end + + after(:all) do + Dir.rmdir(@mount_point) + cleanup_device(@device) + end + + after(:each) do + cleanup_mount(new_resource.mount_point) + end + + describe "when the target state is a mounted filesystem" do + it "should mount the filesystem if it isn't mounted" do + current_resource.enabled.should be_false + current_resource.mounted.should be_false + new_resource.run_action(:mount) + new_resource.should be_updated + mount_should_exists(new_resource.mount_point, new_resource.device) + end + + end + + describe "when the filesystem should be remounted and the resource supports remounting" do + it "should remount the filesystem if it is mounted" do + new_resource.run_action(:mount) + mount_should_exists(new_resource.mount_point, new_resource.device) + + new_resource.supports[:remount] = true + new_resource.options "rw,log=NULL" if ohai[:platform] == 'aix' + new_resource.run_action(:remount) + + mount_should_exists(new_resource.mount_point, new_resource.device, nil, (ohai[:platform] == 'aix') ? new_resource.options : nil) + end + end + + describe "when the target state is a unmounted filesystem" do + it "should umount the filesystem if it is mounted" do + new_resource.run_action(:mount) + mount_should_exists(new_resource.mount_point, new_resource.device) + + new_resource.run_action(:umount) + mount_should_not_exists(new_resource.mount_point) + end + end + + describe "when enabling the filesystem to be mounted" do + after do + new_resource.run_action(:disable) + end + + it "should enable the mount if it isn't enable" do + new_resource.run_action(:mount) + new_resource.run_action(:enable) + mount_should_be_enabled(new_resource.mount_point, new_resource.device) + end + end + + describe "when the target state is to disable the mount" do + it "should disable the mount if it is enabled" do + new_resource.run_action(:mount) + new_resource.run_action(:enable) + new_resource.run_action(:disable) + mount_should_be_disabled(new_resource.mount_point) + end + end +end diff --git a/spec/functional/resource/package_spec.rb b/spec/functional/resource/package_spec.rb index b5f8e5dc66..55011271b5 100644 --- a/spec/functional/resource/package_spec.rb +++ b/spec/functional/resource/package_spec.rb @@ -95,15 +95,6 @@ metadata = { :unix_only => true, describe Chef::Resource::Package, metadata do include Chef::Mixin::ShellOut - def chef_test_dpkg_installed? - shell_out("dpkg -l chef-integration-test").status.success? - end - - def dpkg_should_be_installed(pkg_name) - shell_out!("dpkg -l #{pkg_name}") - end - - context "with a remote package source" do include AptServer @@ -166,11 +157,6 @@ describe Chef::Resource::Package, metadata do base_resource end - # it "results in a usable apt server" do - # shell_out!("apt-get install -q -y --force-yes chef-integration-test ", :env => { "DEBIAN_FRONTEND" => "noninteractive" }) - # shell_out!("dpkg -l chef-integration-test") - # end - context "when the package is not yet installed" do it "installs the package with action :install" do package_resource.run_action(:install) @@ -206,7 +192,7 @@ describe Chef::Resource::Package, metadata do it "raises a reasonable error for action :install" do expect do package_resource.run_action(:install) - end.to raise_error(Chef::Exceptions::Exec) + end.to raise_error(Mixlib::ShellOut::ShellCommandFailed) end end @@ -216,7 +202,6 @@ describe Chef::Resource::Package, metadata do let(:file_cache_path) { Dir.mktmpdir } before do - @old_config = Chef::Config.configuration.dup Chef::Config[:file_cache_path] = file_cache_path debconf_reset = 'chef-integration-test chef-integration-test/sample-var string "INVALID"' shell_out!("echo #{debconf_reset} |debconf-set-selections") @@ -224,7 +209,6 @@ describe Chef::Resource::Package, metadata do after do FileUtils.rm_rf(file_cache_path) - Chef::Config.configuration = @old_config end context "with a preseed file" do @@ -267,6 +251,10 @@ describe Chef::Resource::Package, metadata do context "with a preseed template" do + # NOTE: in the fixtures, there is also a cookbook_file named + # "preseed-template.seed". This implicitly tests that templates are + # preferred over cookbook_files when both are present. + let(:package_resource) do r = base_resource r.cookbook_name = "preseed" @@ -286,8 +274,98 @@ describe Chef::Resource::Package, metadata do end end + end # installing w/ preseed + end # when package not installed + context "and the desired version of the package is installed" do + + before do + v_1_1_package = File.expand_path("apt/chef-integration-test_1.1-1_amd64.deb", CHEF_SPEC_DATA) + shell_out!("dpkg -i #{v_1_1_package}") + end + + it "does nothing for action :install" do + package_resource.run_action(:install) + shell_out!("dpkg -l chef-integration-test", :returns => [0]) + package_resource.should_not be_updated_by_last_action end + + it "does nothing for action :upgrade" do + package_resource.run_action(:upgrade) + shell_out!("dpkg -l chef-integration-test", :returns => [0]) + package_resource.should_not be_updated_by_last_action + end + + # Verify that the package is removed by running `dpkg -l PACKAGE` + # On Ubuntu 12.10 and newer, the command exits 1. + # + # On Ubuntu 12.04 and older, the `dpkg -l` command will exit 0 and + # display a package status message like this: + # + # Desired=Unknown/Install/Remove/Purge/Hold + # | Status=Not/Inst/Cfg-files/Unpacked/Failed-cfg/Half-inst/trig-aWait/Trig-pend + # |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad) + # ||/ Name Version Description + # +++-=================================-=========================================-============================================ + # un chef-integration-test <none> (no description available) + def pkg_should_be_removed + # will raise if exit code != 0,1 + pkg_check = shell_out!("dpkg -l chef-integration-test", :returns => [0,1]) + + if pkg_check.exitstatus == 0 + pkg_check.stdout.should =~ /un[\s]+chef-integration-test/ + end + end + + + it "removes the package for action :remove" do + package_resource.run_action(:remove) + pkg_should_be_removed + package_resource.should be_updated_by_last_action + end + + it "removes the package for action :purge" do + package_resource.run_action(:purge) + pkg_should_be_removed + package_resource.should be_updated_by_last_action + end + + end + + context "and an older version of the package is installed" do + before do + v_1_0_package = File.expand_path("apt/chef-integration-test_1.0-1_amd64.deb", CHEF_SPEC_DATA) + shell_out!("dpkg -i #{v_1_0_package}") + end + + it "does nothing for action :install" do + package_resource.run_action(:install) + shell_out!("dpkg -l chef-integration-test", :returns => [0]) + package_resource.should_not be_updated_by_last_action + end + + it "upgrades the package for action :upgrade" do + package_resource.run_action(:upgrade) + dpkg_l = shell_out!("dpkg -l chef-integration-test", :returns => [0]) + dpkg_l.stdout.should =~ /chef\-integration\-test[\s]+1\.1\-1/ + package_resource.should be_updated_by_last_action + end + + context "and the resource specifies the new version" do + let(:package_resource) do + r = base_resource + r.version("1.1-1") + r + end + + it "upgrades the package for action :install" do + package_resource.run_action(:install) + dpkg_l = shell_out!("dpkg -l chef-integration-test", :returns => [0]) + dpkg_l.stdout.should =~ /chef\-integration\-test[\s]+1\.1\-1/ + package_resource.should be_updated_by_last_action + end + end + end end diff --git a/spec/functional/resource/powershell_spec.rb b/spec/functional/resource/powershell_spec.rb index 4d31eb3ef1..6bd3b3c1e5 100644 --- a/spec/functional/resource/powershell_spec.rb +++ b/spec/functional/resource/powershell_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -17,11 +17,10 @@ # require 'spec_helper' -require 'functional/resource/batch_spec.rb' describe Chef::Resource::WindowsScript::PowershellScript, :windows_only do - include_context Chef::Resource::WindowsScript + include_context Chef::Resource::WindowsScript let(:successful_executable_script_content) { "#{ENV['SystemRoot']}\\system32\\attrib.exe $env:systemroot" } let(:failed_executable_script_content) { "#{ENV['SystemRoot']}\\system32\\attrib.exe /badargument" } @@ -36,7 +35,7 @@ describe Chef::Resource::WindowsScript::PowershellScript, :windows_only do let(:arbitrary_nonzero_process_exit_code) { 4193 } let(:arbitrary_nonzero_process_exit_code_content) { "exit #{arbitrary_nonzero_process_exit_code}" } let(:invalid_powershell_interpreter_flag) { "/thisflagisinvalid" } - let(:valid_powershell_interpreter_flag) { "-Sta" } + let(:valid_powershell_interpreter_flag) { "-Sta" } let!(:resource) do r = Chef::Resource::WindowsScript::PowershellScript.new("Powershell resource functional test", @run_context) r.code(successful_executable_script_content) @@ -53,31 +52,31 @@ describe Chef::Resource::WindowsScript::PowershellScript, :windows_only do it "returns the process exit code" do resource.code(arbitrary_nonzero_process_exit_code_content) resource.returns(arbitrary_nonzero_process_exit_code) - resource.run_action(:run) + resource.run_action(:run) end it "returns 0 if the last command was a cmdlet that succeeded" do resource.code(cmdlet_exit_code_success_content) resource.returns(0) - resource.run_action(:run) + resource.run_action(:run) end it "returns 0 if the last command was a cmdlet that succeeded and was preceded by a non-cmdlet Windows binary that failed" do resource.code([windows_process_exit_code_not_found_content, cmdlet_exit_code_success_content].join(';')) resource.returns(0) - resource.run_action(:run) + resource.run_action(:run) end - + it "returns 1 if the last command was a cmdlet that failed" do resource.code(cmdlet_exit_code_not_found_content) resource.returns(1) - resource.run_action(:run) + resource.run_action(:run) end it "returns 1 if the last command was a cmdlet that failed and was preceded by a successfully executed non-cmdlet Windows binary" do resource.code([windows_process_exit_code_success_content, cmdlet_exit_code_not_found_content].join(';')) resource.returns(1) - resource.run_action(:run) + resource.run_action(:run) end # This somewhat ambiguous case, two failures of different types, @@ -91,34 +90,34 @@ describe Chef::Resource::WindowsScript::PowershellScript, :windows_only do it "returns 1 if the last command was a cmdlet that failed and was preceded by an unsuccessfully executed non-cmdlet Windows binary" do resource.code([arbitrary_nonzero_process_exit_code_content,cmdlet_exit_code_not_found_content].join(';')) resource.returns(arbitrary_nonzero_process_exit_code) - resource.run_action(:run) + resource.run_action(:run) end it "returns 0 if the last command was a non-cmdlet Windows binary that succeeded and was preceded by a failed cmdlet" do resource.code([cmdlet_exit_code_success_content, arbitrary_nonzero_process_exit_code_content].join(';')) resource.returns(arbitrary_nonzero_process_exit_code) - resource.run_action(:run) + resource.run_action(:run) end - + it "returns a specific error code if the last command was a non-cmdlet Windows binary that failed and was preceded by cmdlet that succeeded" do resource.code([cmdlet_exit_code_success_content, arbitrary_nonzero_process_exit_code_content].join(';')) resource.returns(arbitrary_nonzero_process_exit_code) - resource.run_action(:run) + resource.run_action(:run) end it "returns a specific error code if the last command was a non-cmdlet Windows binary that failed and was preceded by cmdlet that failed" do resource.code([cmdlet_exit_code_not_found_content, arbitrary_nonzero_process_exit_code_content].join(';')) resource.returns(arbitrary_nonzero_process_exit_code) - resource.run_action(:run) + resource.run_action(:run) end - + it "executes a script with a 64-bit process on a 64-bit OS, otherwise a 32-bit process" do resource.code(processor_architecture_script_content + " | out-file -encoding ASCII #{script_output_path}") resource.returns(0) resource.run_action(:run) is_64_bit = (ENV['PROCESSOR_ARCHITECTURE'] == 'AMD64') || (ENV['PROCESSOR_ARCHITEW6432'] == 'AMD64') - + detected_64_bit = source_contains_case_insensitive_content?( get_script_output, 'AMD64' ) is_64_bit.should == detected_64_bit @@ -128,15 +127,15 @@ describe Chef::Resource::WindowsScript::PowershellScript, :windows_only do resource.code(cmdlet_exit_code_success_content) resource.flags(invalid_powershell_interpreter_flag) resource.returns(1) - resource.run_action(:run) + resource.run_action(:run) end it "returns 0 if a valid flag is passed to the interpreter" do resource.code(cmdlet_exit_code_success_content) resource.flags(valid_powershell_interpreter_flag) resource.returns(0) - resource.run_action(:run) - end + resource.run_action(:run) + end end context "when running on a 32-bit version of Windows", :windows32_only do @@ -167,7 +166,7 @@ describe Chef::Resource::WindowsScript::PowershellScript, :windows_only do source_contains_case_insensitive_content?( get_script_output, 'AMD64' ).should == true end - + it "executes a script with a 32-bit process if :i386 arch is specified" do resource.code(processor_architecture_script_content + " | out-file -encoding ASCII #{script_output_path}") resource.architecture(:i386) diff --git a/spec/functional/resource/registry_spec.rb b/spec/functional/resource/registry_spec.rb index fa52640eb7..8f3cfa9a8a 100644 --- a/spec/functional/resource/registry_spec.rb +++ b/spec/functional/resource/registry_spec.rb @@ -104,8 +104,6 @@ describe Chef::Resource::RegistryKey, :windows_only do @new_resource = Chef::Resource::RegistryKey.new(resource_name, @run_context) @registry = Chef::Win32::Registry.new(@run_context) - @current_whyrun = Chef::Config[:why_run] - reset_registry end @@ -259,12 +257,9 @@ describe Chef::Resource::RegistryKey, :windows_only do end context "while running in whyrun mode" do - before (:all) do + before (:each) do Chef::Config[:why_run] = true end - after (:all) do - Chef::Config[:why_run] = @current_whyrun - end it "does not throw an exception if the keys do not exist but recursive is set to false" do @new_resource.key(reg_child + '\Slitheen\Raxicoricofallapatorius') @@ -373,12 +368,9 @@ describe Chef::Resource::RegistryKey, :windows_only do end context "while running in whyrun mode" do - before (:all) do + before (:each) do Chef::Config[:why_run] = true end - after (:all) do - Chef::Config[:why_run] = @current_whyrun - end it "does not throw an exception if the keys do not exist but recursive is set to false" do @new_resource.key(reg_child + '\Zygons\Zygor') @@ -469,12 +461,9 @@ describe Chef::Resource::RegistryKey, :windows_only do end context "while running in whyrun mode" do - before (:all) do + before (:each) do Chef::Config[:why_run] = true end - after (:all) do - Chef::Config[:why_run] = @current_whyrun - end it "does nothing if the action is delete" do @new_resource.key(reg_parent + '\OpscodeWhyRun') @new_resource.values([{:name=>"BriskWalk",:type=>:string,:data=>"is good for health"}]) @@ -510,7 +499,7 @@ describe Chef::Resource::RegistryKey, :windows_only do @registry.key_exists?(reg_parent + '\OpscodeTest').should == false end - it "raises an exception if the the key has subkeys and recursive == false" do + it "raises an exception if the key has subkeys and recursive == false" do @new_resource.key(reg_parent) @new_resource.recursive(false) lambda{@new_resource.run_action(:delete_key)}.should raise_error(Chef::Exceptions::Win32RegNoRecursive) @@ -549,12 +538,9 @@ describe Chef::Resource::RegistryKey, :windows_only do @report["total_res_count"].should == "1" end context "while running in whyrun mode" do - before (:all) do + before (:each) do Chef::Config[:why_run] = true end - after (:all) do - Chef::Config[:why_run] = @current_whyrun - end it "does not throw an exception if the key has subkeys but recursive is set to false" do @new_resource.key(reg_parent + '\OpscodeWhyRun') diff --git a/spec/functional/resource/rpm_spec.rb b/spec/functional/resource/rpm_spec.rb new file mode 100644 index 0000000000..7825377c6b --- /dev/null +++ b/spec/functional/resource/rpm_spec.rb @@ -0,0 +1,122 @@ +# +# Author:: Prabhu Das (<prabhu.das@clogeny.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 'functional/resource/base' +require 'chef/mixin/shell_out' + +# run this test only for following platforms. +exclude_test = !['aix', 'centos', 'redhat', 'suse'].include?(ohai[:platform]) +describe Chef::Resource::RpmPackage, :requires_root, :external => exclude_test do + include Chef::Mixin::ShellOut + + let(:new_resource) do + new_resource = Chef::Resource::RpmPackage.new(@pkg_name, run_context) + new_resource.source @pkg_path + new_resource + end + + def rpm_pkg_should_be_installed(resource) + case ohai[:platform] + # Due to dependency issues , different rpm pkgs are used in different platforms. + # dummy rpm package works in aix, without any dependency issues. + when "aix" + expect(shell_out("rpm -qa | grep dummy").exitstatus).to eq(0) + # mytest rpm package works in centos, redhat and in suse without any dependency issues. + when "centos", "redhat", "suse" + expect(shell_out("rpm -qa | grep mytest").exitstatus).to eq(0) + ::File.exists?("/opt/mytest/mytest.sh") # The mytest rpm package contains the mytest.sh file + end + end + + def rpm_pkg_should_not_be_installed(resource) + case ohai[:platform] + when "aix" + expect(shell_out("rpm -qa | grep dummy").exitstatus).to eq(1) + when "centos", "redhat", "suse" + expect(shell_out("rpm -qa | grep mytest").exitstatus).to eq(1) + !::File.exists?("/opt/mytest/mytest.sh") + end + end + + before(:all) do + case ohai[:platform] + # Due to dependency issues , different rpm pkgs are used in different platforms. + when "aix" + @pkg_name = "dummy" + @pkg_version = "1-0" + @pkg_path = "/tmp/dummy-1-0.aix6.1.noarch.rpm" + FileUtils.cp 'spec/functional/assets/dummy-1-0.aix6.1.noarch.rpm' , @pkg_path + when "centos", "redhat", "suse" + @pkg_name = "mytest" + @pkg_version = "1.0-1" + @pkg_path = "/tmp/mytest-1.0-1.noarch.rpm" + FileUtils.cp 'spec/functional/assets/mytest-1.0-1.noarch.rpm' , @pkg_path + end + end + + after(:all) do + FileUtils.rm @pkg_path + end + + context "package install action" do + it "should create a package" do + new_resource.run_action(:install) + rpm_pkg_should_be_installed(new_resource) + end + + after(:each) do + shell_out("rpm -qa | grep #{@pkg_name}-#{@pkg_version} | xargs rpm -e") + end + end + + context "package remove action" do + before(:each) do + shell_out("rpm -i #{@pkg_path}") + end + + it "should remove an existing package" do + new_resource.run_action(:remove) + rpm_pkg_should_not_be_installed(new_resource) + end + end + + context "package upgrade action" do + before(:each) do + shell_out("rpm -i #{@pkg_path}") + if ohai[:platform] == 'aix' + @pkg_version = "2-0" + @pkg_path = "/tmp/dummy-2-0.aix6.1.noarch.rpm" + FileUtils.cp 'spec/functional/assets/dummy-2-0.aix6.1.noarch.rpm' , @pkg_path + else + @pkg_version = "2.0-1" + @pkg_path = "/tmp/mytest-2.0-1.noarch.rpm" + FileUtils.cp 'spec/functional/assets/mytest-2.0-1.noarch.rpm' , @pkg_path + end + end + + it "should upgrade a package" do + new_resource.run_action(:install) + rpm_pkg_should_be_installed(new_resource) + end + + after(:each) do + shell_out("rpm -qa | grep #{@pkg_name}-#{@pkg_version} | xargs rpm -e") + FileUtils.rm @pkg_path + end + end +end diff --git a/spec/functional/resource/template_spec.rb b/spec/functional/resource/template_spec.rb index 1882dc051c..7816d6357b 100644 --- a/spec/functional/resource/template_spec.rb +++ b/spec/functional/resource/template_spec.rb @@ -189,54 +189,21 @@ describe Chef::Resource::Template do end describe "when template source contains windows style line endings" do - include_context "diff disabled" - let(:expected_content) { - "Template rendering libraries\r\nshould support\r\ndifferent line endings\r\n\r\n" - } - - context "for all lines" do - let(:resource) do - r = create_resource - r.source "all_windows_line_endings.erb" - r - end - - it "output should contain windows line endings" do - resource.run_action(:create) - binread(path).each_line do |line| - line.should end_with("\r\n") - end - end - end - - context "for some lines" do - let(:resource) do - r = create_resource - r.source "some_windows_line_endings.erb" - r - end - - it "output should contain windows line endings" do - resource.run_action(:create) - binread(path).each_line do |line| - line.should end_with("\r\n") + ["all", "some", "no"].each do |test_case| + context "for #{test_case} lines" do + let(:resource) do + r = create_resource + r.source "#{test_case}_windows_line_endings.erb" + r end - end - end - context "for no lines" do - let(:resource) do - r = create_resource - r.source "no_windows_line_endings.erb" - r - end - - it "output should not contain windows line endings" do - resource.run_action(:create) - IO.read(path).each_line do |line| - line.should_not end_with("\r\n") + it "output should contain platform's line endings" do + resource.run_action(:create) + binread(path).each_line do |line| + line.should end_with(Chef::Platform.windows? ? "\r\n" : "\n") + end end end end diff --git a/spec/functional/resource/user_spec.rb b/spec/functional/resource/user_spec.rb index 7a5f020de9..92248a95bb 100644 --- a/spec/functional/resource/user_spec.rb +++ b/spec/functional/resource/user_spec.rb @@ -54,6 +54,7 @@ describe Chef::Resource::User, metadata do end before do + pending "porting implementation for user provider in aix" if OHAI_SYSTEM[:platform] == 'aix' # Silence shell_out live stream Chef::Log.level = :warn end @@ -497,7 +498,7 @@ describe Chef::Resource::User, metadata do context "and has no password" do # TODO: platform_family should be setup in spec_helper w/ tags - if OHAI_SYSTEM["platform_family"] == "suse" + if %w[suse opensuse].include?(OHAI_SYSTEM["platform_family"]) # suse gets this right: it "errors out trying to unlock the user" do @error.should be_a(Mixlib::ShellOut::ShellCommandFailed) diff --git a/spec/functional/run_lock_spec.rb b/spec/functional/run_lock_spec.rb index 7dc23d41fd..51645c0ae3 100644 --- a/spec/functional/run_lock_spec.rb +++ b/spec/functional/run_lock_spec.rb @@ -20,7 +20,7 @@ require 'chef/client' describe Chef::RunLock do - # This behavior is believed to work on windows, but the tests use UNIX APIs. + # This behavior works on windows, but the tests use fork :( describe "when locking the chef-client run", :unix_only => true do ## @@ -31,7 +31,6 @@ describe Chef::RunLock do "/tmp/#{Kernel.rand(Time.now.to_i + Process.pid)}" end - 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. @@ -161,7 +160,7 @@ describe Chef::RunLock do ## # Run lock is the system under test - let!(:run_lock) { Chef::RunLock.new(:file_cache_path => file_cache_path, :lockfile => lockfile) } + let!(:run_lock) { Chef::RunLock.new(lockfile) } it "creates the full path to the lockfile" do lambda { run_lock.acquire }.should_not raise_error(Errno::ENOENT) @@ -225,7 +224,6 @@ E Process.kill(:KILL, p1) Process.waitpid2(p1) - p2 = fork do run_lock.acquire record "p2 has lock" @@ -237,7 +235,52 @@ E results.should =~ /p2 has lock\Z/ end - end + it "test returns true and acquires the lock" do + p1 = fork do + run_lock.test.should == true + sleep 2 + exit! 1 + end + + wait_on_lock + + p2 = fork do + run_lock.test.should == false + exit! 0 + end + + Process.waitpid2(p2) + Process.waitpid2(p1) + end + + it "test returns without waiting when the lock is acquired" do + p1 = fork do + run_lock.acquire + sleep 2 + exit! 1 + end + + wait_on_lock + + run_lock.test.should == false + Process.waitpid2(p1) + end + + it "doesn't truncate the lock file so that contents can be read" do + p1 = fork do + run_lock.acquire + run_lock.save_pid + sleep 2 + exit! 1 + end + + wait_on_lock + File.read(lockfile).should == p1.to_s + + Process.waitpid2(p1) + end + + end end diff --git a/spec/functional/shell_spec.rb b/spec/functional/shell_spec.rb index 90f421ca11..64bd28f16c 100644 --- a/spec/functional/shell_spec.rb +++ b/spec/functional/shell_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -16,9 +16,10 @@ # limitations under the License. # -require 'spec_helper' +require 'functional/resource/base' require 'chef/version' require 'chef/shell' +require 'chef/mixin/command/unix' describe Shell do @@ -26,6 +27,7 @@ describe Shell do # not catch cases where chef-shell fails to boot because of changes in # chef/client.rb describe "smoke tests", :unix_only => true do + include Chef::Mixin::Command::Unix def read_until(io, expected_value) start = Time.new @@ -59,32 +61,52 @@ describe Shell do end def run_chef_shell_with(options) - # Windows ruby installs don't (always?) have PTY, - # so hide the require here - require 'pty' - config = File.expand_path("shef-config.rb", CHEF_SPEC_DATA) - path_to_chef_shell = File.expand_path("../../../bin/chef-shell", __FILE__) - reader, writer, pid = PTY.spawn("#{path_to_chef_shell} -c #{config} #{options}") - read_until(reader, "chef >") - yield reader, writer if block_given? - writer.puts('"done"') - output = read_until(reader, '=> "done"') - writer.print("exit\n") - read_until(reader, "exit") - read_until(reader, "\n") - read_until(reader, "\n") - writer.close + case ohai[:platform] + when "aix" + config = File.expand_path("shef-config.rb", CHEF_SPEC_DATA) + path_to_chef_shell = File.expand_path("../../../bin/chef-shell", __FILE__) + output = '' + status = popen4("#{path_to_chef_shell} -c #{config} #{options}", :waitlast => true) do |pid, stdin, stdout, stderr| + read_until(stdout, "chef >") + yield stdout, stdin if block_given? + stdin.write("'done'\n") + output = read_until(stdout, '=> "done"') + stdin.print("exit\n") + read_until(stdout, "\n") + end + + [output, status.exitstatus] + else + # Windows ruby installs don't (always?) have PTY, + # so hide the require here + begin + require 'pty' + config = File.expand_path("shef-config.rb", CHEF_SPEC_DATA) + path_to_chef_shell = File.expand_path("../../../bin/chef-shell", __FILE__) + reader, writer, pid = PTY.spawn("#{path_to_chef_shell} -c #{config} #{options}") + read_until(reader, "chef >") + yield reader, writer if block_given? + writer.puts('"done"') + output = read_until(reader, '=> "done"') + writer.print("exit\n") + read_until(reader, "exit") + read_until(reader, "\n") + read_until(reader, "\n") + writer.close - exitstatus = wait_or_die(pid) + exitstatus = wait_or_die(pid) - [output, exitstatus] - rescue PTY::ChildExited => e - [output, e.status] + [output, exitstatus] + rescue PTY::ChildExited => e + [output, e.status] + end + end end it "boots correctly with -lauto" do output, exitstatus = run_chef_shell_with("-lauto") - exitstatus.should be_success + output.should include("done") + expect(exitstatus).to eq(0) end it "sets the log_level from the command line" do @@ -94,9 +116,7 @@ describe Shell do read_until(out, show_log_level_code) end output.should include("===fatal===") - exitstatus.should be_success + expect(exitstatus).to eq(0) end - end - end diff --git a/spec/functional/tiny_server_spec.rb b/spec/functional/tiny_server_spec.rb index 68ab9e7294..4262d9e536 100644 --- a/spec/functional/tiny_server_spec.rb +++ b/spec/functional/tiny_server_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/functional/win32/versions_spec.rb b/spec/functional/win32/versions_spec.rb index 5cf3a13fd8..acb8bb126d 100644 --- a/spec/functional/win32/versions_spec.rb +++ b/spec/functional/win32/versions_spec.rb @@ -44,7 +44,7 @@ describe "Chef::ReservedNames::Win32::Version", :windows_only do # The name from WMI is actually what we want in Win2k8R2+. # So this expectation sould continue to hold without modification # as new versions of Windows are released. - @current_os_version = host.caption + @current_os_version = host.caption end @version = Chef::ReservedNames::Win32::Version.new @@ -55,10 +55,10 @@ describe "Chef::ReservedNames::Win32::Version", :windows_only do @current_os_version.should include(@version.marketing_name) end end - + def is_windows_server_2008?(wmi_host) is_win2k8 = false - + os_version = wmi_host.send('Version') # The operating system version is a string in the following form diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb new file mode 100644 index 0000000000..839899d059 --- /dev/null +++ b/spec/integration/client/client_spec.rb @@ -0,0 +1,146 @@ +require 'support/shared/integration/integration_helper' +require 'chef/mixin/shell_out' + +describe "chef-client" do + extend IntegrationSupport + include Chef::Mixin::ShellOut + + when_the_repository "has a cookbook with a no-op recipe" do + file 'cookbooks/x/recipes/default.rb', '' + + it "should complete with success" do + file 'config/client.rb', <<EOM +local_mode true +cookbook_path "#{path_to('cookbooks')}" +EOM + + chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "bin") + result = shell_out("chef-client -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir) + result.error! + end + + context 'and no config file' do + it 'should complete with success when cwd is just above cookbooks and paths are not specified' do + chef_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "bin")) + result = shell_out("#{chef_dir}/chef-client -z -o 'x::default' --config-file-jail \"#{path_to('')}\"", :cwd => path_to('')) + result.error! + end + + it 'should complete with success when cwd is below cookbooks and paths are not specified' do + chef_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "bin")) + result = shell_out("#{chef_dir}/chef-client -z -o 'x::default' --config-file-jail \"#{path_to('')}\"", :cwd => path_to('cookbooks/x')) + result.error! + end + + it 'should fail when cwd is below high above and paths are not specified' do + chef_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "bin")) + result = shell_out("#{chef_dir}/chef-client -z -o 'x::default' --config-file-jail \"#{path_to('')}\"", :cwd => File.expand_path('..', path_to(''))) + result.exitstatus.should == 1 + end + end + + context 'and a config file under .chef/knife.rb' do + file '.chef/knife.rb', 'xxx.xxx' + + it 'should load .chef/knife.rb when -z is specified' do + chef_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "bin")) + result = shell_out("#{chef_dir}/chef-client -z -o 'x::default' --config-file-jail \"#{path_to('')}\"", :cwd => path_to('')) + result.exitstatus.should == 2 + end + + it 'fails to load .chef/knife.rb when -z is specified and --config-file-jail does not include the .chef/knife.rb' do + chef_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "bin")) + result = shell_out("#{chef_dir}/chef-client -z -o 'x::default' --config-file-jail \"#{path_to('roles')}\"", :cwd => path_to('')) + result.error! + end + end + + it "should complete with success" do + file 'config/client.rb', <<EOM +local_mode true +cookbook_path "#{path_to('cookbooks')}" +EOM + + chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "bin") + result = shell_out("chef-client -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir) + result.error! + end + + context 'and a private key' do + file 'mykey.pem', <<EOM +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEApubutqtYYQ5UiA9QhWP7UvSmsfHsAoPKEVVPdVW/e8Svwpyf +0Xef6OFWVmBE+W442ZjLOe2y6p2nSnaq4y7dg99NFz6X+16mcKiCbj0RCiGqCvCk +NftHhTgO9/RFvCbmKZ1RKNob1YzLrFpxBHaSh9po+DGWhApcd+I+op+ZzvDgXhNn +0nauZu3rZmApI/r7EEAOjFedAXs7VPNXhhtZAiLSAVIrwU3ZajtSzgXOxbNzgj5O +AAAMmThK+71qPdffAdO4J198H6/MY04qgtFo7vumzCq0UCaGZfmeI1UNE4+xQWwP +HJ3pDAP61C6Ebx2snI2kAd9QMx9Y78nIedRHPwIDAQABAoIBAHssRtPM1GacWsom +8zfeN6ZbI4KDlbetZz0vhnqDk9NVrpijWlcOP5dwZXVNitnB/HaqCqFvyPDY9JNB +zI/pEFW4QH59FVDP42mVEt0keCTP/1wfiDDGh1vLqVBYl/ZphscDcNgDTzNkuxMx +k+LFVxKnn3w7rGc59lALSkpeGvbbIDjp3LUMlUeCF8CIFyYZh9ZvXe4OCxYdyjxb +i8tnMLKvJ4Psbh5jMapsu3rHQkfPdqzztQUz8vs0NYwP5vWge46FUyk+WNm/IhbJ +G3YM22nwUS8Eu2bmTtADSJolATbCSkOwQ1D+Fybz/4obfYeGaCdOqB05ttubhenV +ShsAb7ECgYEA20ecRVxw2S7qA7sqJ4NuYOg9TpfGooptYNA1IP971eB6SaGAelEL +awYkGNuu2URmm5ElZpwJFFTDLGA7t2zB2xI1FeySPPIVPvJGSiZoFQOVlIg9WQzK +7jTtFQ/tOMrF+bigEUJh5bP1/7HzqSpuOsPjEUb2aoCTp+tpiRGL7TUCgYEAwtns +g3ysrSEcTzpSv7fQRJRk1lkBhatgNd0oc+ikzf74DaVLhBg1jvSThDhiDCdB59mr +Jh41cnR1XqE8jmdQbCDRiFrI1Pq6TPaDZFcovDVE1gue9x86v3FOH2ukPG4d2/Xy +HevXjThtpMMsWFi0JYXuzXuV5HOvLZiP8sN3lSMCgYANpdxdGM7RRbE9ADY0dWK2 +V14ReTLcxP7fyrWz0xLzEeCqmomzkz3BsIUoouu0DCTSw+rvAwExqcDoDylIVlWO +fAifz7SeZHbcDxo+3TsXK7zwnLYsx7YNs2+aIv6hzUUbMNmNmXMcZ+IEwx+mRMTN +lYmZdrA5mr0V83oDFPt/jQKBgC74RVE03pMlZiObFZNtheDiPKSG9Bz6wMh7NWMr +c37MtZLkg52mEFMTlfPLe6ceV37CM8WOhqe+dwSGrYhOU06dYqUR7VOZ1Qr0aZvo +fsNPu/Y0+u7rMkgv0fs1AXQnvz7kvKaF0YITVirfeXMafuKEtJoH7owRbur42cpV +YCAtAoGAP1rHOc+w0RUcBK3sY7aErrih0OPh9U5bvJsrw1C0FIZhCEoDVA+fNIQL +syHLXYFNy0OxMtH/bBAXBGNHd9gf5uOnqh0pYcbe/uRAxumC7Rl0cL509eURiA2T ++vFmf54y9YdnLXaqv+FhJT6B6V7WX7IpU9BMqJY1cJYXHuHG2KA= +-----END RSA PRIVATE KEY----- +EOM + + it "should complete with success even with a client key" do + file 'config/client.rb', <<EOM +local_mode true +client_key "#{path_to('mykey.pem')}" +cookbook_path "#{path_to('cookbooks')}" +EOM + + chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "bin") + result = shell_out("chef-client -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir) + result.error! + end + end + + it "should complete with success when passed the -z flag" do + file 'config/client.rb', <<EOM +chef_server_url 'http://omg.com/blah' +cookbook_path "#{path_to('cookbooks')}" +EOM + + chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "bin") + result = shell_out("chef-client -c \"#{path_to('config/client.rb')}\" -o 'x::default' -z", :cwd => chef_dir) + result.error! + end + + it "should complete with success when passed the --local-mode flag" do + file 'config/client.rb', <<EOM +chef_server_url 'http://omg.com/blah' +cookbook_path "#{path_to('cookbooks')}" +EOM + + chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "bin") + result = shell_out("chef-client -c \"#{path_to('config/client.rb')}\" -o 'x::default' --local-mode", :cwd => chef_dir) + result.error! + end + + it "should complete with success when passed -z and --chef-zero-port" do + file 'config/client.rb', <<EOM +chef_server_url 'http://omg.com/blah' +cookbook_path "#{path_to('cookbooks')}" +EOM + + chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "bin") + result = shell_out("chef-client -c \"#{path_to('config/client.rb')}\" -o 'x::default' -z", :cwd => chef_dir) + result.error! + end + end +end diff --git a/spec/integration/knife/chef_fs_data_store_spec.rb b/spec/integration/knife/chef_fs_data_store_spec.rb new file mode 100644 index 0000000000..255a7b66b7 --- /dev/null +++ b/spec/integration/knife/chef_fs_data_store_spec.rb @@ -0,0 +1,353 @@ +# +# Author:: John Keiser (<jkeiser@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 'support/shared/integration/integration_helper' +require 'chef/knife/list' +require 'chef/knife/delete' +require 'chef/knife/show' +require 'chef/knife/raw' +require 'chef/knife/cookbook_upload' + +describe 'knife raw -z' do + extend IntegrationSupport + include KnifeSupport + + when_the_repository "has one of each thing" do + file 'clients/x.json', {} + file 'cookbooks/x/metadata.rb', 'version "1.0.0"' + file 'data_bags/x/y.json', {} + file 'environments/x.json', {} + file 'nodes/x.json', {} + file 'roles/x.json', {} + file 'users/x.json', {} + + context 'GET /TYPE' do + it 'knife list -z -R returns everything' do + knife('list -z -Rfp /').should_succeed <<EOM +/clients/ +/clients/x.json +/cookbooks/ +/cookbooks/x/ +/cookbooks/x/metadata.rb +/data_bags/ +/data_bags/x/ +/data_bags/x/y.json +/environments/ +/environments/x.json +/nodes/ +/nodes/x.json +/roles/ +/roles/x.json +/users/ +/users/x.json +EOM + end + end + + context 'DELETE /TYPE/NAME' do + it 'knife delete -z /clients/x.json works' do + knife('delete -z /clients/x.json').should_succeed "Deleted /clients/x.json\n" + knife('list -z -Rfp /clients').should_succeed '' + end + + it 'knife delete -z -r /cookbooks/x works' do + knife('delete -z -r /cookbooks/x').should_succeed "Deleted /cookbooks/x\n" + knife('list -z -Rfp /cookbooks').should_succeed '' + end + + it 'knife delete -z -r /data_bags/x works' do + knife('delete -z -r /data_bags/x').should_succeed "Deleted /data_bags/x\n" + knife('list -z -Rfp /data_bags').should_succeed '' + end + + it 'knife delete -z /data_bags/x/y.json works' do + knife('delete -z /data_bags/x/y.json').should_succeed "Deleted /data_bags/x/y.json\n" + knife('list -z -Rfp /data_bags').should_succeed "/data_bags/x/\n" + end + + it 'knife delete -z /environments/x.json works' do + knife('delete -z /environments/x.json').should_succeed "Deleted /environments/x.json\n" + knife('list -z -Rfp /environments').should_succeed '' + end + + it 'knife delete -z /nodes/x.json works' do + knife('delete -z /nodes/x.json').should_succeed "Deleted /nodes/x.json\n" + knife('list -z -Rfp /nodes').should_succeed '' + end + + it 'knife delete -z /roles/x.json works' do + knife('delete -z /roles/x.json').should_succeed "Deleted /roles/x.json\n" + knife('list -z -Rfp /roles').should_succeed '' + end + + it 'knife delete -z /users/x.json works' do + knife('delete -z /users/x.json').should_succeed "Deleted /users/x.json\n" + knife('list -z -Rfp /users').should_succeed '' + end + end + + context 'GET /TYPE/NAME' do + it 'knife show -z /clients/x.json works' do + knife('show -z /clients/x.json').should_succeed /"x"/ + end + + it 'knife show -z /cookbooks/x/metadata.rb works' do + knife('show -z /cookbooks/x/metadata.rb').should_succeed "/cookbooks/x/metadata.rb:\nversion \"1.0.0\"\n" + end + + it 'knife show -z /data_bags/x/y.json works' do + knife('show -z /data_bags/x/y.json').should_succeed /"y"/ + end + + it 'knife show -z /environments/x.json works' do + knife('show -z /environments/x.json').should_succeed /"x"/ + end + + it 'knife show -z /nodes/x.json works' do + knife('show -z /nodes/x.json').should_succeed /"x"/ + end + + it 'knife show -z /roles/x.json works' do + knife('show -z /roles/x.json').should_succeed /"x"/ + end + + it 'knife show -z /users/x.json works' do + knife('show -z /users/x.json').should_succeed /"x"/ + end + end + + context 'PUT /TYPE/NAME' do + file 'empty.json', {} + file 'rolestuff.json', '{"description":"hi there","name":"x"}' + file 'cookbooks_to_upload/x/metadata.rb', "version '1.0.0'\n\n" + + it 'knife raw -z -i empty.json -m PUT /clients/x' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /clients/x").should_succeed /"x"/ + knife('list --local /clients').should_succeed "/clients/x.json\n" + end + + it 'knife cookbook upload works' do + knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} x").should_succeed <<EOM +Uploading x [1.0.0] +Uploaded 1 cookbook. +EOM + knife('list --local -Rfp /cookbooks').should_succeed "/cookbooks/x/\n/cookbooks/x/metadata.rb\n" + end + + it 'knife raw -z -i empty.json -m PUT /data/x/y' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /data/x/y").should_succeed /"y"/ + knife('list --local -Rfp /data_bags').should_succeed "/data_bags/x/\n/data_bags/x/y.json\n" + end + + it 'knife raw -z -i empty.json -m PUT /environments/x' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /environments/x").should_succeed /"x"/ + knife('list --local /environments').should_succeed "/environments/x.json\n" + end + + it 'knife raw -z -i empty.json -m PUT /nodes/x' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /nodes/x").should_succeed /"x"/ + knife('list --local /nodes').should_succeed "/nodes/x.json\n" + end + + it 'knife raw -z -i empty.json -m PUT /roles/x' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /roles/x").should_succeed /"x"/ + knife('list --local /roles').should_succeed "/roles/x.json\n" + end + + it 'knife raw -z -i empty.json -m PUT /users/x' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /users/x").should_succeed /"x"/ + knife('list --local /users').should_succeed "/users/x.json\n" + end + + it 'After knife raw -z -i rolestuff.json -m PUT /roles/x, the output is pretty', :pending => (RUBY_VERSION < "1.9") do + knife("raw -z -i #{path_to('rolestuff.json')} -m PUT /roles/x").should_succeed /"x"/ + IO.read(path_to('roles/x.json')).should == <<EOM.strip +{ + "name": "x", + "description": "hi there" +} +EOM + end + end + end + + when_the_repository 'is empty' do + context 'POST /TYPE/NAME' do + file 'empty.json', { 'name' => 'z' } + file 'empty_id.json', { 'id' => 'z' } + file 'rolestuff.json', '{"description":"hi there","name":"x"}' + file 'cookbooks_to_upload/z/metadata.rb', "version '1.0.0'" + + it 'knife raw -z -i empty.json -m POST /clients' do + knife("raw -z -i #{path_to('empty.json')} -m POST /clients").should_succeed /uri/ + knife('list --local /clients').should_succeed "/clients/z.json\n" + end + + it 'knife cookbook upload works' do + knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} z").should_succeed <<EOM +Uploading z [1.0.0] +Uploaded 1 cookbook. +EOM + knife('list --local -Rfp /cookbooks').should_succeed "/cookbooks/z/\n/cookbooks/z/metadata.rb\n" + end + + it 'knife raw -z -i empty.json -m POST /data' do + knife("raw -z -i #{path_to('empty.json')} -m POST /data").should_succeed /uri/ + knife('list --local -Rfp /data_bags').should_succeed "/data_bags/z/\n" + end + + it 'knife raw -z -i empty.json -m POST /data/x' do + knife("raw -z -i #{path_to('empty_id.json')} -m POST /data/x").should_succeed /"z"/ + knife('list --local -Rfp /data_bags').should_succeed "/data_bags/x/\n/data_bags/x/z.json\n" + end + + it 'knife raw -z -i empty.json -m POST /environments' do + knife("raw -z -i #{path_to('empty.json')} -m POST /environments").should_succeed /uri/ + knife('list --local /environments').should_succeed "/environments/z.json\n" + end + + it 'knife raw -z -i empty.json -m POST /nodes' do + knife("raw -z -i #{path_to('empty.json')} -m POST /nodes").should_succeed /uri/ + knife('list --local /nodes').should_succeed "/nodes/z.json\n" + end + + it 'knife raw -z -i empty.json -m POST /roles' do + knife("raw -z -i #{path_to('empty.json')} -m POST /roles").should_succeed /uri/ + knife('list --local /roles').should_succeed "/roles/z.json\n" + end + + it 'knife raw -z -i empty.json -m POST /users' do + knife("raw -z -i #{path_to('empty.json')} -m POST /users").should_succeed /uri/ + knife('list --local /users').should_succeed "/users/z.json\n" + end + + it 'After knife raw -z -i rolestuff.json -m POST /roles, the output is pretty', :pending => (RUBY_VERSION < "1.9") do + knife("raw -z -i #{path_to('rolestuff.json')} -m POST /roles").should_succeed /uri/ + IO.read(path_to('roles/x.json')).should == <<EOM.strip +{ + "name": "x", + "description": "hi there" +} +EOM + end + end + + it 'knife list -z -R returns nothing' do + knife('list -z -Rfp /').should_succeed <<EOM +/clients/ +/cookbooks/ +/data_bags/ +/environments/ +/nodes/ +/roles/ +/users/ +EOM + end + + context 'DELETE /TYPE/NAME' do + it 'knife delete -z /clients/x.json fails with an error' do + knife('delete -z /clients/x.json').should_fail "ERROR: /clients/x.json: No such file or directory\n" + end + + it 'knife delete -z -r /cookbooks/x fails with an error' do + knife('delete -z -r /cookbooks/x').should_fail "ERROR: /cookbooks/x: No such file or directory\n" + end + + it 'knife delete -z -r /data_bags/x fails with an error' do + knife('delete -z -r /data_bags/x').should_fail "ERROR: /data_bags/x: No such file or directory\n" + end + + it 'knife delete -z /data_bags/x/y.json fails with an error' do + knife('delete -z /data_bags/x/y.json').should_fail "ERROR: /data_bags/x/y.json: No such file or directory\n" + end + + it 'knife delete -z /environments/x.json fails with an error' do + knife('delete -z /environments/x.json').should_fail "ERROR: /environments/x.json: No such file or directory\n" + end + + it 'knife delete -z /nodes/x.json fails with an error' do + knife('delete -z /nodes/x.json').should_fail "ERROR: /nodes/x.json: No such file or directory\n" + end + + it 'knife delete -z /roles/x.json fails with an error' do + knife('delete -z /roles/x.json').should_fail "ERROR: /roles/x.json: No such file or directory\n" + end + + it 'knife delete -z /users/x.json fails with an error' do + knife('delete -z /users/x.json').should_fail "ERROR: /users/x.json: No such file or directory\n" + end + end + + context 'GET /TYPE/NAME' do + it 'knife show -z /clients/x.json fails with an error' do + knife('show -z /clients/x.json').should_fail "ERROR: /clients/x.json: No such file or directory\n" + end + + it 'knife show -z /cookbooks/x/metadata.rb fails with an error' do + knife('show -z /cookbooks/x/metadata.rb').should_fail "ERROR: /cookbooks/x/metadata.rb: No such file or directory\n" + end + + it 'knife show -z /data_bags/x/y.json fails with an error' do + knife('show -z /data_bags/x/y.json').should_fail "ERROR: /data_bags/x/y.json: No such file or directory\n" + end + + it 'knife show -z /environments/x.json fails with an error' do + knife('show -z /environments/x.json').should_fail "ERROR: /environments/x.json: No such file or directory\n" + end + + it 'knife show -z /nodes/x.json fails with an error' do + knife('show -z /nodes/x.json').should_fail "ERROR: /nodes/x.json: No such file or directory\n" + end + + it 'knife show -z /roles/x.json fails with an error' do + knife('show -z /roles/x.json').should_fail "ERROR: /roles/x.json: No such file or directory\n" + end + + it 'knife show -z /users/x.json fails with an error' do + knife('show -z /users/x.json').should_fail "ERROR: /users/x.json: No such file or directory\n" + end + end + + context 'PUT /TYPE/NAME' do + file 'empty.json', {} + + it 'knife raw -z -i empty.json -m PUT /clients/x fails with 404' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /clients/x").should_fail /404/ + end + + it 'knife raw -z -i empty.json -m PUT /data/x/y fails with 404' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /data/x/y").should_fail /404/ + end + + it 'knife raw -z -i empty.json -m PUT /environments/x fails with 404' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /environments/x").should_fail /404/ + end + + it 'knife raw -z -i empty.json -m PUT /nodes/x fails with 404' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /nodes/x").should_fail /404/ + end + + it 'knife raw -z -i empty.json -m PUT /roles/x fails with 404' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /roles/x").should_fail /404/ + end + + it 'knife raw -z -i empty.json -m PUT /users/x fails with 404' do + knife("raw -z -i #{path_to('empty.json')} -m PUT /users/x").should_fail /404/ + end + end + end +end diff --git a/spec/integration/knife/chef_repo_path_spec.rb b/spec/integration/knife/chef_repo_path_spec.rb index 11989933a1..4ffb179a4b 100644 --- a/spec/integration/knife/chef_repo_path_spec.rb +++ b/spec/integration/knife/chef_repo_path_spec.rb @@ -52,6 +52,28 @@ describe 'chef_repo_path tests' do file 'users/user3.json', {} end + it 'knife list --local -Rfp --chef-repo-path chef_repo2 / grabs chef_repo2 stuff' do + Chef::Config.delete(:chef_repo_path) + knife("list --local -Rfp --chef-repo-path #{path_to('chef_repo2')} /").should_succeed <<EOM +/clients/ +/clients/client3.json +/cookbooks/ +/cookbooks/cookbook3/ +/cookbooks/cookbook3/metadata.rb +/data_bags/ +/data_bags/bag3/ +/data_bags/bag3/item3.json +/environments/ +/environments/env3.json +/nodes/ +/nodes/node3.json +/roles/ +/roles/role3.json +/users/ +/users/user3.json +EOM + end + context 'when all _paths are set to alternates' do before :each do %w(client cookbook data_bag environment node role user).each do |object_name| @@ -60,6 +82,27 @@ describe 'chef_repo_path tests' do Chef::Config.chef_repo_path = File.join(Chef::Config.chef_repo_path, 'chef_repo2') end + it 'knife list --local -Rfp --chef-repo-path chef_repo2 / grabs chef_repo2 stuff' do + knife("list --local -Rfp --chef-repo-path #{path_to('chef_repo2')} /").should_succeed <<EOM +/clients/ +/clients/client3.json +/cookbooks/ +/cookbooks/cookbook3/ +/cookbooks/cookbook3/metadata.rb +/data_bags/ +/data_bags/bag3/ +/data_bags/bag3/item3.json +/environments/ +/environments/env3.json +/nodes/ +/nodes/node3.json +/roles/ +/roles/role3.json +/users/ +/users/user3.json +EOM + end + context 'when cwd is at the top level' do cwd '.' it 'knife list --local -Rfp fails' do @@ -171,7 +214,7 @@ EOM context 'when only chef_repo_path is set to its alternate' do before :each do %w(client cookbook data_bag environment node role user).each do |object_name| - Chef::Config["#{object_name}_path".to_sym] = nil + Chef::Config.delete("#{object_name}_path".to_sym) end Chef::Config.chef_repo_path = File.join(Chef::Config.chef_repo_path, 'chef_repo2') end @@ -439,7 +482,7 @@ EOM context 'when when chef_repo_path is set to both places and no other _path is set' do before :each do %w(client cookbook data_bag environment node role user).each do |object_name| - Chef::Config["#{object_name}_path".to_sym] = nil + Chef::Config.delete("#{object_name}_path".to_sym) end Chef::Config.chef_repo_path = [ Chef::Config.chef_repo_path, @@ -541,10 +584,10 @@ EOM context 'when cookbook_path is set and nothing else' do before :each do %w(client data_bag environment node role user).each do |object_name| - Chef::Config["#{object_name}_path".to_sym] = nil + Chef::Config.delete("#{object_name}_path".to_sym) end - Chef::Config.cookbook_path = File.join(Chef::Config.chef_repo_path, 'chef_repo2', 'cookbooks') - Chef::Config.chef_repo_path = nil + Chef::Config.delete(:chef_repo_path) + Chef::Config.cookbook_path = File.join(@repository_dir, 'chef_repo2', 'cookbooks') end context 'when cwd is at the top level' do @@ -599,13 +642,13 @@ EOM context 'when cookbook_path is set to multiple places and nothing else is set' do before :each do %w(client data_bag environment node role user).each do |object_name| - Chef::Config["#{object_name}_path".to_sym] = nil + Chef::Config.delete("#{object_name}_path".to_sym) end + Chef::Config.delete(:chef_repo_path) Chef::Config.cookbook_path = [ - File.join(Chef::Config.chef_repo_path, 'cookbooks'), - File.join(Chef::Config.chef_repo_path, 'chef_repo2', 'cookbooks') + File.join(@repository_dir, 'cookbooks'), + File.join(@repository_dir, 'chef_repo2', 'cookbooks') ] - Chef::Config.chef_repo_path = nil end context 'when cwd is at the top level' do @@ -702,7 +745,7 @@ EOM context 'when data_bag_path and chef_repo_path are set, and nothing else' do before :each do %w(client cookbook environment node role user).each do |object_name| - Chef::Config["#{object_name}_path".to_sym] = nil + Chef::Config.delete("#{object_name}_path".to_sym) end Chef::Config.data_bag_path = File.join(Chef::Config.chef_repo_path, 'data_bags') Chef::Config.chef_repo_path = File.join(Chef::Config.chef_repo_path, 'chef_repo2') @@ -760,24 +803,34 @@ EOM context 'when data_bag_path is set and nothing else' do before :each do %w(client cookbook environment node role user).each do |object_name| - Chef::Config["#{object_name}_path".to_sym] = nil + Chef::Config.delete("#{object_name}_path".to_sym) end - Chef::Config.data_bag_path = File.join(Chef::Config.chef_repo_path, 'data_bags') - Chef::Config.chef_repo_path = nil + Chef::Config.delete(:chef_repo_path) + Chef::Config.data_bag_path = File.join(@repository_dir, 'data_bags') end - it 'knife list --local -Rfp / fails' do - knife('list --local -Rfp /').should_fail("ERROR: Must specify either chef_repo_path or cookbook_path in Chef config file\n") + it 'knife list --local -Rfp / lists data bags' do + knife('list --local -Rfp /').should_succeed <<EOM +/data_bags/ +/data_bags/bag/ +/data_bags/bag/item.json +EOM end - it 'knife list --local -Rfp /data_bags fails' do - knife('list --local -Rfp /data_bags').should_fail("ERROR: Must specify either chef_repo_path or cookbook_path in Chef config file\n") + it 'knife list --local -Rfp /data_bags lists data bags' do + knife('list --local -Rfp /data_bags').should_succeed <<EOM +/data_bags/bag/ +/data_bags/bag/item.json +EOM end context 'when cwd is inside the data_bags directory' do cwd 'data_bags' - it 'knife list --local -Rfp fails' do - knife('list --local -Rfp').should_fail("ERROR: Must specify either chef_repo_path or cookbook_path in Chef config file\n") + it 'knife list --local -Rfp lists data bags' do + knife('list --local -Rfp').should_succeed <<EOM +bag/ +bag/item.json +EOM end end end diff --git a/spec/integration/knife/common_options_spec.rb b/spec/integration/knife/common_options_spec.rb new file mode 100644 index 0000000000..6de4d9360b --- /dev/null +++ b/spec/integration/knife/common_options_spec.rb @@ -0,0 +1,103 @@ +# +# Author:: John Keiser (<jkeiser@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 'support/shared/integration/integration_helper' +require 'chef/knife/raw' + +describe 'knife common options' do + extend IntegrationSupport + include KnifeSupport + + when_the_repository "has a node" do + file 'nodes/x.json', {} + + before(:each) do + if ChefZero::RSpec.server + ChefZero::RSpec.server.stop + ChefZero::RSpec.server = nil + end + end + + context 'When chef_zero.enabled is true' do + before(:each) do + Chef::Config.chef_zero.enabled = true + end + + it 'knife raw /nodes/x should retrieve the role' do + knife('raw /nodes/x').should_succeed /"name": "x"/ + end + + context 'And chef_zero.port is 9999' do + before(:each) { Chef::Config.chef_zero.port = 9999 } + + it 'knife raw /nodes/x should retrieve the role' do + knife('raw /nodes/x').should_succeed /"name": "x"/ + Chef::Config.chef_server_url.should == 'http://127.0.0.1:9999' + end + end + + context 'and there is a private key' do + file 'mykey.pem', <<EOM +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEApubutqtYYQ5UiA9QhWP7UvSmsfHsAoPKEVVPdVW/e8Svwpyf +0Xef6OFWVmBE+W442ZjLOe2y6p2nSnaq4y7dg99NFz6X+16mcKiCbj0RCiGqCvCk +NftHhTgO9/RFvCbmKZ1RKNob1YzLrFpxBHaSh9po+DGWhApcd+I+op+ZzvDgXhNn +0nauZu3rZmApI/r7EEAOjFedAXs7VPNXhhtZAiLSAVIrwU3ZajtSzgXOxbNzgj5O +AAAMmThK+71qPdffAdO4J198H6/MY04qgtFo7vumzCq0UCaGZfmeI1UNE4+xQWwP +HJ3pDAP61C6Ebx2snI2kAd9QMx9Y78nIedRHPwIDAQABAoIBAHssRtPM1GacWsom +8zfeN6ZbI4KDlbetZz0vhnqDk9NVrpijWlcOP5dwZXVNitnB/HaqCqFvyPDY9JNB +zI/pEFW4QH59FVDP42mVEt0keCTP/1wfiDDGh1vLqVBYl/ZphscDcNgDTzNkuxMx +k+LFVxKnn3w7rGc59lALSkpeGvbbIDjp3LUMlUeCF8CIFyYZh9ZvXe4OCxYdyjxb +i8tnMLKvJ4Psbh5jMapsu3rHQkfPdqzztQUz8vs0NYwP5vWge46FUyk+WNm/IhbJ +G3YM22nwUS8Eu2bmTtADSJolATbCSkOwQ1D+Fybz/4obfYeGaCdOqB05ttubhenV +ShsAb7ECgYEA20ecRVxw2S7qA7sqJ4NuYOg9TpfGooptYNA1IP971eB6SaGAelEL +awYkGNuu2URmm5ElZpwJFFTDLGA7t2zB2xI1FeySPPIVPvJGSiZoFQOVlIg9WQzK +7jTtFQ/tOMrF+bigEUJh5bP1/7HzqSpuOsPjEUb2aoCTp+tpiRGL7TUCgYEAwtns +g3ysrSEcTzpSv7fQRJRk1lkBhatgNd0oc+ikzf74DaVLhBg1jvSThDhiDCdB59mr +Jh41cnR1XqE8jmdQbCDRiFrI1Pq6TPaDZFcovDVE1gue9x86v3FOH2ukPG4d2/Xy +HevXjThtpMMsWFi0JYXuzXuV5HOvLZiP8sN3lSMCgYANpdxdGM7RRbE9ADY0dWK2 +V14ReTLcxP7fyrWz0xLzEeCqmomzkz3BsIUoouu0DCTSw+rvAwExqcDoDylIVlWO +fAifz7SeZHbcDxo+3TsXK7zwnLYsx7YNs2+aIv6hzUUbMNmNmXMcZ+IEwx+mRMTN +lYmZdrA5mr0V83oDFPt/jQKBgC74RVE03pMlZiObFZNtheDiPKSG9Bz6wMh7NWMr +c37MtZLkg52mEFMTlfPLe6ceV37CM8WOhqe+dwSGrYhOU06dYqUR7VOZ1Qr0aZvo +fsNPu/Y0+u7rMkgv0fs1AXQnvz7kvKaF0YITVirfeXMafuKEtJoH7owRbur42cpV +YCAtAoGAP1rHOc+w0RUcBK3sY7aErrih0OPh9U5bvJsrw1C0FIZhCEoDVA+fNIQL +syHLXYFNy0OxMtH/bBAXBGNHd9gf5uOnqh0pYcbe/uRAxumC7Rl0cL509eURiA2T ++vFmf54y9YdnLXaqv+FhJT6B6V7WX7IpU9BMqJY1cJYXHuHG2KA= +-----END RSA PRIVATE KEY----- +EOM + + it 'knife raw /nodes/x should retrieve the role' do + knife('raw /nodes/x').should_succeed /"name": "x"/ + end + end + end + + it 'knife raw -z /nodes/x retrieves the role' do + knife('raw -z /nodes/x').should_succeed /"name": "x"/ + end + + it 'knife raw --local-mode /nodes/x retrieves the role' do + knife('raw --local-mode /nodes/x').should_succeed /"name": "x"/ + end + + it 'knife raw -z --chef-zero-port=9999 /nodes/x retrieves the role' do + knife('raw -z --chef-zero-port=9999 /nodes/x').should_succeed /"name": "x"/ + Chef::Config.chef_server_url.should == 'http://127.0.0.1:9999' + end + end +end diff --git a/spec/integration/knife/download_spec.rb b/spec/integration/knife/download_spec.rb index a3b3b875a8..ce8df38bd8 100644 --- a/spec/integration/knife/download_spec.rb +++ b/spec/integration/knife/download_spec.rb @@ -258,6 +258,15 @@ EOM D\t/data_bags/x/z.json EOM end + + it 'knife download /data_bags/x /data_bags/x/y.json downloads x once' do + knife('download /data_bags/x /data_bags/x/y.json').should_succeed <<EOM +Created /data_bags +Created /data_bags/x +Created /data_bags/x/y.json +Created /data_bags/x/z.json +EOM + end end end @@ -583,7 +592,7 @@ EOM context 'except the role file is textually different, but not ACTUALLY different' do file 'roles/x.json', <<EOM -{ +{ "chef_type": "role" , "default_attributes": { }, @@ -595,7 +604,7 @@ EOM "override_attributes": { }, "run_list": [ - + ] } EOM @@ -959,4 +968,31 @@ EOM end end end # with versioned cookbooks + + when_the_chef_server 'has a cookbook' do + cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"' } + + when_the_repository 'is empty' do + it 'knife download /cookbooks/x signs all requests' do + + # Check that BasicClient.request() always gets called with X-OPS-USERID + original_new = Chef::HTTP::BasicClient.method(:new) + Chef::HTTP::BasicClient.should_receive(:new) do |args| + new_result = original_new.call(*args) + original_request = new_result.method(:request) + new_result.should_receive(:request) do |method, url, body, headers, &response_handler| + headers['X-OPS-USERID'].should_not be_nil + original_request.call(method, url, body, headers, &response_handler) + end.at_least(:once) + new_result + end.at_least(:once) + + knife('download /cookbooks/x').should_succeed <<EOM +Created /cookbooks +Created /cookbooks/x +Created /cookbooks/x/metadata.rb +EOM + end + end + end end diff --git a/spec/integration/knife/raw_spec.rb b/spec/integration/knife/raw_spec.rb index 002fd4fdc4..b7412e4e8a 100644 --- a/spec/integration/knife/raw_spec.rb +++ b/spec/integration/knife/raw_spec.rb @@ -162,5 +162,68 @@ EOM EOM end end + + context 'When a server returns raw json' do + before :each do + @real_chef_server_url = Chef::Config.chef_server_url + Chef::Config.chef_server_url = "http://127.0.0.1:9018" + app = lambda do |env| + [200, {'Content-Type' => 'application/json' }, ['{ "x": "y", "a": "b" }'] ] + end + @raw_server = Puma::Server.new(app, Puma::Events.new(STDERR, STDOUT)) + @raw_server.add_tcp_listener("127.0.0.1", 9018) + @raw_server.run + end + + after :each do + Chef::Config.chef_server_url = @real_chef_server_url + @raw_server.stop(true) + end + + it 'knife raw /blah returns the prettified json', :pending => (RUBY_VERSION < "1.9") do + knife('raw /blah').should_succeed <<EOM +{ + "x": "y", + "a": "b" +} +EOM + end + + it 'knife raw --no-pretty /blah returns the raw json' do + knife('raw --no-pretty /blah').should_succeed <<EOM +{ "x": "y", "a": "b" } +EOM + end + end + + context 'When a server returns text' do + before :each do + @real_chef_server_url = Chef::Config.chef_server_url + Chef::Config.chef_server_url = "http://127.0.0.1:9018" + app = lambda do |env| + [200, {'Content-Type' => 'text' }, ['{ "x": "y", "a": "b" }'] ] + end + @raw_server = Puma::Server.new(app, Puma::Events.new(STDERR, STDOUT)) + @raw_server.add_tcp_listener("127.0.0.1", 9018) + @raw_server.run + end + + after :each do + Chef::Config.chef_server_url = @real_chef_server_url + @raw_server.stop(true) + end + + it 'knife raw /blah returns the raw text' do + knife('raw /blah').should_succeed(<<EOM, :stderr => "WARN: Expected JSON response, but got content-type 'text'\n") +{ "x": "y", "a": "b" } +EOM + end + + it 'knife raw --no-pretty /blah returns the raw text' do + knife('raw --no-pretty /blah').should_succeed(<<EOM, :stderr => "WARN: Expected JSON response, but got content-type 'text'\n") +{ "x": "y", "a": "b" } +EOM + end + end end end diff --git a/spec/integration/knife/upload_spec.rb b/spec/integration/knife/upload_spec.rb index e0715f761a..46b804205f 100644 --- a/spec/integration/knife/upload_spec.rb +++ b/spec/integration/knife/upload_spec.rb @@ -58,10 +58,10 @@ D\t/roles/x.json D\t/users/admin.json D\t/users/x.json EOM - end + end - it 'knife upload --purge deletes everything' do - knife('upload --purge /').should_succeed(<<EOM, :stderr => "WARNING: /environments/_default.json cannot be deleted (default environment cannot be modified).\n") + it 'knife upload --purge deletes everything' do + knife('upload --purge /').should_succeed(<<EOM, :stderr => "WARNING: /environments/_default.json cannot be deleted (default environment cannot be modified).\n") Deleted extra entry /clients/chef-validator.json (purge is on) Deleted extra entry /clients/chef-webui.json (purge is on) Deleted extra entry /clients/x.json (purge is on) @@ -76,7 +76,7 @@ EOM knife('diff --name-status /').should_succeed <<EOM D\t/environments/_default.json EOM - end + end end when_the_repository 'has an identical copy of each thing' do @@ -239,6 +239,13 @@ EOM EOM JSON.parse(knife('raw /data/x/y').stdout, :create_additions => false).keys.sort.should == [ 'foo', 'id' ] end + + it 'knife upload /data_bags/x /data_bags/x/y.json uploads x once' do + knife('upload /data_bags/x /data_bags/x/y.json').should_succeed <<EOM +Created /data_bags/x +Created /data_bags/x/y.json +EOM + end end when_the_repository 'has a data bag item with keys chef_type and data_bag' do @@ -1057,4 +1064,13 @@ EOM end end # with versioned cookbooks + when_the_chef_server 'has a user' do + user 'x', {} + when_the_repository 'has the same user with json_class in it' do + file 'users/x.json', { 'admin' => true, 'json_class' => 'Chef::WebUIUser' } + it 'knife upload /users/x.json succeeds' do + knife('upload /users/x.json').should_succeed "Updated /users/x.json\n" + end + end + end end diff --git a/spec/integration/solo/solo_spec.rb b/spec/integration/solo/solo_spec.rb index 667a9ad87b..9d2a391477 100644 --- a/spec/integration/solo/solo_spec.rb +++ b/spec/integration/solo/solo_spec.rb @@ -1,41 +1,94 @@ require 'support/shared/integration/integration_helper' require 'chef/mixin/shell_out' +require 'chef/run_lock' +require 'chef/config' +require 'timeout' +require 'fileutils' describe "chef-solo" do extend IntegrationSupport include Chef::Mixin::ShellOut - context "with a no-op recipe in the run_list" do + when_the_repository "has a cookbook with a no-op recipe" do + file 'cookbooks/x/metadata.rb', 'version "1.0.0"' + file 'cookbooks/x/recipes/default.rb', '' - when_the_repository "has a cookbook with a no-op recipe" do - directory 'cookbooks' - directory 'cookbooks/x' - directory 'cookbooks/x/recipes' - file 'cookbooks/x/metadata.rb', 'version "1.0.0"' - file 'cookbooks/x/recipes/default.rb', '' + it "should complete with success" do + file 'config/solo.rb', <<EOM +cookbook_path "#{path_to('cookbooks')}" +file_cache_path "#{path_to('config/cache')}" +EOM + chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "bin") + result = shell_out("chef-solo -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir) + result.error! + end + end - before do - @chef_file_cache = Dir.mktmpdir('file_cache') - end + when_the_repository "has a cookbook with a recipe with sleep" do + directory 'logs' + file 'logs/runs.log', '' + file 'cookbooks/x/metadata.rb', 'version "1.0.0"' + file 'cookbooks/x/recipes/default.rb', <<EOM +ruby_block "sleeping" do + block do + sleep 3 + end +end +EOM + # Ruby 1.8.7 doesn't have Process.spawn :( + it "while running solo concurrently", :ruby_gte_19_only => true do + file 'config/solo.rb', <<EOM +cookbook_path "#{path_to('cookbooks')}" +file_cache_path "#{path_to('config/cache')}" +EOM + # We have a timeout protection here so that if due to some bug + # run_lock gets stuck we can discover it. + lambda { + Timeout.timeout(120) do + chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "bin") - after do - FileUtils.rm_rf(@chef_file_cache) if @chef_file_cache - end + # Instantiate the first chef-solo run + s1 = Process.spawn("chef-solo -c \"#{path_to('config/solo.rb')}\" -o 'x::default' \ +-l debug -L #{path_to('logs/runs.log')}", :chdir => chef_dir) - it "should complete with success" do - # prepare the solo config - directory 'config' - file 'config/solo.rb', <<EOM -cookbook_path "#{File.join(@repository_dir, 'cookbooks')}" -file_cache_path "#{@chef_file_cache}" -EOM - config_file = canonicalize_path(File.join(@repository_dir, 'config', 'solo.rb')) + # Give it some time to progress + sleep 3 - chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..", "bin") - result = shell_out("chef-solo -c \"#{config_file}\" -o 'x::default' -l debug", :cwd => chef_dir) - result.error! - end + # Instantiate the second chef-solo run + s2 = Process.spawn("chef-solo -c \"#{path_to('config/solo.rb')}\" -o 'x::default' \ +-l debug -L #{path_to('logs/runs.log')}", :chdir => chef_dir) + + Process.waitpid(s1) + Process.waitpid(s2) + end + }.should_not raise_error(Timeout::Error) + + # Unfortunately file / directory helpers in integration tests + # are implemented using before(:each) so we need to do all below + # checks in one example. + run_log = File.read(path_to('logs/runs.log')) + # both of the runs should succeed + run_log.lines.reject {|l| !l.include? "INFO: Chef Run complete in"}.length.should == 2 + + # second run should have a message which indicates it's waiting for the first run + pid_lines = run_log.lines.reject {|l| !l.include? "Chef-client pid:"} + pid_lines.length.should == 2 + pids = pid_lines.map {|l| l.split(" ").last} + run_log.should include("Chef client #{pids[0]} is running, will wait for it to finish and then run.") + + # second run should start after first run ends + starts = [ ] + ends = [ ] + run_log.lines.each_with_index do |line, index| + if line.include? "Chef-client pid:" + starts << index + elsif line.include? "INFO: Chef Run complete in" + ends << index + end + end + starts[1].should > ends[0] end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e66f320151..618f782c7c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -67,6 +67,8 @@ require 'chef/applications' require 'chef/shell' require 'chef/util/file_edit' +require 'chef/config' + # If you want to load anything into the testing environment # without versioning it, add it to spec/support/local_gems.rb require 'spec/support/local_gems.rb' if File.exists?(File.join(File.dirname(__FILE__), 'support', 'local_gems.rb')) @@ -107,6 +109,8 @@ RSpec.configure do |config| config.filter_run_excluding :windows32_only => true unless windows32? config.filter_run_excluding :system_windows_service_gem_only => true unless system_windows_service_gem? config.filter_run_excluding :unix_only => true unless unix? + # Remove this filter once these issues are fixed: OC-9764, OC-9765, OC-9766, OC-9767 + config.filter_run_excluding :unsupported_group_provider_platform => true if (os_x? or solaris? or freebsd? or suse?) config.filter_run_excluding :supports_cloexec => true unless supports_cloexec? config.filter_run_excluding :selinux_only => true unless selinux_enabled? config.filter_run_excluding :ruby_18_only => true unless ruby_18? @@ -114,7 +118,8 @@ RSpec.configure do |config| config.filter_run_excluding :ruby_gte_19_only => true unless ruby_gte_19? config.filter_run_excluding :ruby_20_only => true unless ruby_20? config.filter_run_excluding :ruby_gte_20_only => true unless ruby_gte_20? - config.filter_run_excluding :requires_root => true unless ENV['USER'] == 'root' + config.filter_run_excluding :requires_root => true unless ENV['USER'] == 'root' || ENV['LOGIN'] == 'root' + config.filter_run_excluding :requires_root_or_running_windows => true unless (ENV['USER'] == 'root' or windows?) config.filter_run_excluding :requires_unprivileged_user => true if ENV['USER'] == 'root' config.filter_run_excluding :uses_diff => true unless has_diff? @@ -142,4 +147,33 @@ RSpec.configure do |config| config.run_all_when_everything_filtered = true config.treat_symbols_as_metadata_keys_with_true_values = true + + config.before(:each) do + Chef::Config.reset + end +end + +require 'webrick/utils' + +# Webrick uses a centralized/synchronized timeout manager. It works by +# starting a thread to check for timeouts on an interval. The timeout +# checker thread cannot be stopped or canceled in any easy way, and it +# makes calls to Time.new, which fail when rspec is in the process of +# creating a method stub for that method. Since our tests don't rely on +# any timeout behavior enforced by webrick, disable the timeout manager +# via a monkey patch. +# +# Hopefully this fails loudly if the webrick code should change. As of this +# writing, the relevant code is in webrick/utils, which can be located on +# your system with: +# +# $ gem which webrick/utils +module WEBrick + module Utils + class TimeoutHandler + def initialize + @timeout_info = Hash.new + end + end + end end diff --git a/spec/support/lib/chef/provider/easy.rb b/spec/support/lib/chef/provider/easy.rb index 054b45256c..a4d285a838 100644 --- a/spec/support/lib/chef/provider/easy.rb +++ b/spec/support/lib/chef/provider/easy.rb @@ -6,9 +6,9 @@ # 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. @@ -22,11 +22,11 @@ class Chef def load_current_resource true end - + def action_sell true end - + def action_buy true end diff --git a/spec/support/lib/chef/provider/snakeoil.rb b/spec/support/lib/chef/provider/snakeoil.rb index c5d8d52a82..e9d01f654f 100644 --- a/spec/support/lib/chef/provider/snakeoil.rb +++ b/spec/support/lib/chef/provider/snakeoil.rb @@ -6,9 +6,9 @@ # 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. @@ -22,7 +22,7 @@ class Chef def load_current_resource true end - + def action_purr @new_resource.updated_by_last_action(true) true @@ -31,7 +31,7 @@ class Chef def action_sell true end - + def action_buy true end diff --git a/spec/support/lib/chef/resource/cat.rb b/spec/support/lib/chef/resource/cat.rb index 83eb9f08a3..ecca50cb53 100644 --- a/spec/support/lib/chef/resource/cat.rb +++ b/spec/support/lib/chef/resource/cat.rb @@ -6,9 +6,9 @@ # 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. @@ -19,15 +19,15 @@ class Chef class Resource class Cat < Chef::Resource - + attr_accessor :action - + def initialize(name, run_context=nil) @resource_name = :cat super @action = "sell" end - + def pretty_kitty(arg=nil) if arg == true or arg == false @pretty_kitty = arg diff --git a/spec/support/lib/chef/resource/with_state.rb b/spec/support/lib/chef/resource/with_state.rb new file mode 100644 index 0000000000..226de0a6d2 --- /dev/null +++ b/spec/support/lib/chef/resource/with_state.rb @@ -0,0 +1,37 @@ +# +# Author:: Adam Jacob (<adam@opscode.com>) +# Copyright:: Copyright (c) 2008, 2010 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' +require 'chef/json_compat' + +class Chef + class Resource + class WithState < Chef::Resource + attr_accessor :state + + def initialize(name, run_context=nil) + @resource_name = :with_state + super + end + + def state + @state + end + end + end +end diff --git a/spec/support/lib/library_load_order.rb b/spec/support/lib/library_load_order.rb new file mode 100644 index 0000000000..c47a2f2c74 --- /dev/null +++ b/spec/support/lib/library_load_order.rb @@ -0,0 +1,22 @@ +# Helper module to track the load order of library files. +# Used by `cookbook_compiler_spec.rb` +# +# This module must be loaded for any tests that load the cookbook +# data/run_context/cookbooks/test to succeed. +module LibraryLoadOrder + extend self + + def load_order + @load_order ||= [] + end + + def reset! + @load_order = nil + end + + def record(file) + load_order << file + end +end + + diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb index 1aea6dfad3..1501a162e0 100644 --- a/spec/support/platform_helpers.rb +++ b/spec/support/platform_helpers.rb @@ -60,6 +60,10 @@ def freebsd? !!(RUBY_PLATFORM =~ /freebsd/) end +def aix? + !!(RUBY_PLATFORM =~ /aix/) +end + def supports_cloexec? Fcntl.const_defined?('F_SETFD') && Fcntl.const_defined?('FD_CLOEXEC') end @@ -87,3 +91,7 @@ def selinux_enabled? return false end end + +def suse? + File.exists?("/etc/SuSE-release") +end diff --git a/spec/support/shared/functional/file_resource.rb b/spec/support/shared/functional/file_resource.rb index bab421d18d..44048598c7 100644 --- a/spec/support/shared/functional/file_resource.rb +++ b/spec/support/shared/functional/file_resource.rb @@ -18,45 +18,29 @@ shared_context "deploying with move" do before do - @original_atomic_update = Chef::Config[:file_atomic_update] + Chef::Config[:file_backup_path] = CHEF_SPEC_BACKUP_PATH Chef::Config[:file_atomic_update] = true end - - after do - Chef::Config[:file_atomic_update] = @original_atomic_update - end end shared_context "deploying with copy" do before do - @original_atomic_update = Chef::Config[:file_atomic_update] + Chef::Config[:file_backup_path] = CHEF_SPEC_BACKUP_PATH Chef::Config[:file_atomic_update] = false end - - after do - Chef::Config[:file_atomic_update] = @original_atomic_update - end end shared_context "deploying via tmpdir" do before do - @original_stage_via = Chef::Config[:file_staging_uses_destdir] Chef::Config[:file_staging_uses_destdir] = false - end - - after do - Chef::Config[:file_staging_uses_destdir] = @original_stage_via + Chef::Config[:file_backup_path] = CHEF_SPEC_BACKUP_PATH end end shared_context "deploying via destdir" do before do - @original_stage_via = Chef::Config[:file_staging_uses_destdir] Chef::Config[:file_staging_uses_destdir] = true - end - - after do - Chef::Config[:file_staging_uses_destdir] = @original_stage_via + Chef::Config[:file_backup_path] = CHEF_SPEC_BACKUP_PATH end end @@ -75,7 +59,6 @@ shared_examples_for "a file with the wrong content" do context "when running action :create" do context "with backups enabled" do before do - Chef::Config[:file_backup_path] = CHEF_SPEC_BACKUP_PATH resource.run_action(:create) end @@ -99,7 +82,6 @@ shared_examples_for "a file with the wrong content" do context "with backups disabled" do before do - Chef::Config[:file_backup_path] = CHEF_SPEC_BACKUP_PATH resource.backup(0) resource.run_action(:create) end diff --git a/spec/support/shared/functional/windows_script.rb b/spec/support/shared/functional/windows_script.rb new file mode 100644 index 0000000000..afeb4c029c --- /dev/null +++ b/spec/support/shared/functional/windows_script.rb @@ -0,0 +1,48 @@ +# +# 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. +# + +# Shared context used by both Powershell and Batch script provider +# tests. + +shared_context Chef::Resource::WindowsScript do + before(:all) do + + ohai_reader = Ohai::System.new + ohai_reader.require_plugin("os") + ohai_reader.require_plugin("windows::platform") + + new_node = Chef::Node.new + new_node.consume_external_attrs(ohai_reader.data,{}) + + events = Chef::EventDispatch::Dispatcher.new + + @run_context = Chef::RunContext.new(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 diff --git a/spec/support/shared/integration/integration_helper.rb b/spec/support/shared/integration/integration_helper.rb index b7b377ff6a..0c4bf990af 100644 --- a/spec/support/shared/integration/integration_helper.rb +++ b/spec/support/shared/integration/integration_helper.rb @@ -28,30 +28,14 @@ require 'spec_helper' module IntegrationSupport include ChefZero::RSpec - def self.extended(base) - base.before :each do - # We mess with Chef::Config a lot. Save and restore it. - @old_chef_config = Chef::Config.configuration - Chef::Config.configuration = Chef::Config.configuration.dup - Chef::Config.repo_mode = nil - Chef::Config.versioned_cookbooks = nil - end - base.after :each do - Chef::Config.configuration = @old_chef_config - end - end - def when_the_repository(description, *args, &block) context "When the local repository #{description}", *args do before :each do raise "Can only create one directory per test" if @repository_dir @repository_dir = Dir.mktmpdir('chef_repo') - @old_chef_repo_path = Chef::Config.chef_repo_path - @old_paths = {} Chef::Config.chef_repo_path = @repository_dir %w(client cookbook data_bag environment node role user).each do |object_name| - @old_paths[object_name] = Chef::Config["#{object_name}_path".to_sym] - Chef::Config["#{object_name}_path".to_sym] = nil + Chef::Config.delete("#{object_name}_path".to_sym) end end @@ -59,13 +43,11 @@ module IntegrationSupport if @repository_dir begin %w(client cookbook data_bag environment node role user).each do |object_name| - Chef::Config["#{object_name}_path".to_sym] = @old_paths[object_name] + Chef::Config.delete("#{object_name}_path".to_sym) end - Chef::Config.chef_repo_path = @old_chef_repo_path + Chef::Config.delete(:chef_repo_path) FileUtils.remove_entry_secure(@repository_dir) ensure - @old_chef_repo_path = nil - @old_paths = nil @repository_dir = nil end end @@ -150,7 +132,7 @@ module IntegrationSupport _m = { :versioned_cookbooks => true }.merge(_metadata) context 'with versioned cookbooks', _m do before(:each) { Chef::Config[:versioned_cookbooks] = true } - after(:each) { Chef::Config[:versioned_cookbooks] = false } + after(:each) { Chef::Config.delete(:versioned_cookbooks) } instance_eval(&block) end end @@ -160,6 +142,7 @@ module IntegrationSupport context 'with versioned cookbooks', _m do # Just make sure this goes back to default before(:each) { Chef::Config[:versioned_cookbooks] = false } + after(:each) { Chef::Config.delete(:versioned_cookbooks) } instance_eval(&block) end end diff --git a/spec/support/shared/integration/knife_support.rb b/spec/support/shared/integration/knife_support.rb index d2aa153004..036972e18e 100644 --- a/spec/support/shared/integration/knife_support.rb +++ b/spec/support/shared/integration/knife_support.rb @@ -38,7 +38,6 @@ module KnifeSupport # Work on machines where we can't access /var checksums_cache_dir = Dir.mktmpdir('checksums') do |checksums_cache_dir| - old_cache_options = Chef::Config[:cache_options] Chef::Config[:cache_options] = { :path => checksums_cache_dir, :skip_expires => true @@ -84,7 +83,7 @@ module KnifeSupport Chef::Log.level = ( DEBUG ? :debug : :warn ) Chef::Log::Formatter.show_time = false - instance.run + instance.run_with_pretty_exceptions(true) exit_code = 0 @@ -94,7 +93,8 @@ module KnifeSupport ensure Chef::Log.use_log_devices(old_loggers) Chef::Log.level = old_log_level - Chef::Config[:cache_options] = old_cache_options + Chef::Config.delete(:cache_options) + Chef::Config.delete(:concurrency) end KnifeResult.new(stdout.string, stderr.string, exit_code) diff --git a/spec/support/shared/unit/script_resource.rb b/spec/support/shared/unit/script_resource.rb index 0451f4694a..5f37506df6 100644 --- a/spec/support/shared/unit/script_resource.rb +++ b/spec/support/shared/unit/script_resource.rb @@ -7,9 +7,9 @@ # 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. @@ -23,26 +23,26 @@ shared_examples_for "a script resource" do before(:each) do @resource = script_resource - end + 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") diff --git a/spec/support/shared/unit/windows_script_resource.rb b/spec/support/shared/unit/windows_script_resource.rb index 0a0079a287..23dbfbe722 100644 --- a/spec/support/shared/unit/windows_script_resource.rb +++ b/spec/support/shared/unit/windows_script_resource.rb @@ -6,9 +6,9 @@ # 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. @@ -29,10 +29,10 @@ shared_examples_for "a Windows script resource" do node.default["kernel"][:machine] = :x86_64.to_s run_context = Chef::RunContext.new(node, nil, nil) - + @resource = resource_instance - end + end it "should be a kind of Chef::Resource::WindowsScript" do @resource.should be_a_kind_of(Chef::Resource) @@ -40,9 +40,9 @@ shared_examples_for "a Windows script resource" do end context "script" do - let(:script_resource) { resource_instance } - it_should_behave_like "a script resource" + let(:script_resource) { resource_instance } + it_should_behave_like "a script resource" end - + end diff --git a/spec/tiny_server.rb b/spec/tiny_server.rb index fb8dfc6290..340c5d5fb6 100644 --- a/spec/tiny_server.rb +++ b/spec/tiny_server.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/api_client/registration_spec.rb b/spec/unit/api_client/registration_spec.rb index 3efbe9914b..0d21730664 100644 --- a/spec/unit/api_client/registration_spec.rb +++ b/spec/unit/api_client/registration_spec.rb @@ -57,7 +57,7 @@ describe Chef::ApiClient::Registration do end it "creates a new ApiClient on the server using the validator identity" do - response = {"uri" => "https://chef.local/clients/silent-bob", + response = {"uri" => "https://chef.local/clients/silent-bob", "private_key" => "--begin rsa key etc--"} http_mock.should_receive(:post). with("clients", :name => 'silent-bob', :admin => false). diff --git a/spec/unit/api_client_spec.rb b/spec/unit/api_client_spec.rb index 50f22c7066..0df863cb78 100644 --- a/spec/unit/api_client_spec.rb +++ b/spec/unit/api_client_spec.rb @@ -53,6 +53,19 @@ describe Chef::ApiClient do lambda { @client.admin(Hash.new) }.should raise_error(ArgumentError) end + it "has a 'validator' flag attribute" do + @client.validator(true) + @client.validator.should be_true + end + + it "defaults to non-validator" do + @client.validator.should be_false + end + + it "allows only boolean values for the 'validator' flag" do + lambda { @client.validator(false) }.should_not raise_error + lambda { @client.validator(Hash.new) }.should raise_error(ArgumentError) + end it "has a public key attribute" do @client.public_key("super public") @@ -98,6 +111,10 @@ describe Chef::ApiClient do @json.should include(%q{"admin":false}) end + it "includes the 'validator' flag" do + @json.should include(%q{"validator":false}) + end + it "includes the private key when present" do @client.private_key("monkeypants") @client.to_json.should include(%q{"private_key":"monkeypants"}) @@ -115,6 +132,7 @@ describe Chef::ApiClient do "public_key" => "crowes", "private_key" => "monkeypants", "admin" => true, + "validator" => true, "json_class" => "Chef::ApiClient" } @client = Chef::JSONCompat.from_json(client.to_json) @@ -136,6 +154,10 @@ describe Chef::ApiClient do @client.admin.should be_true end + it "preserves the 'validator' status" do + @client.validator.should be_true + end + it "includes the private key if present" do @client.private_key.should == "monkeypants" end @@ -198,7 +220,7 @@ describe Chef::ApiClient do @api_client_with_key.name("lost-my-key") @api_client_with_key.private_key("the new private key") @http_client.should_receive(:put). - with("clients/lost-my-key", :name => "lost-my-key", :admin => false, :private_key => true). + with("clients/lost-my-key", :name => "lost-my-key", :admin => false, :validator => false, :private_key => true). and_return(@api_client_with_key) end @@ -216,7 +238,7 @@ describe Chef::ApiClient do before do @api_client_with_key = {"name" => "lost-my-key", "private_key" => "the new private key"} @http_client.should_receive(:put). - with("clients/lost-my-key", :name => "lost-my-key", :admin => false, :private_key => true). + with("clients/lost-my-key", :name => "lost-my-key", :admin => false, :validator => false, :private_key => true). and_return(@api_client_with_key) end @@ -227,6 +249,7 @@ describe Chef::ApiClient do response.private_key.should == "the new private key" response.name.should == "lost-my-key" response.admin.should be_false + response.validator.should be_false end end diff --git a/spec/unit/application/apply.rb b/spec/unit/application/apply.rb index 7038801a60..0dc24544b0 100644 --- a/spec/unit/application/apply.rb +++ b/spec/unit/application/apply.rb @@ -20,20 +20,12 @@ require 'spec_helper' describe Chef::Application::Apply do before do - @original_config = Chef::Config.configuration @app = Chef::Application::Recipe.new @app.stub!(:configure_logging).and_return(true) @recipe_text = "package 'nyancat'" Chef::Config[:solo] = true end - after do - Chef::Config[:solo] = nil - Chef::Config.configuration.replace(@original_config) - Chef::Config[:solo] = false - end - - describe "configuring the application" do it "should set solo mode to true" do @app.reconfigure @@ -68,7 +60,7 @@ describe Chef::Application::Apply do describe "temp_recipe_file" do before do @app.instance_variable_set(:@recipe_text, @recipe_text) - @app.temp_recipe_file + @app.temp_recipe_file @recipe_fh = @app.instance_variable_get(:@recipe_fh) end it "should open a tempfile" do diff --git a/spec/unit/application/client_spec.rb b/spec/unit/application/client_spec.rb index e894b8f702..c4387890cd 100644 --- a/spec/unit/application/client_spec.rb +++ b/spec/unit/application/client_spec.rb @@ -19,21 +19,20 @@ require 'spec_helper' describe Chef::Application::Client, "reconfigure" do before do - @original_config = Chef::Config.configuration.dup + @original_argv = ARGV.dup + ARGV.clear @app = Chef::Application::Client.new @app.stub!(:configure_opt_parser).and_return(true) @app.stub!(:configure_chef).and_return(true) @app.stub!(:configure_logging).and_return(true) - Chef::Config[:json_attribs] = nil Chef::Config[:interval] = 10 - Chef::Config[:splay] = nil Chef::Config[:once] = false end after do - Chef::Config.configuration.replace(@original_config) + ARGV.replace(@original_argv) end describe "when in daemonized mode and no interval has been set" do @@ -70,49 +69,19 @@ describe Chef::Application::Client, "reconfigure" do describe "when the json_attribs configuration option is specified" do - describe "and the json_attribs matches a HTTP regex" do - before do - @json = StringIO.new({:a=>"b"}.to_json) - @json_tempfile = mock("Tempfile for remote JSON", :open => @json) - @rest = mock("Chef::REST", :get_rest => @json_tempfile) - - Chef::Config[:json_attribs] = "https://foo.com/foo.json" - Chef::REST.stub!(:new).with("https://foo.com/foo.json", nil, nil).and_return(@rest) - @app.stub!(:open).with("/etc/chef/dna.json").and_return(@json) - end - - it "should perform a RESTful GET on the supplied URL" do - @app.reconfigure - @app.chef_client_json.should == {"a" => "b"} - end - end + let(:json_attribs) { {"a" => "b"} } + let(:config_fetcher) { double(Chef::ConfigFetcher, :fetch_json => json_attribs) } + let(:json_source) { "https://foo.com/foo.json" } - describe "and the json_attribs does not match the HTTP regex" do - before do - Chef::Config[:json_attribs] = "/etc/chef/dna.json" - @json = StringIO.new({:a=>"b"}.to_json) - @app.stub!(:open).with("/etc/chef/dna.json").and_return(@json) - end - - it "should parse the json out of the file" do - @app.reconfigure - @app.chef_client_json.should == {"a" => "b"} - end + before do + Chef::Config[:json_attribs] = json_source + Chef::ConfigFetcher.should_receive(:new).with(json_source). + and_return(config_fetcher) end - describe "when parsing fails" do - before do - Chef::Config[:json_attribs] = "/etc/chef/dna.json" - @json = mock("Tempfile", :read => {:a=>"b"}.to_json) - @app.stub!(:open).with("/etc/chef/dna.json").and_return(@json) - Chef::JSONCompat.stub!(:from_json).with(@json.read).and_raise(JSON::ParserError) - Chef::Application.stub!(:fatal!).and_return(true) - end - - it "should hard fail the application" do - Chef::Application.should_receive(:fatal!).with("Could not parse the provided JSON file (/etc/chef/dna.json)!: JSON::ParserError", 2).and_return(true) - @app.reconfigure - end + it "reads the JSON attributes from the specified source" do + @app.reconfigure + @app.chef_client_json.should == json_attribs end end end @@ -137,10 +106,16 @@ end describe Chef::Application::Client, "configure_chef" do before do + @original_argv = ARGV.dup + ARGV.clear @app = Chef::Application::Client.new @app.configure_chef end + after do + ARGV.replace(@original_argv) + end + it "should set the colored output to false by default on windows and true otherwise" do if windows? Chef::Config[:color].should be_false diff --git a/spec/unit/application/solo_spec.rb b/spec/unit/application/solo_spec.rb index 07598dd01c..6dd8c8f147 100644 --- a/spec/unit/application/solo_spec.rb +++ b/spec/unit/application/solo_spec.rb @@ -19,25 +19,15 @@ require 'spec_helper' describe Chef::Application::Solo do before do - @original_config = Chef::Config.configuration - - @app = Chef::Application::Solo.new @app.stub!(:configure_opt_parser).and_return(true) @app.stub!(:configure_chef).and_return(true) @app.stub!(:configure_logging).and_return(true) Chef::Config[:recipe_url] = false Chef::Config[:json_attribs] = false - Chef::Config[:splay] = nil Chef::Config[:solo] = true end - after do - Chef::Config[:solo] = nil - Chef::Config.configuration.replace(@original_config) - Chef::Config[:solo] = false - end - describe "configuring the application" do it "should set solo mode to true" do @app.reconfigure @@ -58,49 +48,19 @@ describe Chef::Application::Solo do describe "when the json_attribs configuration option is specified" do - describe "and the json_attribs matches a HTTP regex" do - before do - @json = StringIO.new({:a=>"b"}.to_json) - @json_tempfile = mock("Tempfile (mock)", :open => @json) - @rest = mock("Chef::REST", :get_rest => @json_tempfile) - - Chef::Config[:json_attribs] = "https://foo.com/foo.json" - Chef::REST.stub!(:new).with("https://foo.com/foo.json", nil, nil).and_return(@rest) - @app.stub!(:open).with("/etc/chef/dna.json").and_return(@json) - end - - it "should perform a RESTful GET on the supplied URL" do - @app.reconfigure - @app.instance_variable_get(:@chef_client_json).should == {"a" => "b"} - end - end + let(:json_attribs) { {"a" => "b"} } + let(:config_fetcher) { double(Chef::ConfigFetcher, :fetch_json => json_attribs) } + let(:json_source) { "https://foo.com/foo.json" } - describe "and the json_attribs does not match the HTTP regex" do - before do - Chef::Config[:json_attribs] = "/etc/chef/dna.json" - @json = StringIO.new({:a=>"b"}.to_json) - @app.stub!(:open).with("/etc/chef/dna.json").and_return(@json) - end - - it "should parse the json out of the file" do - @app.reconfigure - @app.instance_variable_get(:@chef_client_json).should == {"a" => "b"} - end + before do + Chef::Config[:json_attribs] = json_source + Chef::ConfigFetcher.should_receive(:new).with(json_source). + and_return(config_fetcher) end - describe "when parsing fails" do - before do - Chef::Config[:json_attribs] = "/etc/chef/dna.json" - @json = mock("Tempfile", :read => {:a=>"b"}.to_json) - @app.stub!(:open).with("/etc/chef/dna.json").and_return(@json) - Chef::JSONCompat.stub!(:from_json).with(@json.read).and_raise(JSON::ParserError) - Chef::Application.stub!(:fatal!).and_return(true) - end - - it "should hard fail the application" do - Chef::Application.should_receive(:fatal!).with("Could not parse the provided JSON file (/etc/chef/dna.json)!: JSON::ParserError", 2).and_return(true) - @app.reconfigure - end + it "reads the JSON attributes from the specified source" do + @app.reconfigure + @app.chef_solo_json.should == json_attribs end end diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb index f3df8c14cd..1606c82531 100644 --- a/spec/unit/application_spec.rb +++ b/spec/unit/application_spec.rb @@ -20,15 +20,17 @@ require 'spec_helper' describe Chef::Application do before do - @original_conf = Chef::Config.configuration + @original_argv = ARGV.dup + ARGV.clear Chef::Log.logger = Logger.new(StringIO.new) @app = Chef::Application.new Dir.stub!(:chdir).and_return(0) @app.stub!(:reconfigure) + Chef::Log.init(STDERR) end after do - Chef::Config.configuration.replace(@original_conf) + ARGV.replace(@original_argv) end describe "reconfigure" do @@ -94,28 +96,30 @@ describe Chef::Application do end describe "when a config_file is present" do - before do - Chef::Config.configuration.delete('rspec_ran') - - @config_file = Tempfile.new("rspec-chef-config") - @config_file.puts("rspec_ran('true')") - @config_file.close + let(:config_content) { "rspec_ran('true')" } + let(:config_location) { "/etc/chef/default.rb" } - @app.config[:config_file] = "/etc/chef/default.rb" + let(:config_location_pathname) do + p = Pathname.new(config_location) + p.stub(:realpath).and_return(config_location) + p end - after do - @config_file.unlink + before do + @app.config[:config_file] = config_location + Pathname.stub(:new).with(config_location).and_return(config_location_pathname) + File.should_receive(:read). + with(config_location). + and_return(config_content) end it "should configure chef::config from a file" do - File.should_receive(:open).with("/etc/chef/default.rb").and_yield(@config_file) - Chef::Config.should_receive(:from_file).with(@config_file.path) + Chef::Config.should_receive(:from_string).with(config_content, config_location) @app.configure_chef end it "should merge the local config hash into chef::config" do - File.should_receive(:open).with("/etc/chef/default.rb").and_yield(@config_file) + #File.should_receive(:open).with("/etc/chef/default.rb").and_yield(@config_file) @app.configure_chef Chef::Config.rspec_ran.should == "true" end @@ -127,9 +131,9 @@ describe Chef::Application do @app.config[:config_file] = nil end - it "should raise a fatal" do + it "should emit a warning" do Chef::Config.should_not_receive(:from_file).with("/etc/chef/default.rb") - Chef::Application.should_receive(:fatal!) + Chef::Log.should_receive(:warn).with("No config file found or specified on command line, using command line options.") @app.configure_chef end end @@ -143,36 +147,6 @@ describe Chef::Application do @app.configure_chef end end - - describe "when the config_file is an URL" do - before do - Chef::Config.configuration.delete('rspec_ran') - - @app.config[:config_file] = "http://example.com/foo.rb" - - @config_file = Tempfile.new("rspec-chef-config") - @config_file.puts("rspec_ran('true')") - @config_file.close - - - @cf = mock("cf") - #@cf.stub!(:path).and_return("/tmp/some/path") - #@cf.stub!(:nil?).and_return(false) - @rest = mock("rest") - #@rest.stub!(:get_rest).and_return(@rest) - #@rest.stub!(:open).and_yield(@cf) - Chef::REST.stub!(:new).and_return(@rest) - end - - after {@config_file.unlink} - - it "should configure chef::config from an URL" do - Chef::REST.should_receive(:new).with("", nil, nil).at_least(1).times.and_return(@rest) - @rest.should_receive(:fetch).with("http://example.com/foo.rb").and_yield(@config_file) - @app.configure_chef - Chef::Config.rspec_ran.should == "true" - end - end end describe "when configuring the logger" do @@ -189,17 +163,8 @@ describe Chef::Application do @app.configure_logging end - it "should initialise the chef logger level" do - Chef::Log.should_receive(:level=).with(Chef::Config[:log_level]).and_return(true) - @app.configure_logging - end - - context "and log_level is :auto" do - before do - Chef::Config[:log_level] = :auto - end - - context "and STDOUT is to a tty" do + shared_examples_for "log_level_is_auto" do + context "when STDOUT is to a tty" do before do STDOUT.stub!(:tty?).and_return(true) end @@ -209,7 +174,7 @@ describe Chef::Application do Chef::Log.level.should == :warn end - context "and force_logger is configured" do + context "when force_logger is configured" do before do Chef::Config[:force_logger] = true end @@ -221,7 +186,7 @@ describe Chef::Application do end end - context "and STDOUT is not to a tty" do + context "when STDOUT is not to a tty" do before do STDOUT.stub!(:tty?).and_return(false) end @@ -231,7 +196,7 @@ describe Chef::Application do Chef::Log.level.should == :info end - context "and force_formatter is configured" do + context "when force_formatter is configured" do before do Chef::Config[:force_formatter] = true end @@ -241,7 +206,18 @@ describe Chef::Application do end end end + end + + context "when log_level is not set" do + it_behaves_like "log_level_is_auto" + end + + context "when log_level is :auto" do + before do + Chef::Config[:log_level] = :auto + end + it_behaves_like "log_level_is_auto" end end @@ -293,34 +269,29 @@ describe Chef::Application do end end - describe "configuration errors" do - before do - Process.stub!(:exit).and_return(true) - end - - def raises_informative_fatals_on_configure_chef - config_file_regexp = Regexp.new @app.config[:config_file] - Chef::Log.should_receive(:fatal).with(config_file_regexp).and_return(true) - @app.configure_chef - end - - def warns_informatively_on_configure_chef + context "when the config file is not available" do + it "should warn for bad config file path" do + @app.config[:config_file] = "/tmp/non-existing-dir/file" config_file_regexp = Regexp.new @app.config[:config_file] Chef::Log.should_receive(:warn).at_least(:once).with(config_file_regexp).and_return(true) Chef::Log.should_receive(:warn).any_number_of_times.and_return(true) @app.configure_chef end + end - it "should warn for bad config file path" do - @app.config[:config_file] = "/tmp/non-existing-dir/file" - warns_informatively_on_configure_chef + describe "configuration errors" do + before do + Process.should_receive(:exit) end - it "should raise informative fatals for bad config file url" do - non_existing_url = "http://its-stubbed.com/foo.rb" - @app.config[:config_file] = non_existing_url - Chef::REST.any_instance.stub(:fetch).with(non_existing_url).and_raise(SocketError) - raises_informative_fatals_on_configure_chef + def raises_informative_fatals_on_configure_chef + config_file_regexp = Regexp.new @app.config[:config_file] + Chef::Log.should_receive(:fatal). + with(/Configuration error/) + Chef::Log.should_receive(:fatal). + with(config_file_regexp). + at_least(1).times + @app.configure_chef end describe "when config file exists but contains errors" do diff --git a/spec/unit/checksum/storage/filesystem_spec.rb b/spec/unit/checksum/storage/filesystem_spec.rb index a39644202e..144dc69ff1 100644 --- a/spec/unit/checksum/storage/filesystem_spec.rb +++ b/spec/unit/checksum/storage/filesystem_spec.rb @@ -27,16 +27,17 @@ describe Chef::Checksum::Storage::Filesystem do @now = Time.now Time.stub!(:now).and_return(@now) + Chef::Config.stub!(:checksum_path).and_return("/var/chef/checksums") @checksum_of_the_file = "3fafecfb15585ede6b840158cbc2f399" - @storage = Chef::Checksum::Storage::Filesystem.new(Chef::Config.checksum_path, @checksum_of_the_file) + @storage = Chef::Checksum::Storage::Filesystem.new("/not/used/path", @checksum_of_the_file) end it "has the path to the file in the checksum repo" do @storage.file_location.should == "/var/chef/checksums/3f/3fafecfb15585ede6b840158cbc2f399" end - it "has the path the the file's subdirectory in the checksum repo" do + it "has the path the file's subdirectory in the checksum repo" do @storage.checksum_repo_directory.should == "/var/chef/checksums/3f" end diff --git a/spec/unit/chef_fs/file_system/operation_failed_error_spec.rb b/spec/unit/chef_fs/file_system/operation_failed_error_spec.rb new file mode 100644 index 0000000000..570246c41f --- /dev/null +++ b/spec/unit/chef_fs/file_system/operation_failed_error_spec.rb @@ -0,0 +1,47 @@ +# +# Author:: John Keiser (<jkeiser@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/chef_fs/file_system/operation_failed_error' + +describe Chef::ChefFS::FileSystem::OperationFailedError do + context 'message' do + let(:error_message) { 'HTTP error writing: 400 "Bad Request"' } + + context 'has a cause attribute and HTTP result code is 400' do + it 'include error cause' do + allow_message_expectations_on_nil + response_body = '{"error":["Invalid key test in request body"]}' + @response.stub(:code).and_return("400") + @response.stub(:body).and_return(response_body) + exception = Net::HTTPServerException.new("(exception) unauthorized", @response) + proc { + raise Chef::ChefFS::FileSystem::OperationFailedError.new(:write, self, exception), error_message + }.should raise_error(Chef::ChefFS::FileSystem::OperationFailedError, "#{error_message} cause: #{response_body}") + end + end + + context 'does not have a cause attribute' do + it 'does not include error cause' do + proc { + raise Chef::ChefFS::FileSystem::OperationFailedError.new(:write, self), error_message + }.should raise_error(Chef::ChefFS::FileSystem::OperationFailedError, error_message) + end + end + end +end diff --git a/spec/unit/chef_spec.rb b/spec/unit/chef_spec.rb index cf60e64629..b0f0359806 100644 --- a/spec/unit/chef_spec.rb +++ b/spec/unit/chef_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb index 6f0c2b9da5..67eb97f5c2 100644 --- a/spec/unit/client_spec.rb +++ b/spec/unit/client_spec.rb @@ -74,23 +74,13 @@ shared_examples_for Chef::Client do end describe "configuring output formatters" do - before do - @original_config = Chef::Config.configuration - end - - after do - Chef::Config.configuration.replace(@original_config) - end context "when no formatter has been configured" do before do - Chef::Config.formatters.clear @client = Chef::Client.new end context "and STDOUT is a TTY" do before do - Chef::Config[:force_formatter] = false - Chef::Config[:force_logger] = false STDOUT.stub!(:tty?).and_return(true) end @@ -114,7 +104,6 @@ shared_examples_for Chef::Client do context "and STDOUT is not a TTY" do before do - Chef::Config[:force_formatter] = false STDOUT.stub!(:tty?).and_return(false) end @@ -137,7 +126,6 @@ shared_examples_for Chef::Client do context "when a formatter is configured" do context "with no output path" do before do - Chef::Config.formatters.clear @client = Chef::Client.new Chef::Config.add_formatter(:min) end @@ -156,7 +144,6 @@ shared_examples_for Chef::Client do context "with an output path" do before do - Chef::Config.formatters.clear @client = Chef::Client.new @tmpout = Tempfile.open("rspec-for-client-formatter-selection-#{Process.pid}") Chef::Config.add_formatter(:min, @tmpout.path) @@ -226,6 +213,7 @@ shared_examples_for Chef::Client do mock_chef_rest_for_node_save.should_receive(:put_rest).with("nodes/#{@fqdn}", @node).and_return(true) Chef::RunLock.any_instance.should_receive(:acquire) + Chef::RunLock.any_instance.should_receive(:save_pid) Chef::RunLock.any_instance.should_receive(:release) # Post conditions: check that node has been filled in correctly @@ -463,19 +451,15 @@ shared_examples_for Chef::Client do end describe Chef::Client do + Chef::Config[:client_fork] = false it_behaves_like Chef::Client end describe "Chef::Client Forked" do before do - @original_config = Chef::Config.configuration Chef::Config[:client_fork] = true end - after do - Chef::Config.configuration.replace(@original_config) - end - it_behaves_like Chef::Client end diff --git a/spec/unit/config_fetcher_spec.rb b/spec/unit/config_fetcher_spec.rb new file mode 100644 index 0000000000..c29521806a --- /dev/null +++ b/spec/unit/config_fetcher_spec.rb @@ -0,0 +1,98 @@ +require 'spec_helper' +require 'chef/config_fetcher' +describe Chef::ConfigFetcher do + let(:valid_json) { {:a=>"b"}.to_json } + let(:invalid_json) { %q[{"syntax-error": "missing quote}] } + let(:http) { double("Chef::HTTP::Simple") } + + let(:config_location_regex) { Regexp.escape(config_location) } + let(:invalid_json_error_regex) { %r[Could not parse the provided JSON file \(#{config_location_regex}\)] } + + let(:config_jail_path) { nil } + + let(:fetcher) { Chef::ConfigFetcher.new(config_location, config_jail_path) } + + context "when loading a local file" do + let(:config_location) { "/etc/chef/client.rb" } + let(:config_content) { "# The client.rb content" } + + it "reads the file from disk" do + ::File.should_receive(:read). + with(config_location). + and_return(config_content) + fetcher.read_config.should == config_content + end + + context "and consuming JSON" do + + let(:config_location) { "/etc/chef/first-boot.json" } + + + it "returns the parsed JSON" do + ::File.should_receive(:read). + with(config_location). + and_return(valid_json) + + fetcher.fetch_json.should == {"a" => "b"} + end + + context "and the JSON is invalid" do + + it "reports the JSON error" do + + + ::File.should_receive(:read). + with(config_location). + and_return(invalid_json) + + Chef::Application.should_receive(:fatal!). + with(invalid_json_error_regex, 2) + fetcher.fetch_json + end + end + end + + end + + context "when loading a file over HTTP" do + + let(:config_location) { "https://example.com/client.rb" } + let(:config_content) { "# The client.rb content" } + + before do + Chef::HTTP::Simple.should_receive(:new). + with(config_location). + and_return(http) + end + + it "reads the file over HTTP" do + http.should_receive(:get). + with("").and_return(config_content) + fetcher.read_config.should == config_content + end + + context "and consuming JSON" do + let(:config_location) { "https://example.com/foo.json" } + + it "fetches the file and parses it" do + http.should_receive(:get). + with("").and_return(valid_json) + fetcher.fetch_json.should == {"a" => "b"} + end + + context "and the JSON is invalid" do + it "reports the JSON error" do + http.should_receive(:get). + with("").and_return(invalid_json) + + Chef::Application.should_receive(:fatal!). + with(invalid_json_error_regex, 2) + fetcher.fetch_json + end + end + end + + end + + +end diff --git a/spec/unit/config_spec.rb b/spec/unit/config_spec.rb index 5d10b6927b..cb48ab5bcc 100644 --- a/spec/unit/config_spec.rb +++ b/spec/unit/config_spec.rb @@ -22,7 +22,6 @@ require 'chef/exceptions' describe Chef::Config do before(:all) do - @original_config = Chef::Config.hash_dup @original_env = { 'HOME' => ENV['HOME'], 'SYSTEMDRIVE' => ENV['SYSTEMDRIVE'], 'HOMEPATH' => ENV['HOMEPATH'], 'USERPROFILE' => ENV['USERPROFILE'] } end @@ -82,22 +81,18 @@ describe Chef::Config do # log_level = info or defualt # end # - before do - @config_class = Class.new(Chef::Config) - end - it "has an empty list of formatters by default" do - @config_class.formatters.should == [] + Chef::Config.formatters.should == [] end it "configures a formatter with a short name" do - @config_class.add_formatter(:doc) - @config_class.formatters.should == [[:doc, nil]] + Chef::Config.add_formatter(:doc) + Chef::Config.formatters.should == [[:doc, nil]] end it "configures a formatter with a file output" do - @config_class.add_formatter(:doc, "/var/log/formatter.log") - @config_class.formatters.should == [[:doc, "/var/log/formatter.log"]] + Chef::Config.add_formatter(:doc, "/var/log/formatter.log") + Chef::Config.formatters.should == [[:doc, "/var/log/formatter.log"]] end end @@ -142,10 +137,6 @@ describe Chef::Config do and_return(@mockfile) end - after do - Chef::Config.log_location = STDOUT - end - it "should configure itself to use a File object based upon the String" do Chef::Config.log_location = "/var/log/chef/client.log" Chef::Config.log_location.path.should == "/var/log/chef/client.log" @@ -174,15 +165,6 @@ describe Chef::Config do end describe "default values" do - before(:each) do - # reload Chef::Config to ensure defaults are truely active - load File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "chef", "config.rb")) - end - - after(:each) do - # reload spec helper to re-set any spec specific Chef::Config values - load File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper.rb")) - end it "Chef::Config[:file_backup_path] defaults to /var/chef/backup" do backup_path = if windows? @@ -220,6 +202,70 @@ describe Chef::Config do Chef::Config[:environment_path].should == environment_path end + + describe "joining platform specific paths" do + + context "on UNIX" do + before do + Chef::Config.stub(:on_windows?).and_return(false) + end + + it "joins components when some end with separators" do + Chef::Config.path_join("/foo/", "bar", "baz").should == "/foo/bar/baz" + end + + it "joins components that don't end in separators" do + Chef::Config.path_join("/foo", "bar", "baz").should == "/foo/bar/baz" + end + + end + + context "on Windows" do + before do + Chef::Config.stub(:on_windows?).and_return(true) + end + + it "joins components with the windows separator" do + Chef::Config.path_join('c:\\foo\\', 'bar', "baz").should == 'c:\\foo\\bar\\baz' + end + end + end + + describe "setting the config dir" do + + before do + Chef::Config.stub(:on_windows?).and_return(false) + Chef::Config.config_file = "/etc/chef/client.rb" + end + + context "by default" do + it "is the parent dir of the config file" do + Chef::Config.config_dir.should == "/etc/chef" + end + end + + context "when chef is running in local mode" do + before do + Chef::Config.local_mode = true + Chef::Config.user_home = "/home/charlie" + end + + it "is in the user's home dir" do + Chef::Config.config_dir.should == "/home/charlie/.chef/" + end + end + + context "when explicitly set" do + before do + Chef::Config.config_dir = "/other/config/dir/" + end + + it "uses the explicit value" do + Chef::Config.config_dir.should == "/other/config/dir/" + end + end + + end end describe "Chef::Config[:user_home]" do @@ -278,8 +324,4 @@ describe Chef::Config do expect{Chef::Config.log_location = missing_path}.to raise_error Chef::Exceptions::ConfigurationError end end - - after(:each) do - Chef::Config.configuration = @original_config - end end diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb index 2757f92506..9822146131 100644 --- a/spec/unit/cookbook/metadata_spec.rb +++ b/spec/unit/cookbook/metadata_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -20,7 +20,7 @@ require 'spec_helper' require 'chef/cookbook/metadata' -describe Chef::Cookbook::Metadata do +describe Chef::Cookbook::Metadata do before(:each) do @cookbook = Chef::CookbookVersion.new('test_cookbook') @meta = Chef::Cookbook::Metadata.new(@cookbook) @@ -86,7 +86,7 @@ describe Chef::Cookbook::Metadata do it "should return a Chef::Cookbook::Metadata object" do @meta.should be_a_kind_of(Chef::Cookbook::Metadata) end - + it "should allow a cookbook as the first argument" do lambda { Chef::Cookbook::Metadata.new(@cookbook) }.should_not raise_error end @@ -96,7 +96,7 @@ describe Chef::Cookbook::Metadata do end it "should set the maintainer name from the second argument" do - md = Chef::Cookbook::Metadata.new(@cookbook, 'Bobo T. Clown') + md = Chef::Cookbook::Metadata.new(@cookbook, 'Bobo T. Clown') md.maintainer.should == 'Bobo T. Clown' end @@ -105,7 +105,7 @@ describe Chef::Cookbook::Metadata do end it "should set the maintainer email from the third argument" do - md = Chef::Cookbook::Metadata.new(@cookbook, 'Bobo T. Clown', 'bobo@clown.co') + md = Chef::Cookbook::Metadata.new(@cookbook, 'Bobo T. Clown', 'bobo@clown.co') md.maintainer_email.should == 'bobo@clown.co' end @@ -114,10 +114,10 @@ describe Chef::Cookbook::Metadata do end it "should set the license from the fourth argument" do - md = Chef::Cookbook::Metadata.new(@cookbook, 'Bobo T. Clown', 'bobo@clown.co', 'Clown License v1') + md = Chef::Cookbook::Metadata.new(@cookbook, 'Bobo T. Clown', 'bobo@clown.co', 'Clown License v1') md.license.should == 'Clown License v1' end - end + end describe "cookbook" do it "should return the cookbook we were initialized with" do @@ -133,7 +133,7 @@ describe Chef::Cookbook::Metadata do describe "platforms" do it "should return the current platform hash" do - @meta.platforms.should be_a_kind_of(Hash) + @meta.platforms.should be_a_kind_of(Hash) end end @@ -235,7 +235,7 @@ describe Chef::Cookbook::Metadata do end end end - + describe "attribute groupings" do it "should allow you set a grouping" do group = { @@ -312,7 +312,7 @@ describe Chef::Cookbook::Metadata do @meta.attribute("db/mysql/databases", {}) @meta.attributes["db/mysql/databases"][:choice].should == [] end - + it "should let calculated be true or false" do lambda { @meta.attribute("db/mysql/databases", :calculated => true) @@ -324,7 +324,7 @@ describe Chef::Cookbook::Metadata do @meta.attribute("db/mysql/databases", :calculated => Hash.new) }.should raise_error(ArgumentError) end - + it "should set calculated to false by default" do @meta.attribute("db/mysql/databases", {}) @meta.attributes["db/mysql/databases"][:calculated].should == false @@ -350,7 +350,7 @@ describe Chef::Cookbook::Metadata do @meta.attribute("db/mysql/databases", :type => "symbol") }.should_not raise_error(ArgumentError) end - + it "should let type be hash (backwards compatability only)" do lambda { @meta.attribute("db/mysql/databases", :type => "hash") @@ -375,7 +375,7 @@ describe Chef::Cookbook::Metadata do }.should_not raise_error(ArgumentError) #attrib = @meta.attributes["db/mysql/databases"][:required].should == "required" end - + it "should convert required false to optional" do lambda { @meta.attribute("db/mysql/databases", :required => false) @@ -387,7 +387,7 @@ describe Chef::Cookbook::Metadata do @meta.attribute("db/mysql/databases", {}) @meta.attributes["db/mysql/databases"][:required].should == 'optional' end - + it "should make sure recipes is an array" do lambda { @meta.attribute("db/mysql/databases", :recipes => []) @@ -399,7 +399,7 @@ describe Chef::Cookbook::Metadata do it "should set recipes to an empty array by default" do @meta.attribute("db/mysql/databases", {}) - @meta.attributes["db/mysql/databases"][:recipes].should == [] + @meta.attributes["db/mysql/databases"][:recipes].should == [] end it "should allow the default value to be a string, array, or hash" do @@ -438,14 +438,14 @@ describe Chef::Cookbook::Metadata do lambda { attrs = { :choice => [ "a", "b", "c"], - :default => "b" + :default => "b" } @meta.attribute("db/mysql/databases", attrs) }.should_not raise_error(ArgumentError) lambda { attrs = { :choice => [ "a", "b", "c", "d", "e"], - :default => ["b", "d"] + :default => ["b", "d"] } @meta.attribute("db/mysql/databases", attrs) }.should_not raise_error(ArgumentError) @@ -455,7 +455,7 @@ describe Chef::Cookbook::Metadata do lambda { attrs = { :choice => [ "a", "b", "c"], - :default => "d" + :default => "d" } @meta.attribute("db/mysql/databases", attrs) }.should raise_error(ArgumentError) @@ -470,11 +470,11 @@ describe Chef::Cookbook::Metadata do end describe "recipes" do - before(:each) do + before(:each) do @cookbook.recipe_files = [ "default.rb", "enlighten.rb" ] @meta = Chef::Cookbook::Metadata.new(@cookbook) end - + it "should have the names of the recipes" do @meta.recipes["test_cookbook"].should == "" @meta.recipes["test_cookbook::enlighten"].should == "" @@ -493,7 +493,7 @@ describe Chef::Cookbook::Metadata do end describe "json" do - before(:each) do + before(:each) do @cookbook.recipe_files = [ "default.rb", "enlighten.rb" ] @meta = Chef::Cookbook::Metadata.new(@cookbook) @meta.version "1.0" @@ -509,8 +509,8 @@ describe Chef::Cookbook::Metadata do @meta.provides "foo(:bar, :baz)" @meta.replaces "snarkitron" @meta.recipe "test_cookbook::enlighten", "is your buddy" - @meta.attribute "bizspark/has_login", - :display_name => "You have nothing" + @meta.attribute "bizspark/has_login", + :display_name => "You have nothing" @meta.version "1.2.3" end @@ -524,23 +524,23 @@ describe Chef::Cookbook::Metadata do end %w{ - name - description - long_description - maintainer - maintainer_email + name + description + long_description + maintainer + maintainer_email license - platforms - dependencies - suggestions - recommendations - conflicting + platforms + dependencies + suggestions + recommendations + conflicting providing - replacing - attributes + replacing + attributes recipes version - }.each do |t| + }.each do |t| it "should include '#{t}'" do @serial[t].should == @meta.send(t.to_sym) end @@ -557,23 +557,23 @@ describe Chef::Cookbook::Metadata do end %w{ - name - description - long_description - maintainer - maintainer_email + name + description + long_description + maintainer + maintainer_email license - platforms - dependencies - suggestions - recommendations - conflicting + platforms + dependencies + suggestions + recommendations + conflicting providing - replacing - attributes + replacing + attributes recipes version - }.each do |t| + }.each do |t| it "should match '#{t}'" do @deserial.send(t.to_sym).should == @meta.send(t.to_sym) end diff --git a/spec/unit/cookbook/synchronizer_spec.rb b/spec/unit/cookbook/synchronizer_spec.rb index 4c6aa0c0ed..31f30c5bf4 100644 --- a/spec/unit/cookbook/synchronizer_spec.rb +++ b/spec/unit/cookbook/synchronizer_spec.rb @@ -176,11 +176,11 @@ describe Chef::CookbookSynchronizer do @cookbook_a_template_default_tempfile = mock("Tempfile for cookbook_a apache.conf.erb template", :path => "/tmp/cookbook_a_template_default_tempfile") end - + after do Chef::Config[:no_lazy_load] = false end - + it "fetches templates and cookbook files" do @file_cache.should_receive(:has_key?). with("cookbooks/cookbook_a/files/default/megaman.conf"). @@ -206,7 +206,7 @@ describe Chef::CookbookSynchronizer do @file_cache.should_receive(:load). with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false). and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb") - + @synchronizer.sync_cookbooks end end diff --git a/spec/unit/cookbook/syntax_check_spec.rb b/spec/unit/cookbook/syntax_check_spec.rb index 84cd84121b..85d6950a45 100644 --- a/spec/unit/cookbook/syntax_check_spec.rb +++ b/spec/unit/cookbook/syntax_check_spec.rb @@ -32,7 +32,7 @@ describe Chef::Cookbook::SyntaxCheck do @attr_files = %w{default.rb smokey.rb}.map { |f| File.join(cookbook_path, 'attributes', f) } @defn_files = %w{client.rb server.rb}.map { |f| File.join(cookbook_path, 'definitions', f)} @recipes = %w{default.rb gigantor.rb one.rb}.map { |f| File.join(cookbook_path, 'recipes', f) } - @ruby_files = @attr_files + @defn_files + @recipes + @ruby_files = @attr_files + @defn_files + @recipes + [File.join(cookbook_path, "metadata.rb")] basenames = %w{ helpers_via_partial_test.erb helper_test.erb openldap_stuff.conf.erb @@ -74,7 +74,6 @@ describe Chef::Cookbook::SyntaxCheck do after do FileUtils.rm_rf(cache_path) if File.exist?(cache_path) - Chef::Config[:syntax_check_cache_path] = nil end describe "and the files have not been syntax checked previously" do diff --git a/spec/unit/cookbook_loader_spec.rb b/spec/unit/cookbook_loader_spec.rb index c3303dd09a..4c21c124e0 100644 --- a/spec/unit/cookbook_loader_spec.rb +++ b/spec/unit/cookbook_loader_spec.rb @@ -71,7 +71,7 @@ describe Chef::CookbookLoader do seen[5].should == "openldap" end end - + describe "load_cookbooks" do it "should find all the cookbooks in the cookbook path" do Chef::Config.cookbook_path << File.expand_path(File.join(CHEF_SPEC_DATA, "hidden-cookbooks")) @@ -79,7 +79,7 @@ describe Chef::CookbookLoader do @cookbook_loader.should have_key(:openldap) @cookbook_loader.should have_key(:apache2) end - + it "should allow you to override an attribute file via cookbook_path" do @cookbook_loader[:openldap].attribute_filenames.detect { |f| f =~ /cookbooks\/openldap\/attributes\/default.rb/ @@ -88,13 +88,13 @@ describe Chef::CookbookLoader do f =~ /kitchen\/openldap\/attributes\/default.rb/ }.should eql(nil) end - + it "should load different attribute files from deeper paths" do @cookbook_loader[:openldap].attribute_filenames.detect { |f| f =~ /kitchen\/openldap\/attributes\/robinson.rb/ }.should_not eql(nil) end - + it "should allow you to override a definition file via cookbook_path" do @cookbook_loader[:openldap].definition_filenames.detect { |f| f =~ /cookbooks\/openldap\/definitions\/client.rb/ @@ -103,13 +103,13 @@ describe Chef::CookbookLoader do f =~ /kitchen\/openldap\/definitions\/client.rb/ }.should eql(nil) end - + it "should load definition files from deeper paths" do @cookbook_loader[:openldap].definition_filenames.detect { |f| f =~ /kitchen\/openldap\/definitions\/drewbarrymore.rb/ }.should_not eql(nil) end - + it "should allow you to override a recipe file via cookbook_path" do @cookbook_loader[:openldap].recipe_filenames.detect { |f| f =~ /cookbooks\/openldap\/recipes\/gigantor.rb/ @@ -118,19 +118,19 @@ describe Chef::CookbookLoader do f =~ /kitchen\/openldap\/recipes\/gigantor.rb/ }.should eql(nil) end - + it "should load recipe files from deeper paths" do @cookbook_loader[:openldap].recipe_filenames.detect { |f| f =~ /kitchen\/openldap\/recipes\/woot.rb/ }.should_not eql(nil) end - + it "should allow you to have an 'ignore' file, which skips loading files in later cookbooks" do @cookbook_loader[:openldap].recipe_filenames.detect { |f| f =~ /kitchen\/openldap\/recipes\/ignoreme.rb/ }.should eql(nil) end - + it "should find files that start with a ." do @cookbook_loader[:openldap].file_filenames.detect { |f| f =~ /\.dotfile$/ @@ -139,9 +139,9 @@ describe Chef::CookbookLoader do f =~ /\.ssh\/id_rsa$/ }.should =~ /\.ssh\/id_rsa$/ end - + it "should load the metadata for the cookbook" do - @cookbook_loader.metadata[:openldap].name.should == :openldap + @cookbook_loader.metadata[:openldap].name.to_s.should == "openldap" @cookbook_loader.metadata[:openldap].should be_a_kind_of(Chef::Cookbook::Metadata) end @@ -173,6 +173,22 @@ describe Chef::CookbookLoader do seen.should have_key("openldap") end + it "should not duplicate keys when serialized to JSON" do + # Chef JSON serialization will generate duplicate keys if given + # a Hash containing matching string and symbol keys. See CHEF-4571. + aa = @cookbook_loader["openldap"] + aa.to_hash["metadata"].recipes.keys.should_not include(:openldap) + aa.to_hash["metadata"].recipes.keys.should include("openldap") + expected_desc = "Main Open LDAP configuration" + aa.to_hash["metadata"].recipes["openldap"].should == expected_desc + raw = aa.to_hash["metadata"].recipes.to_json + search_str = "\"openldap\":\"" + key_idx = raw.index(search_str) + key_idx.should be > 0 + dup_idx = raw[(key_idx + 1)..-1].index(search_str) + dup_idx.should be_nil + end + it "should not load the cookbook again when accessed" do @cookbook_loader.should_not_receive('load_cookbook') @cookbook_loader["openldap"] @@ -202,7 +218,7 @@ describe Chef::CookbookLoader do end seen.should have_key("openldap") seen.should have_key("apache2") - end + end end end # loading only one cookbook end diff --git a/spec/unit/cookbook_manifest_spec.rb b/spec/unit/cookbook_manifest_spec.rb index 7da87e93a5..e87b8e1e9a 100644 --- a/spec/unit/cookbook_manifest_spec.rb +++ b/spec/unit/cookbook_manifest_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -96,7 +96,7 @@ describe "Chef::CookbookVersion manifest" do :checksum => "csum-host-2", :specificity => "host-examplehost.example.org" }, - + { :name => "anotherfile1.rb", :path => "files/ubuntu-9.10/adirectory/anotherfile1.rb.platform-full-version", @@ -122,7 +122,7 @@ describe "Chef::CookbookVersion manifest" do :checksum => "csum-platver-partial-2", :specificity => "nweubuntu-9" }, - + { :name => "anotherfile1.rb", :path => "files/ubuntu/adirectory/anotherfile1.rb.platform", @@ -135,7 +135,7 @@ describe "Chef::CookbookVersion manifest" do :checksum => "csum-plat-2", :specificity => "ubuntu" }, - + { :name => "anotherfile1.rb", :path => "files/default/adirectory/anotherfile1.rb.default", @@ -201,8 +201,8 @@ describe "Chef::CookbookVersion manifest" do } end - - + + it "should return a manifest record based on priority preference: host" do node = Chef::Node.new node.automatic_attrs[:platform] = "ubuntu" @@ -213,7 +213,7 @@ describe "Chef::CookbookVersion manifest" do manifest_record.should_not be_nil manifest_record[:checksum].should == "csum-host" end - + it "should return a manifest record based on priority preference: platform & full version" do node = Chef::Node.new node.automatic_attrs[:platform] = "ubuntu" @@ -235,7 +235,7 @@ describe "Chef::CookbookVersion manifest" do manifest_record.should_not be_nil manifest_record[:checksum].should == "csum-platver-partial" end - + it "should return a manifest record based on priority preference: platform only" do node = Chef::Node.new node.automatic_attrs[:platform] = "ubuntu" @@ -246,7 +246,7 @@ describe "Chef::CookbookVersion manifest" do manifest_record.should_not be_nil manifest_record[:checksum].should == "csum-plat" end - + it "should return a manifest record based on priority preference: default" do node = Chef::Node.new node.automatic_attrs[:platform] = "notubuntu" @@ -301,7 +301,7 @@ describe "Chef::CookbookVersion manifest" do manifest_record.should_not be_nil manifest_record[:checksum].should == "csum4-platver-full" end - + describe "when fetching the contents of a directory by file specificity" do it "should return a directory of manifest records based on priority preference: host" do diff --git a/spec/unit/cookbook_site_streaming_uploader.rb b/spec/unit/cookbook_site_streaming_uploader.rb new file mode 100644 index 0000000000..73a513494f --- /dev/null +++ b/spec/unit/cookbook_site_streaming_uploader.rb @@ -0,0 +1,200 @@ +# +# Author:: Xabier de Zuazo (xabier@onddo.com) +# Copyright:: Copyright (c) 2013 Onddo Labs, SL. +# 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/cookbook_site_streaming_uploader' + +class FakeTempfile + def initialize(basename) + @basename = basename + end + + def close + end + + def path + "#{@basename}.ZZZ" + end + +end + +describe Chef::CookbookSiteStreamingUploader do + + describe "create_build_dir" do + + before(:each) do + @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, 'cookbooks')) + @loader = Chef::CookbookLoader.new(@cookbook_repo) + @loader.load_cookbooks + File.stub(:unlink).and_return() + end + + it "should create the cookbook tmp dir" do + cookbook = @loader[:openldap] + files_count = Dir.glob(File.join(@cookbook_repo, cookbook.name.to_s, '**', '*'), File::FNM_DOTMATCH).count { |file| File.file?(file) } + + Tempfile.should_receive(:new).with("chef-#{cookbook.name}-build").and_return(FakeTempfile.new("chef-#{cookbook.name}-build")) + FileUtils.should_receive(:mkdir_p).exactly(files_count + 1).times + FileUtils.should_receive(:cp).exactly(files_count).times + Chef::CookbookSiteStreamingUploader.create_build_dir(cookbook) + end + + end # create_build_dir + + describe "make_request" do + + before(:each) do + @uri = "http://cookbooks.dummy.com/api/v1/cookbooks" + @secret_filename = File.join(CHEF_SPEC_DATA, 'ssl/private_key.pem') + @rsa_key = File.read(@secret_filename) + response = Net::HTTPResponse.new('1.0', '200', 'OK') + Net::HTTP.any_instance.stub(:request).and_return(response) + end + + it "should send an http request" do + Net::HTTP.any_instance.should_receive(:request) + Chef::CookbookSiteStreamingUploader.make_request(:post, @uri, 'bill', @secret_filename) + end + + it "should read the private key file" do + File.should_receive(:read).with(@secret_filename).and_return(@rsa_key) + Chef::CookbookSiteStreamingUploader.make_request(:post, @uri, 'bill', @secret_filename) + end + + it "should add the authentication signed header" do + Mixlib::Authentication::SigningObject.any_instance.should_receive(:sign).and_return({}) + Chef::CookbookSiteStreamingUploader.make_request(:post, @uri, 'bill', @secret_filename) + end + + it "should be able to send post requests" do + post = Net::HTTP::Post.new(@uri, {}) + + Net::HTTP::Post.should_receive(:new).once.and_return(post) + Net::HTTP::Put.should_not_receive(:new) + Net::HTTP::Get.should_not_receive(:new) + Chef::CookbookSiteStreamingUploader.make_request(:post, @uri, 'bill', @secret_filename) + end + + it "should be able to send put requests" do + put = Net::HTTP::Put.new(@uri, {}) + + Net::HTTP::Post.should_not_receive(:new) + Net::HTTP::Put.should_receive(:new).once.and_return(put) + Net::HTTP::Get.should_not_receive(:new) + Chef::CookbookSiteStreamingUploader.make_request(:put, @uri, 'bill', @secret_filename) + end + + it "should be able to receive files to attach as argument" do + Chef::CookbookSiteStreamingUploader.make_request(:put, @uri, 'bill', @secret_filename, { + :myfile => File.new(File.join(CHEF_SPEC_DATA, 'config.rb')), # a dummy file + }) + end + + it "should be able to receive strings to attach as argument" do + Chef::CookbookSiteStreamingUploader.make_request(:put, @uri, 'bill', @secret_filename, { + :mystring => 'Lorem ipsum', + }) + end + + it "should be able to receive strings and files as argument at the same time" do + Chef::CookbookSiteStreamingUploader.make_request(:put, @uri, 'bill', @secret_filename, { + :myfile1 => File.new(File.join(CHEF_SPEC_DATA, 'config.rb')), + :mystring1 => 'Lorem ipsum', + :myfile2 => File.new(File.join(CHEF_SPEC_DATA, 'config.rb')), + :mystring2 => 'Dummy text', + }) + end + + end # make_request + + describe "StreamPart" do + before(:each) do + @file = File.new(File.join(CHEF_SPEC_DATA, 'config.rb')) + @stream_part = Chef::CookbookSiteStreamingUploader::StreamPart.new(@file, File.size(@file)) + end + + it "should create a StreamPart" do + @stream_part.should be_instance_of(Chef::CookbookSiteStreamingUploader::StreamPart) + end + + it "should expose its size" do + @stream_part.size.should eql(File.size(@file)) + end + + it "should read with offset and how_much" do + content = @file.read(4) + @file.rewind + @stream_part.read(0, 4).should eql(content) + end + + end # StreamPart + + describe "StringPart" do + before(:each) do + @str = 'What a boring string' + @string_part = Chef::CookbookSiteStreamingUploader::StringPart.new(@str) + end + + it "should create a StringPart" do + @string_part.should be_instance_of(Chef::CookbookSiteStreamingUploader::StringPart) + end + + it "should expose its size" do + @string_part.size.should eql(@str.size) + end + + it "should read with offset and how_much" do + @string_part.read(2, 4).should eql(@str[2, 4]) + end + + end # StringPart + + describe "MultipartStream" do + before(:each) do + @string1 = "stream1" + @string2 = "stream2" + @stream1 = Chef::CookbookSiteStreamingUploader::StringPart.new(@string1) + @stream2 = Chef::CookbookSiteStreamingUploader::StringPart.new(@string2) + @parts = [ @stream1, @stream2 ] + + @multipart_stream = Chef::CookbookSiteStreamingUploader::MultipartStream.new(@parts) + end + + it "should create a MultipartStream" do + @multipart_stream.should be_instance_of(Chef::CookbookSiteStreamingUploader::MultipartStream) + end + + it "should expose its size" do + @multipart_stream.size.should eql(@stream1.size + @stream2.size) + end + + it "should read with how_much" do + @multipart_stream.read(10).should eql("#{@string1}#{@string2}"[0, 10]) + end + + it "should read receiving destination buffer as second argument (CHEF-4456: Ruby 2 compat)" do + dst_buf = '' + @multipart_stream.read(10, dst_buf) + dst_buf.should eql("#{@string1}#{@string2}"[0, 10]) + end + + end # MultipartStream + +end + diff --git a/spec/unit/cookbook_version_spec.rb b/spec/unit/cookbook_version_spec.rb index 85e1db1fae..d186ef01be 100644 --- a/spec/unit/cookbook_version_spec.rb +++ b/spec/unit/cookbook_version_spec.rb @@ -130,6 +130,12 @@ describe Chef::CookbookVersion do @cookbook_version.provider_filenames = @cookbook[:provider_filenames] @cookbook_version.root_filenames = @cookbook[:root_filenames] @cookbook_version.metadata_filenames = @cookbook[:metadata_filenames] + + # Used to test file-specificity related file lookups + @node = Chef::Node.new + @node.set[:platform] = "ubuntu" + @node.set[:platform_version] = "13.04" + @node.name("testing") end it "generates a manifest containing the cookbook's files" do @@ -211,6 +217,16 @@ describe Chef::CookbookVersion do readme["specificity"].should == "default" end + it "determines whether a template is available for a given node" do + @cookbook_version.should have_template_for_node(@node, "configuration.erb") + @cookbook_version.should_not have_template_for_node(@node, "missing.erb") + end + + it "determines whether a cookbook_file is available for a given node" do + @cookbook_version.should have_cookbook_file_for_node(@node, "giant_blob.tgz") + @cookbook_version.should_not have_cookbook_file_for_node(@node, "missing.txt") + end + describe "raises an error when attempting to load a missing cookbook_file and" do before do node = Chef::Node.new.tap do |n| diff --git a/spec/unit/daemon_spec.rb b/spec/unit/daemon_spec.rb index 5c0d828354..8d66e08511 100644 --- a/spec/unit/daemon_spec.rb +++ b/spec/unit/daemon_spec.rb @@ -20,7 +20,6 @@ require 'ostruct' describe Chef::Daemon do before do - @original_config = Chef::Config.configuration if windows? mock_struct = #Struct::Passwd.new(nil, nil, 111, 111) mock_struct = OpenStruct.new(:uid => 2342, :gid => 2342) @@ -33,42 +32,6 @@ describe Chef::Daemon do end end - after do - Chef::Config.configuration.replace(@original_config) - end - - describe ".running?" do - - before do - Chef::Daemon.name = "spec" - end - - describe "when a pid file exists" do - - before do - Chef::Daemon.stub!(:pid_from_file).and_return(1337) - end - - it "should check that there is a process matching the pidfile" do - Process.should_receive(:kill).with(0, 1337) - Chef::Daemon.running? - end - - end - - describe "when the pid file is nonexistent" do - - before do - Chef::Daemon.stub!(:pid_from_file).and_return(nil) - end - - it "should return false" do - Chef::Daemon.running?.should be_false - end - - end - end - describe ".pid_file" do describe "when the pid_file option has been set" do @@ -77,10 +40,6 @@ describe Chef::Daemon do Chef::Config[:pid_file] = "/var/run/chef/chef-client.pid" end - after do - Chef::Config.configuration.replace(@original_config) - end - it "should return the supplied value" do Chef::Daemon.pid_file.should eql("/var/run/chef/chef-client.pid") end @@ -89,7 +48,6 @@ describe Chef::Daemon do describe "without the pid_file option set" do before do - Chef::Config[:pid_file] = nil Chef::Daemon.name = "chef-client" end @@ -112,92 +70,6 @@ describe Chef::Daemon do end end - describe ".save_pid_file" do - - before do - Process.stub!(:pid).and_return(1337) - Chef::Config[:pid_file] = "/var/run/chef/chef-client.pid" - Chef::Application.stub!(:fatal!).and_return(true) - @f_mock = mock(File, { :print => true, :close => true, :write => true }) - File.stub!(:open).with("/var/run/chef/chef-client.pid", "w").and_yield(@f_mock) - end - - it "should try and create the parent directory" do - FileUtils.should_receive(:mkdir_p).with("/var/run/chef") - Chef::Daemon.save_pid_file - end - - it "should open the pid file for writing" do - File.should_receive(:open).with("/var/run/chef/chef-client.pid", "w") - Chef::Daemon.save_pid_file - end - - it "should write the pid, converted to string, to the pid file" do - @f_mock.should_receive(:write).with("1337").once.and_return(true) - Chef::Daemon.save_pid_file - end - - end - - describe ".remove_pid_file" do - before do - Chef::Config[:pid_file] = "/var/run/chef/chef-client.pid" - end - - describe "when the pid file exists" do - - before do - File.stub!(:exists?).with("/var/run/chef/chef-client.pid").and_return(true) - end - - it "should remove the file" do - FileUtils.should_receive(:rm).with("/var/run/chef/chef-client.pid") - Chef::Daemon.remove_pid_file - end - - - end - - describe "when the pid file exists and the process is forked" do - - before do - File.stub!(:exists?).with("/var/run/chef/chef-client.pid").and_return(true) - Chef::Daemon.stub!(:forked?) { true } - end - - it "should not remove the file" do - FileUtils.should_not_receive(:rm) - Chef::Daemon.remove_pid_file - end - - end - - describe "when the pid file exists and the process is not forked" do - before do - File.stub!(:exists?).with("/var/run/chef/chef-client.pid").and_return(true) - Chef::Daemon.stub!(:forked?) { false } - end - - it "should remove the file" do - FileUtils.should_receive(:rm) - Chef::Daemon.remove_pid_file - end - end - - describe "when the pid file does not exist" do - - before do - File.stub!(:exists?).with("/var/run/chef/chef-client.pid").and_return(false) - end - - it "should not remove the file" do - FileUtils.should_not_receive(:rm) - Chef::Daemon.remove_pid_file - end - - end - end - describe ".change_privilege" do before do @@ -230,10 +102,6 @@ describe Chef::Daemon do end describe "when just the user option is supplied" do - before do - Chef::Config[:group] = nil - end - it "should log an appropriate info message" do Chef::Log.should_receive(:info).with("About to change privilege to aj") Chef::Daemon.change_privilege diff --git a/spec/unit/data_bag_item_spec.rb b/spec/unit/data_bag_item_spec.rb index 6f46c81054..6bc5954fa5 100644 --- a/spec/unit/data_bag_item_spec.rb +++ b/spec/unit/data_bag_item_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -130,7 +130,7 @@ describe Chef::DataBagItem do end describe "to_hash" do - before(:each) do + before(:each) do @data_bag_item.data_bag("still_lost") @data_bag_item.raw_data = { "id" => "whoa", "i_know" => "kung_fu" } @to_hash = @data_bag_item.to_hash @@ -197,7 +197,7 @@ describe Chef::DataBagItem do before do @rest = mock("Chef::REST") Chef::REST.stub!(:new).and_return(@rest) - @data_bag_item['id'] = "heart of darkness" + @data_bag_item['id'] = "heart of darkness" raw_data = {"id" => "heart_of_darkness", "author" => "Conrad"} @data_bag_item.raw_data = raw_data @data_bag_item.data_bag("books") @@ -207,7 +207,7 @@ describe Chef::DataBagItem do @data_bag_item.save end - it "should create if the item is not found" do + it "should create if the item is not found" do exception = mock("404 error", :code => "404") @rest.should_receive(:put_rest).and_raise(Net::HTTPServerException.new("foo", exception)) @rest.should_receive(:post_rest).with("data/books", @data_bag_item) @@ -228,7 +228,7 @@ describe Chef::DataBagItem do end end - + end describe "when loading" do diff --git a/spec/unit/data_bag_spec.rb b/spec/unit/data_bag_spec.rb index 273ef38d9f..9fbdc64d98 100644 --- a/spec/unit/data_bag_spec.rb +++ b/spec/unit/data_bag_spec.rb @@ -69,24 +69,23 @@ describe Chef::DataBag do end - describe "when saving" do + describe "when saving" do before do @data_bag.name('piggly_wiggly') @rest = mock("Chef::REST") Chef::REST.stub!(:new).and_return(@rest) end - it "should update the data bag when it already exists" do - @rest.should_receive(:put_rest).with("data/piggly_wiggly", @data_bag) + it "should silently proceed when the data bag already exists" do + exception = mock("409 error", :code => "409") + @rest.should_receive(:post_rest).and_raise(Net::HTTPServerException.new("foo", exception)) @data_bag.save end - it "should create the data bag when it is not found" do - exception = mock("404 error", :code => "404") - @rest.should_receive(:put_rest).and_raise(Net::HTTPServerException.new("foo", exception)) + it "should create the data bag" do @rest.should_receive(:post_rest).with("data", @data_bag) @data_bag.save - end + end describe "when whyrun mode is enabled" do before do @@ -96,7 +95,6 @@ describe Chef::DataBag do Chef::Config[:why_run] = false end it "should not save" do - @rest.should_not_receive(:put_rest) @rest.should_not_receive(:post_rest) @data_bag.save end diff --git a/spec/unit/digester_spec.rb b/spec/unit/digester_spec.rb index 28e3e918fe..fdf20aca7c 100644 --- a/spec/unit/digester_spec.rb +++ b/spec/unit/digester_spec.rb @@ -8,9 +8,9 @@ # 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. diff --git a/spec/unit/encrypted_data_bag_item_spec.rb b/spec/unit/encrypted_data_bag_item_spec.rb index 9eda1633ab..18178d28b6 100644 --- a/spec/unit/encrypted_data_bag_item_spec.rb +++ b/spec/unit/encrypted_data_bag_item_spec.rb @@ -74,14 +74,9 @@ describe Chef::EncryptedDataBagItem::Encryptor do describe "when using version 2 format" do before do - @original_config = Chef::Config.hash_dup Chef::Config[:data_bag_encrypt_version] = 2 end - after do - Chef::Config.configuration = @original_config - end - it "creates a version 2 encryptor" do encryptor.should be_a_kind_of(Chef::EncryptedDataBagItem::Encryptor::Version2Encryptor) end @@ -179,14 +174,9 @@ describe Chef::EncryptedDataBagItem::Decryptor do context "and version 2 format is required" do before do - @original_config = Chef::Config.hash_dup Chef::Config[:data_bag_decrypt_minimum_version] = 2 end - after do - Chef::Config.configuration = @original_config - end - it "raises an error attempting to decrypt" do lambda { decryptor }.should raise_error(Chef::EncryptedDataBagItem::UnacceptableEncryptedDataBagItemFormat) end @@ -210,14 +200,9 @@ describe Chef::EncryptedDataBagItem::Decryptor do context "and version 1 format is required" do before do - @original_config = Chef::Config.hash_dup Chef::Config[:data_bag_decrypt_minimum_version] = 1 end - after do - Chef::Config.configuration = @original_config - end - it "raises an error attempting to decrypt" do lambda { decryptor }.should raise_error(Chef::EncryptedDataBagItem::UnacceptableEncryptedDataBagItemFormat) end diff --git a/spec/unit/file_cache_spec.rb b/spec/unit/file_cache_spec.rb index 6596326565..7680852cb9 100644 --- a/spec/unit/file_cache_spec.rb +++ b/spec/unit/file_cache_spec.rb @@ -41,7 +41,7 @@ describe Chef::FileCache do end end - + describe "when storing a file" do before do File.stub!(:open).and_yield(@io) diff --git a/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb index e1f8f28bb9..0b20b0ef86 100644 --- a/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -98,7 +98,7 @@ describe Chef::Formatters::ErrorInspectors::CompileErrorInspector do before do Chef::Config.stub!(:cookbook_path).and_return([ "C:/opscode/chef/var/cache/cookbooks" ]) recipe_lines = BAD_RECIPE.split("\n").map {|l| l << "\n" } - IO.should_receive(:readlines).at_least(1).times.with(/:\/opscode\/chef\/var\/cache\/cookbooks\/foo\/recipes\/default.rb/).and_return(recipe_lines) + IO.should_receive(:readlines).at_least(1).times.with(/:\/opscode\/chef\/var\/cache\/cookbooks\/foo\/recipes\/default.rb/).and_return(recipe_lines) @trace = [ "C:/opscode/chef/var/cache/cookbooks/foo/recipes/default.rb:14 in `from_file'", "C:/opscode/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.14.0/lib/chef/run_context.rb:144:in `rescue in block in load_libraries'", @@ -141,7 +141,7 @@ describe Chef::Formatters::ErrorInspectors::CompileErrorInspector do @inspector.add_explanation(@description) @inspector.culprit_file.should == "c:/opscode/chef/var/cache/cookbooks/foo/recipes/default.rb" end - end + end it "finds the line number of the error from the stack trace" do @inspector.culprit_line.should == 14 diff --git a/spec/unit/formatters/error_inspectors/cookbook_resolve_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/cookbook_resolve_error_inspector_spec.rb index cf668fbb0d..93129eadb8 100644 --- a/spec/unit/formatters/error_inspectors/cookbook_resolve_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/cookbook_resolve_error_inspector_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/formatters/error_inspectors/cookbook_sync_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/cookbook_sync_error_inspector_spec.rb index 6db7aaaa0d..eb8d302e5b 100644 --- a/spec/unit/formatters/error_inspectors/cookbook_sync_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/cookbook_sync_error_inspector_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/formatters/error_inspectors/node_load_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/node_load_error_inspector_spec.rb index bd3cc6b764..d2bbffafee 100644 --- a/spec/unit/formatters/error_inspectors/node_load_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/node_load_error_inspector_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/formatters/error_inspectors/registration_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/registration_error_inspector_spec.rb index 4fcf034d80..4c21dadd82 100644 --- a/spec/unit/formatters/error_inspectors/registration_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/registration_error_inspector_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb b/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb index b6d48d0255..fdbb601005 100644 --- a/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -129,7 +129,7 @@ describe Chef::Formatters::ErrorInspectors::ResourceFailureInspector do @inspector = Chef::Formatters::ErrorInspectors::ResourceFailureInspector.new(@resource, :create, @exception) @inspector.recipe_snippet.should match(/^# In \/home\/btm/) end - + context "when the recipe file does not exist" do before do File.stub!(:exists?).and_return(false) @@ -141,7 +141,7 @@ describe Chef::Formatters::ErrorInspectors::ResourceFailureInspector do @inspector = Chef::Formatters::ErrorInspectors::ResourceFailureInspector.new(@resource, :create, @exception) @inspector.recipe_snippet.should be_nil end - + it "does not raise an exception trying to load a non-existant file (CHEF-3411)" do @resource.source_line = "/somewhere/in/space" @inspector = Chef::Formatters::ErrorInspectors::ResourceFailureInspector.new(@resource, :create, @exception) diff --git a/spec/unit/formatters/error_inspectors/run_list_expansion_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/run_list_expansion_error_inspector_spec.rb index 4b6751a120..706ff59c06 100644 --- a/spec/unit/formatters/error_inspectors/run_list_expansion_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/run_list_expansion_error_inspector_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/handler_spec.rb b/spec/unit/handler_spec.rb index 9eeba478ac..eab98e76a2 100644 --- a/spec/unit/handler_spec.rb +++ b/spec/unit/handler_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -126,9 +126,9 @@ describe Chef::Handler do @end_time = @start_time + 4.2 Time.stub!(:now).and_return(@start_time, @end_time) @run_status.start_clock - @run_status.stop_clock + @run_status.stop_clock end - + it "has a shortcut for all resources" do @handler.all_resources.should == @all_resources end @@ -158,7 +158,7 @@ describe Chef::Handler do end it "has a shortcut for the success? and failed? predicates" do - @handler.success?.should be_true + @handler.success?.should be_true @handler.failed?.should be_false end diff --git a/spec/unit/http/ssl_policies_spec.rb b/spec/unit/http/ssl_policies_spec.rb new file mode 100644 index 0000000000..c80f989180 --- /dev/null +++ b/spec/unit/http/ssl_policies_spec.rb @@ -0,0 +1,161 @@ +#-- +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Copyright:: Copyright (c) 2009, 2010, 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/http/ssl_policies' + +describe "HTTP SSL Policy" do + + before do + Chef::Config[:ssl_client_cert] = nil + Chef::Config[:ssl_client_key] = nil + Chef::Config[:ssl_ca_path] = nil + Chef::Config[:ssl_ca_file] = nil + end + + let(:unconfigured_http_client) { Net::HTTP.new("example.com", 443) } + let(:http_client) do + unconfigured_http_client.use_ssl = true + ssl_policy.apply + unconfigured_http_client + end + + describe Chef::HTTP::DefaultSSLPolicy do + + let(:ssl_policy) { Chef::HTTP::DefaultSSLPolicy.new(unconfigured_http_client) } + + describe "when configured with :ssl_verify_mode set to :verify peer" do + before do + Chef::Config[:ssl_verify_mode] = :verify_peer + end + + it "configures the HTTP client to use SSL when given a URL with the https protocol" do + http_client.use_ssl?.should be_true + end + + it "sets the OpenSSL verify mode to verify_peer" do + http_client.verify_mode.should == OpenSSL::SSL::VERIFY_PEER + end + + it "raises a ConfigurationError if :ssl_ca_path is set to a path that doesn't exist" do + Chef::Config[:ssl_ca_path] = "/dev/null/nothing_here" + lambda {http_client}.should raise_error(Chef::Exceptions::ConfigurationError) + end + + it "should set the CA path if that is set in the configuration" do + Chef::Config[:ssl_ca_path] = File.join(CHEF_SPEC_DATA, "ssl") + http_client.ca_path.should == File.join(CHEF_SPEC_DATA, "ssl") + end + + it "raises a ConfigurationError if :ssl_ca_file is set to a file that does not exist" do + Chef::Config[:ssl_ca_file] = "/dev/null/nothing_here" + lambda {http_client}.should raise_error(Chef::Exceptions::ConfigurationError) + end + + it "should set the CA file if that is set in the configuration" do + Chef::Config[:ssl_ca_file] = CHEF_SPEC_DATA + '/ssl/5e707473.0' + http_client.ca_file.should == CHEF_SPEC_DATA + '/ssl/5e707473.0' + end + end + + describe "when configured with :ssl_verify_mode set to :verify peer" do + before do + @url = URI.parse("https://chef.example.com:4443/") + Chef::Config[:ssl_verify_mode] = :verify_none + end + + it "sets the OpenSSL verify mode to :verify_none" do + http_client.verify_mode.should == OpenSSL::SSL::VERIFY_NONE + end + end + + describe "when configured with a client certificate" do + before {@url = URI.parse("https://chef.example.com:4443/")} + + it "raises ConfigurationError if the certificate file doesn't exist" do + Chef::Config[:ssl_client_cert] = "/dev/null/nothing_here" + Chef::Config[:ssl_client_key] = CHEF_SPEC_DATA + '/ssl/chef-rspec.key' + lambda {http_client}.should raise_error(Chef::Exceptions::ConfigurationError) + end + + it "raises ConfigurationError if the certificate file doesn't exist" do + Chef::Config[:ssl_client_cert] = CHEF_SPEC_DATA + '/ssl/chef-rspec.cert' + Chef::Config[:ssl_client_key] = "/dev/null/nothing_here" + lambda {http_client}.should raise_error(Chef::Exceptions::ConfigurationError) + end + + it "raises a ConfigurationError if one of :ssl_client_cert and :ssl_client_key is set but not both" do + Chef::Config[:ssl_client_cert] = "/dev/null/nothing_here" + Chef::Config[:ssl_client_key] = nil + lambda {http_client}.should raise_error(Chef::Exceptions::ConfigurationError) + end + + it "configures the HTTP client's cert and private key" do + Chef::Config[:ssl_client_cert] = CHEF_SPEC_DATA + '/ssl/chef-rspec.cert' + Chef::Config[:ssl_client_key] = CHEF_SPEC_DATA + '/ssl/chef-rspec.key' + http_client.cert.to_s.should == OpenSSL::X509::Certificate.new(IO.read(CHEF_SPEC_DATA + '/ssl/chef-rspec.cert')).to_s + http_client.key.to_s.should == IO.read(CHEF_SPEC_DATA + '/ssl/chef-rspec.key') + end + end + + context "when additional certs are located in the trusted_certs dir" do + let(:self_signed_crt_path) { File.join(CHEF_SPEC_DATA, "trusted_certs", "example.crt") } + let(:self_signed_crt) { OpenSSL::X509::Certificate.new(File.read(self_signed_crt_path)) } + + let(:additional_pem_path) { File.join(CHEF_SPEC_DATA, "trusted_certs", "opscode.pem") } + let(:additional_pem) { OpenSSL::X509::Certificate.new(File.read(additional_pem_path)) } + + before do + Chef::Config.trusted_certs_dir = File.join(CHEF_SPEC_DATA, "trusted_certs") + end + + it "enables verification of self-signed certificates" do + http_client.cert_store.verify(self_signed_crt).should be_true + end + + it "enables verification of cert chains" do + # This cert is signed by DigiCert so it would be valid in normal SSL usage. + # The chain goes: + # trusted root -> intermediate -> opscode.pem + # In this test, the intermediate has to be loaded and trusted in order + # for verification to work correctly. + # If the machine running the test doesn't have ruby SSL configured correctly, + # then the root cert also has to be loaded for the test to succeed. + # The system under test **SHOULD** do both of these things. + http_client.cert_store.verify(additional_pem).should be_true + end + end + end + + describe Chef::HTTP::APISSLPolicy do + + let(:ssl_policy) { Chef::HTTP::APISSLPolicy.new(unconfigured_http_client) } + + context "when verify_api_cert is set" do + before do + Chef::Config[:verify_api_cert] = true + end + + it "sets the OpenSSL verify mode to verify_peer" do + http_client.verify_mode.should == OpenSSL::SSL::VERIFY_PEER + end + end + + end +end + diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb index c716896302..cc0336d8f6 100644 --- a/spec/unit/knife/bootstrap_spec.rb +++ b/spec/unit/knife/bootstrap_spec.rb @@ -22,16 +22,6 @@ Chef::Knife::Bootstrap.load_deps require 'net/ssh' describe Chef::Knife::Bootstrap do - before(:all) do - @original_config = Chef::Config.hash_dup - @original_knife_config = Chef::Config[:knife].dup - end - - after(:all) do - Chef::Config.configuration = @original_config - Chef::Config[:knife] = @original_knife_config - end - before(:each) do Chef::Log.logger = Logger.new(StringIO.new) @knife = Chef::Knife::Bootstrap.new @@ -133,6 +123,34 @@ describe Chef::Knife::Bootstrap do @knife.name_args.first.should == "barf" end + describe "specifying no_proxy with various entries" do + subject(:knife) { described_class.new } + let(:options){ ["--bootstrap-no-proxy", setting] } + let(:template_file) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "no_proxy.erb")) } + let(:rendered_template) do + knife.instance_variable_set("@template_file", template_file) + knife.parse_options(options) + template_string = knife.read_template + knife.render_template(template_string) + end + + context "via --bootstrap-no-proxy" do + let(:setting) { "api.opscode.com" } + + it "renders the client.rb with a single FQDN no_proxy entry" do + rendered_template.should match(%r{.*no_proxy\s*"api.opscode.com".*}) + end + end + + context "via --bootstrap-no-proxy multiple" do + let(:setting) { "api.opscode.com,172.16.10.*" } + + it "renders the client.rb with comma-separated FQDN and wildcard IP address no_proxy entries" do + rendered_template.should match(%r{.*no_proxy\s*"api.opscode.com,172.16.10.\*".*}) + end + end + end + describe "specifying the encrypted data bag secret key" do subject(:knife) { described_class.new } let(:secret) { "supersekret" } @@ -182,7 +200,6 @@ describe Chef::Knife::Bootstrap do it "renders the client.rb with an encrypted_data_bag_secret entry" do rendered_template.should match(%r{encrypted_data_bag_secret\s*"/etc/chef/encrypted_data_bag_secret"}) end - after(:each) { Chef::Config.configuration = @original_config } end end @@ -216,7 +233,7 @@ describe Chef::Knife::Bootstrap do it "configures the ssh port" do @knife_ssh.config[:ssh_port].should == '4001' end - + it "configures the ssh agent forwarding" do @knife_ssh.config[:forward_agent].should == true end @@ -241,7 +258,7 @@ describe Chef::Knife::Bootstrap do it "uses the password from --ssh-password for sudo when --use-sudo-password is set" do @knife.config[:use_sudo] = true @knife.config[:use_sudo_password] = true - @knife.ssh_command.should include("echo #{@knife.config[:ssh_password]} | sudo -S") + @knife.ssh_command.should include("echo \'#{@knife.config[:ssh_password]}\' | sudo -S") end it "should not honor --use-sudo-password when --use-sudo is not set" do @@ -276,7 +293,7 @@ describe Chef::Knife::Bootstrap do it "configures the ssh port" do @knife_ssh.config[:ssh_port].should == '2430' end - + it "configures the ssh agent forwarding" do @knife_ssh.config[:forward_agent].should == true end diff --git a/spec/unit/knife/client_bulk_delete_spec.rb b/spec/unit/knife/client_bulk_delete_spec.rb index 55351554d1..b7864ed098 100644 --- a/spec/unit/knife/client_bulk_delete_spec.rb +++ b/spec/unit/knife/client_bulk_delete_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -37,31 +37,31 @@ describe Chef::Knife::ClientBulkDelete do end Chef::ApiClient.stub!(:list).and_return(@clients) end - + describe "run" do - + it "should get the list of the clients" do Chef::ApiClient.should_receive(:list).and_return(@clients) @knife.run end - + it "should print the clients you are about to delete" do @knife.run @stdout.string.should match(/#{@knife.ui.list(@clients.keys.sort, :columns_down)}/) end - + it "should confirm you really want to delete them" do @knife.ui.should_receive(:confirm) @knife.run end - + it "should delete each client" do @clients.each_value do |c| c.should_receive(:destroy) end @knife.run end - + it "should only delete clients that match the regex" do @knife.name_args = ["tim"] @clients["tim"].should_receive(:destroy) diff --git a/spec/unit/knife/client_create_spec.rb b/spec/unit/knife/client_create_spec.rb index c049748074..d07b6ceb17 100644 --- a/spec/unit/knife/client_create_spec.rb +++ b/spec/unit/knife/client_create_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/knife/client_delete_spec.rb b/spec/unit/knife/client_delete_spec.rb index 865f19f713..9ebccbae15 100644 --- a/spec/unit/knife/client_delete_spec.rb +++ b/spec/unit/knife/client_delete_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/knife/client_edit_spec.rb b/spec/unit/knife/client_edit_spec.rb index 1308d14fd5..1d7049be30 100644 --- a/spec/unit/knife/client_edit_spec.rb +++ b/spec/unit/knife/client_edit_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/knife/client_list_spec.rb b/spec/unit/knife/client_list_spec.rb index 6237a0d14c..c4834ad8d1 100644 --- a/spec/unit/knife/client_list_spec.rb +++ b/spec/unit/knife/client_list_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/knife/client_reregister_spec.rb b/spec/unit/knife/client_reregister_spec.rb index d9fc8ec180..d84978c497 100644 --- a/spec/unit/knife/client_reregister_spec.rb +++ b/spec/unit/knife/client_reregister_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/knife/client_show_spec.rb b/spec/unit/knife/client_show_spec.rb index 5bac3b4af6..ce5f93ab5f 100644 --- a/spec/unit/knife/client_show_spec.rb +++ b/spec/unit/knife/client_show_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/knife/config_file_selection_spec.rb b/spec/unit/knife/config_file_selection_spec.rb index 3ee18d82d0..127e89be9b 100644 --- a/spec/unit/knife/config_file_selection_spec.rb +++ b/spec/unit/knife/config_file_selection_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -20,14 +20,38 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require 'tmpdir' describe Chef::Knife do + + let(:missing_config_fetcher) do + double(Chef::ConfigFetcher, :config_missing? => true) + end + + let(:available_config_fetcher) do + double(Chef::ConfigFetcher, :config_missing? => false, + :read_config => "") + end + + def have_config_file(path) + Chef::ConfigFetcher.should_receive(:new).at_least(1).times.with(path, nil).and_return(available_config_fetcher) + end + + before do + # Make sure tests can run when HOME is not set... + @original_home = ENV["HOME"] + ENV["HOME"] = Dir.tmpdir + end + + after do + ENV["HOME"] = @original_home + end + before :each do Chef::Config.stub!(:from_file).and_return(true) + Chef::ConfigFetcher.stub(:new).and_return(missing_config_fetcher) end it "configure knife from KNIFE_HOME env variable" do env_config = File.expand_path(File.join(Dir.tmpdir, 'knife.rb')) - File.stub!(:exist?).and_return(false) - File.stub!(:exist?).with(env_config).and_return(true) + have_config_file(env_config) ENV['KNIFE_HOME'] = Dir.tmpdir @knife = Chef::Knife.new @@ -37,39 +61,33 @@ describe Chef::Knife do it "configure knife from PWD" do pwd_config = "#{Dir.pwd}/knife.rb" - File.stub!(:exist?).and_return do | arg | - [ pwd_config ].include? arg - end + have_config_file(pwd_config) @knife = Chef::Knife.new @knife.configure_chef @knife.config[:config_file].should == pwd_config end - + it "configure knife from UPWARD" do upward_dir = File.expand_path "#{Dir.pwd}/.chef" upward_config = File.expand_path "#{upward_dir}/knife.rb" - File.stub!(:exist?).and_return do | arg | - [ upward_config ].include? arg - end + have_config_file(upward_config) Chef::Knife.stub!(:chef_config_dir).and_return(upward_dir) - + @knife = Chef::Knife.new @knife.configure_chef @knife.config[:config_file].should == upward_config end - + it "configure knife from HOME" do home_config = File.expand_path(File.join("#{ENV['HOME']}", "/.chef/knife.rb")) - File.stub!(:exist?).and_return do | arg | - [ home_config ].include? arg - end - + have_config_file(home_config) + @knife = Chef::Knife.new @knife.configure_chef @knife.config[:config_file].should == home_config end - + it "configure knife from nothing" do ::File.stub!(:exist?).and_return(false) @knife = Chef::Knife.new @@ -77,7 +95,7 @@ describe Chef::Knife do @knife.configure_chef @knife.config[:config_file].should be_nil end - + it "configure knife precedence" do env_config = File.join(Dir.tmpdir, 'knife.rb') pwd_config = "#{Dir.pwd}/knife.rb" @@ -85,34 +103,33 @@ describe Chef::Knife do upward_config = File.expand_path "#{upward_dir}/knife.rb" home_config = File.expand_path(File.join("#{ENV['HOME']}", "/.chef/knife.rb")) configs = [ env_config, pwd_config, upward_config, home_config ] - File.stub!(:exist?).and_return do | arg | - configs.include? arg - end + Chef::Knife.stub!(:chef_config_dir).and_return(upward_dir) ENV['KNIFE_HOME'] = Dir.tmpdir - + @knife = Chef::Knife.new + @knife.configure_chef - @knife.config[:config_file].should == env_config - - configs.delete env_config - @knife.config.delete :config_file + @knife.config[:config_file].should be_nil + + have_config_file(home_config) + @knife = Chef::Knife.new @knife.configure_chef - @knife.config[:config_file].should == pwd_config + @knife.config[:config_file].should == home_config - configs.delete pwd_config - @knife.config.delete :config_file + have_config_file(upward_config) + @knife = Chef::Knife.new @knife.configure_chef @knife.config[:config_file].should == upward_config - configs.delete upward_config - @knife.config.delete :config_file + have_config_file(pwd_config) + @knife = Chef::Knife.new @knife.configure_chef - @knife.config[:config_file].should == home_config + @knife.config[:config_file].should == pwd_config - configs.delete home_config - @knife.config.delete :config_file + have_config_file(env_config) + @knife = Chef::Knife.new @knife.configure_chef - @knife.config[:config_file].should be_nil + @knife.config[:config_file].should == env_config end end diff --git a/spec/unit/knife/configure_spec.rb b/spec/unit/knife/configure_spec.rb index 3fe4f86eb9..7c48be6727 100644 --- a/spec/unit/knife/configure_spec.rb +++ b/spec/unit/knife/configure_spec.rb @@ -4,8 +4,6 @@ describe Chef::Knife::Configure do before do Chef::Log.logger = Logger.new(StringIO.new) - @original_config = Chef::Config.configuration.dup - Chef::Config[:node_name] = "webmonkey.example.com" @knife = Chef::Knife::Configure.new @rest_client = mock("null rest client", :post_rest => { :result => :true }) @@ -24,10 +22,6 @@ describe Chef::Knife::Configure do Ohai::System.stub!(:new).and_return(ohai) end - after do - Chef::Config.configuration.replace(@original_config) - end - let(:fqdn) { "foo.example.org" } diff --git a/spec/unit/knife/cookbook_create_spec.rb b/spec/unit/knife/cookbook_create_spec.rb index dc1d7d7f79..7891115285 100644 --- a/spec/unit/knife/cookbook_create_spec.rb +++ b/spec/unit/knife/cookbook_create_spec.rb @@ -245,15 +245,8 @@ describe Chef::Knife::CookbookCreate do @knife.run end - it "should create a CHANGELOG file" do - @dir = Dir.tmpdir - @knife.should_receive(:create_changelog).with(@dir, @knife.name_args.first) - @knife.run - end - - context "when the cookbooks path is not specified in the config file nor supplied via parameter" do + context "when the cookbooks path is set to nil" do before do - @old_cookbook_path = Chef::Config[:cookbook_path] Chef::Config[:cookbook_path] = nil end @@ -261,10 +254,6 @@ describe Chef::Knife::CookbookCreate do @dir = Dir.tmpdir lambda{@knife.run}.should raise_error(ArgumentError) end - - after do - Chef::Config[:cookbook_path] = @old_cookbook_path - end end end diff --git a/spec/unit/knife/cookbook_metadata_from_file_spec.rb b/spec/unit/knife/cookbook_metadata_from_file_spec.rb index 60555d89dc..6f406de6b7 100644 --- a/spec/unit/knife/cookbook_metadata_from_file_spec.rb +++ b/spec/unit/knife/cookbook_metadata_from_file_spec.rb @@ -8,9 +8,9 @@ # 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. diff --git a/spec/unit/knife/cookbook_show_spec.rb b/spec/unit/knife/cookbook_show_spec.rb index 2f2d841fea..96fe738b0b 100644 --- a/spec/unit/knife/cookbook_show_spec.rb +++ b/spec/unit/knife/cookbook_show_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -171,7 +171,7 @@ describe Chef::Knife::CookbookShow do @response = "Example recipe text" end - + describe "with --fqdn" do it "should pass the fqdn" do @knife.config[:platform] = "example_platform" diff --git a/spec/unit/knife/cookbook_site_install_spec.rb b/spec/unit/knife/cookbook_site_install_spec.rb index 43afe09f5e..f7d7a397e6 100644 --- a/spec/unit/knife/cookbook_site_install_spec.rb +++ b/spec/unit/knife/cookbook_site_install_spec.rb @@ -25,7 +25,7 @@ describe Chef::Knife::CookbookSiteInstall do @knife.config = {} if Chef::Platform.windows? @install_path = 'C:/tmp/chef' - else + else @install_path = '/var/tmp/chef' end @knife.config[:cookbook_path] = [ @install_path ] diff --git a/spec/unit/knife/core/bootstrap_context_spec.rb b/spec/unit/knife/core/bootstrap_context_spec.rb index 808a6f27ad..47261e2068 100644 --- a/spec/unit/knife/core/bootstrap_context_spec.rb +++ b/spec/unit/knife/core/bootstrap_context_spec.rb @@ -118,14 +118,22 @@ EXPECTED describe "when an encrypted_data_bag_secret is provided" do context "via config[:secret]" do - let(:config){ {:secret => "supersekret" }} + let(:chef_config) do + { + :knife => {:secret => "supersekret" } + } + end it "reads the encrypted_data_bag_secret" do bootstrap_context.encrypted_data_bag_secret.should eq "supersekret" end end context "via config[:secret_file]" do - let(:config){ {:secret_file => secret_file}} + let(:chef_config) do + { + :knife => {:secret_file => secret_file} + } + end it "reads the encrypted_data_bag_secret" do bootstrap_context.encrypted_data_bag_secret.should eq IO.read(secret_file) end diff --git a/spec/unit/knife/data_bag_show_spec.rb b/spec/unit/knife/data_bag_show_spec.rb index 08ecfaa0a7..d64b4f286d 100644 --- a/spec/unit/knife/data_bag_show_spec.rb +++ b/spec/unit/knife/data_bag_show_spec.rb @@ -7,9 +7,9 @@ # 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. diff --git a/spec/unit/knife/environment_from_file_spec.rb b/spec/unit/knife/environment_from_file_spec.rb index d2234d9be1..7d028ae3b8 100644 --- a/spec/unit/knife/environment_from_file_spec.rb +++ b/spec/unit/knife/environment_from_file_spec.rb @@ -49,13 +49,13 @@ describe Chef::Knife::EnvironmentFromFile do @env_apple.name("apple") @knife.loader.stub!(:load_from).with("apple.rb").and_return @env_apple end - + it "loads multiple environments if given" do @knife.name_args = [ "spec.rb", "apple.rb" ] @environment.should_receive(:save).twice @knife.run end - + it "loads all environments with -a" do File.stub!(:expand_path).with("./environments/*.{json,rb}").and_return("/tmp/environments") Dir.stub!(:glob).with("/tmp/environments").and_return(["spec.rb", "apple.rb"]) diff --git a/spec/unit/knife/index_rebuild_spec.rb b/spec/unit/knife/index_rebuild_spec.rb index 414ec95fad..eb4e8020c8 100644 --- a/spec/unit/knife/index_rebuild_spec.rb +++ b/spec/unit/knife/index_rebuild_spec.rb @@ -91,7 +91,7 @@ describe Chef::Knife::IndexRebuild do context "against a Chef 11 server" do let(:api_info) do - {"flavor" => "osc", + {"flavor" => "osc", "version" => "11.0.0", "erchef" => "1.2.3" } diff --git a/spec/unit/knife/node_delete_spec.rb b/spec/unit/knife/node_delete_spec.rb index b1b3db1aa4..bc30ae7e83 100644 --- a/spec/unit/knife/node_delete_spec.rb +++ b/spec/unit/knife/node_delete_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -28,7 +28,7 @@ describe Chef::Knife::NodeDelete do @knife.name_args = [ "adam" ] @knife.stub!(:output).and_return(true) @knife.stub!(:confirm).and_return(true) - @node = Chef::Node.new() + @node = Chef::Node.new() @node.stub!(:destroy).and_return(true) Chef::Node.stub!(:load).and_return(@node) @stdout = StringIO.new diff --git a/spec/unit/knife/node_edit_spec.rb b/spec/unit/knife/node_edit_spec.rb index 0ba2e90cfe..e8f6937a31 100644 --- a/spec/unit/knife/node_edit_spec.rb +++ b/spec/unit/knife/node_edit_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/knife/node_list_spec.rb b/spec/unit/knife/node_list_spec.rb index 5637d679c8..3482eab87c 100644 --- a/spec/unit/knife/node_list_spec.rb +++ b/spec/unit/knife/node_list_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -49,7 +49,7 @@ describe Chef::Knife::NodeList do Chef::Node.should_receive(:list_by_environment).with("prod").and_return(@list) @knife.run end - + describe "with -w or --with-uri" do it "should pretty print the hash" do @knife.config[:with_uri] = true diff --git a/spec/unit/knife/node_run_list_add_spec.rb b/spec/unit/knife/node_run_list_add_spec.rb index ee0cfc9038..80e372c30a 100644 --- a/spec/unit/knife/node_run_list_add_spec.rb +++ b/spec/unit/knife/node_run_list_add_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -27,7 +27,7 @@ describe Chef::Knife::NodeRunListAdd do } @knife.name_args = [ "adam", "role[monkey]" ] @knife.stub!(:output).and_return(true) - @node = Chef::Node.new() + @node = Chef::Node.new() @node.stub!(:save).and_return(true) Chef::Node.stub!(:load).and_return(@node) end diff --git a/spec/unit/knife/node_show_spec.rb b/spec/unit/knife/node_show_spec.rb index 6600b2aa96..eb3593fea1 100644 --- a/spec/unit/knife/node_show_spec.rb +++ b/spec/unit/knife/node_show_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -29,7 +29,7 @@ describe Chef::Knife::NodeShow do } @knife.name_args = [ "adam" ] @knife.stub!(:output).and_return(true) - @node = Chef::Node.new() + @node = Chef::Node.new() Chef::Node.stub!(:load).and_return(@node) end diff --git a/spec/unit/knife/role_create_spec.rb b/spec/unit/knife/role_create_spec.rb index af3a6bf539..39fed8fb68 100644 --- a/spec/unit/knife/role_create_spec.rb +++ b/spec/unit/knife/role_create_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -27,7 +27,7 @@ describe Chef::Knife::RoleCreate do } @knife.name_args = [ "adam" ] @knife.stub!(:output).and_return(true) - @role = Chef::Role.new() + @role = Chef::Role.new() @role.stub!(:save) Chef::Role.stub!(:new).and_return(@role) @knife.stub!(:edit_data).and_return(@role) diff --git a/spec/unit/knife/role_delete_spec.rb b/spec/unit/knife/role_delete_spec.rb index d2d8b889b3..37b16de7df 100644 --- a/spec/unit/knife/role_delete_spec.rb +++ b/spec/unit/knife/role_delete_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -28,7 +28,7 @@ describe Chef::Knife::RoleDelete do @knife.name_args = [ "adam" ] @knife.stub!(:output).and_return(true) @knife.stub!(:confirm).and_return(true) - @role = Chef::Role.new() + @role = Chef::Role.new() @role.stub!(:destroy).and_return(true) Chef::Role.stub!(:load).and_return(@role) @stdout = StringIO.new diff --git a/spec/unit/knife/role_list_spec.rb b/spec/unit/knife/role_list_spec.rb index 1a5e8e2a72..d0cd3b4413 100644 --- a/spec/unit/knife/role_list_spec.rb +++ b/spec/unit/knife/role_list_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/knife/ssh_spec.rb b/spec/unit/knife/ssh_spec.rb index 7f1ed0e321..0d67f33ee7 100644 --- a/spec/unit/knife/ssh_spec.rb +++ b/spec/unit/knife/ssh_spec.rb @@ -21,17 +21,10 @@ require 'net/ssh' require 'net/ssh/multi' describe Chef::Knife::Ssh do - before(:all) do - @original_config = Chef::Config.hash_dup - @original_knife_config = Chef::Config[:knife].dup + before(:each) do Chef::Config[:client_key] = CHEF_SPEC_DATA + "/ssl/private_key.pem" end - after(:all) do - Chef::Config.configuration = @original_config - Chef::Config[:knife] = @original_knife_config - end - before do @knife = Chef::Knife::Ssh.new @knife.merge_configs diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb index 4c5bb3e207..3edddec374 100644 --- a/spec/unit/knife_spec.rb +++ b/spec/unit/knife_spec.rb @@ -203,7 +203,6 @@ describe Chef::Knife do KnifeSpecs::TestYourself.option(:opt_with_default, :short => "-D VALUE", :default => "default-value") - Chef::Config[:knife] = {} end it "prefers the default value if no config or command line value is present" do @@ -227,7 +226,6 @@ describe Chef::Knife do end end - end describe "when first created" do diff --git a/spec/unit/log_spec.rb b/spec/unit/log_spec.rb index b91ee020bb..7be40f77e6 100644 --- a/spec/unit/log_spec.rb +++ b/spec/unit/log_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/mash_spec.rb b/spec/unit/mash_spec.rb index b9a7cd0932..7358781e60 100644 --- a/spec/unit/mash_spec.rb +++ b/spec/unit/mash_spec.rb @@ -35,7 +35,7 @@ describe Mash do @copy = @orig.dup @copy.to_hash.should == Mash.new(data).to_hash @copy[:z] << 4 - @orig[:z].should == [1,2,3] + @orig[:z].should == [1,2,3] end it "should duplicate a nested mash to a new mash" do @@ -44,7 +44,7 @@ describe Mash do @copy = @orig.dup @copy.to_hash.should == Mash.new(data).to_hash @copy[:z][:a] << 4 - @orig[:z][:a].should == [1,2,3] + @orig[:z][:a].should == [1,2,3] end # add more! diff --git a/spec/unit/mixin/checksum_spec.rb b/spec/unit/mixin/checksum_spec.rb index 19af1c7d2b..c0f0acdeb4 100644 --- a/spec/unit/mixin/checksum_spec.rb +++ b/spec/unit/mixin/checksum_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -20,7 +20,7 @@ require 'spec_helper' require 'chef/mixin/checksum' require 'stringio' -class Chef::CMCCheck +class Chef::CMCCheck include Chef::Mixin::Checksum end diff --git a/spec/unit/mixin/convert_to_class_name_spec.rb b/spec/unit/mixin/convert_to_class_name_spec.rb index b78d3f9101..240decc6da 100644 --- a/spec/unit/mixin/convert_to_class_name_spec.rb +++ b/spec/unit/mixin/convert_to_class_name_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -23,23 +23,23 @@ class ConvertToClassTestHarness end describe Chef::Mixin::ConvertToClassName do - + before do @convert = ConvertToClassTestHarness.new end - + it "converts a_snake_case_word to a CamelCaseWord" do @convert.convert_to_class_name("now_camelized").should == "NowCamelized" end - + it "converts a CamelCaseWord to a snake_case_word" do @convert.convert_to_snake_case("NowImASnake").should == "now_im_a_snake" end - + it "removes the base classes before snake casing" do @convert.convert_to_snake_case("NameSpaced::Class::ThisIsWin", "NameSpaced::Class").should == "this_is_win" end - + it "removes the base classes without explicitly naming them and returns snake case" do @convert.snake_case_basename("NameSpaced::Class::ExtraWin").should == "extra_win" end diff --git a/spec/unit/mixin/deprecation_spec.rb b/spec/unit/mixin/deprecation_spec.rb index c3170007de..3ebf06e830 100644 --- a/spec/unit/mixin/deprecation_spec.rb +++ b/spec/unit/mixin/deprecation_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/mixin/params_validate_spec.rb b/spec/unit/mixin/params_validate_spec.rb index aa37362dc3..2947ebea4a 100644 --- a/spec/unit/mixin/params_validate_spec.rb +++ b/spec/unit/mixin/params_validate_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -20,7 +20,7 @@ require 'spec_helper' class TinyClass include Chef::Mixin::ParamsValidate - + def music(is_good=true) is_good end @@ -30,136 +30,136 @@ describe Chef::Mixin::ParamsValidate do before(:each) do @vo = TinyClass.new() end - + it "should allow a hash and a hash as arguments to validate" do lambda { @vo.validate({:one => "two"}, {}) }.should_not raise_error(ArgumentError) end - + it "should raise an argument error if validate is called incorrectly" do lambda { @vo.validate("one", "two") }.should raise_error(ArgumentError) end - + it "should require validation map keys to be symbols or strings" do lambda { @vo.validate({:one => "two"}, { :one => true }) }.should_not raise_error(ArgumentError) lambda { @vo.validate({:one => "two"}, { "one" => true }) }.should_not raise_error(ArgumentError) lambda { @vo.validate({:one => "two"}, { Hash.new => true }) }.should raise_error(ArgumentError) end - + it "should allow options to be required with true" do lambda { @vo.validate({:one => "two"}, { :one => true }) }.should_not raise_error(ArgumentError) end - + it "should allow options to be optional with false" do lambda { @vo.validate({}, {:one => false})}.should_not raise_error(ArgumentError) - end - + end + it "should allow you to check what kind_of? thing an argument is with kind_of" do - lambda { + lambda { @vo.validate( - {:one => "string"}, + {:one => "string"}, { :one => { :kind_of => String } } - ) + ) }.should_not raise_error(ArgumentError) - - lambda { + + lambda { @vo.validate( - {:one => "string"}, + {:one => "string"}, { :one => { :kind_of => Array } } - ) + ) }.should raise_error(ArgumentError) end - + it "should allow you to specify an argument is required with required" do - lambda { + lambda { @vo.validate( - {:one => "string"}, + {:one => "string"}, { :one => { :required => true } } - ) + ) }.should_not raise_error(ArgumentError) - - lambda { + + lambda { @vo.validate( - {:two => "string"}, + {:two => "string"}, { :one => { :required => true } } - ) + ) }.should raise_error(ArgumentError) - - lambda { + + lambda { @vo.validate( - {:two => "string"}, + {:two => "string"}, { :one => { :required => false } } - ) + ) }.should_not raise_error(ArgumentError) end - + it "should allow you to specify whether an object has a method with respond_to" do - lambda { + lambda { @vo.validate( - {:one => @vo}, + {:one => @vo}, { :one => { :respond_to => "validate" } } - ) + ) }.should_not raise_error(ArgumentError) - - lambda { + + lambda { @vo.validate( - {:one => @vo}, + {:one => @vo}, { :one => { :respond_to => "monkey" } } - ) + ) }.should raise_error(ArgumentError) end - + it "should allow you to specify whether an object has all the given methods with respond_to and an array" do - lambda { + lambda { @vo.validate( - {:one => @vo}, + {:one => @vo}, { :one => { :respond_to => ["validate", "music"] } } - ) + ) }.should_not raise_error(ArgumentError) - - lambda { + + lambda { @vo.validate( - {:one => @vo}, + {:one => @vo}, { :one => { :respond_to => ["monkey", "validate"] } } - ) + ) }.should raise_error(ArgumentError) end - + it "should let you set a default value with default => value" do arguments = Hash.new @vo.validate(arguments, { @@ -169,9 +169,9 @@ describe Chef::Mixin::ParamsValidate do }) arguments[:one].should == "is the loneliest number" end - + it "should let you check regular expressions" do - lambda { + lambda { @vo.validate( { :one => "is good" }, { @@ -181,8 +181,8 @@ describe Chef::Mixin::ParamsValidate do } ) }.should_not raise_error(ArgumentError) - - lambda { + + lambda { @vo.validate( { :one => "is good" }, { @@ -193,9 +193,9 @@ describe Chef::Mixin::ParamsValidate do ) }.should raise_error(ArgumentError) end - + it "should let you specify your own callbacks" do - lambda { + lambda { @vo.validate( { :one => "is good" }, { @@ -208,9 +208,9 @@ describe Chef::Mixin::ParamsValidate do } } ) - }.should_not raise_error(ArgumentError) - - lambda { + }.should_not raise_error(ArgumentError) + + lambda { @vo.validate( { :one => "is bad" }, { @@ -223,12 +223,12 @@ describe Chef::Mixin::ParamsValidate do } } ) - }.should raise_error(ArgumentError) + }.should raise_error(ArgumentError) end - + it "should let you combine checks" do args = { :one => "is good", :two => "is bad" } - lambda { + lambda { @vo.validate( args, { @@ -276,7 +276,7 @@ describe Chef::Mixin::ParamsValidate do ) }.should raise_error(ArgumentError) end - + it "should raise an ArgumentError if the validation map has an unknown check" do lambda { @vo.validate( { :one => "two" }, @@ -288,43 +288,43 @@ describe Chef::Mixin::ParamsValidate do ) }.should raise_error(ArgumentError) end - + it "should accept keys that are strings in the options" do lambda { - @vo.validate({ "one" => "two" }, { :one => { :regex => /^two$/ }}) + @vo.validate({ "one" => "two" }, { :one => { :regex => /^two$/ }}) }.should_not raise_error(ArgumentError) end - + it "should allow an array to kind_of" do - lambda { + lambda { @vo.validate( - {:one => "string"}, + {:one => "string"}, { :one => { :kind_of => [ String, Array ] } } - ) + ) }.should_not raise_error(ArgumentError) - lambda { + lambda { @vo.validate( - {:one => ["string"]}, + {:one => ["string"]}, { :one => { :kind_of => [ String, Array ] } } - ) + ) }.should_not raise_error(ArgumentError) - lambda { + lambda { @vo.validate( - {:one => Hash.new}, + {:one => Hash.new}, { :one => { :kind_of => [ String, Array ] } } - ) + ) }.should raise_error(ArgumentError) end @@ -403,5 +403,5 @@ describe Chef::Mixin::ParamsValidate do @vo.set_or_return(:test, nil, {}).object_id.should == value.object_id @vo.set_or_return(:test, nil, {}).should be_a(Proc) end - + end diff --git a/spec/unit/mixin/securable_spec.rb b/spec/unit/mixin/securable_spec.rb index 764da9b1d1..fe21393c90 100644 --- a/spec/unit/mixin/securable_spec.rb +++ b/spec/unit/mixin/securable_spec.rb @@ -45,7 +45,6 @@ describe Chef::Mixin::Securable do describe "unix-specific behavior" do before(:each) do platform_mock :unix do - @original_config = Chef::Config.hash_dup load File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "chef", "config.rb") load File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "chef", "mixin", "securable.rb") @securable = Object.new @@ -54,10 +53,6 @@ describe Chef::Mixin::Securable do end end - after(:each) do - Chef::Config.configuration = @original_config - end - it "should accept a group name or id for group with spaces and backslashes" do lambda { @securable.group 'test\ group' }.should_not raise_error(ArgumentError) end @@ -109,7 +104,6 @@ describe Chef::Mixin::Securable do describe "windows-specific behavior" do before(:each) do platform_mock :windows do - @original_config = Chef::Config.hash_dup load File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "chef", "config.rb") load File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "chef", "mixin", "securable.rb") SECURABLE_CLASS = Class.new do @@ -120,14 +114,6 @@ describe Chef::Mixin::Securable do end end - after(:all) do - Chef::Config.configuration = @original_config if @original_config - end - - after(:each) do - Chef::Config.configuration = @original_config if @original_config - end - it "should not accept a group name or id for group with spaces and multiple backslashes" do lambda { @securable.group 'test\ \group' }.should raise_error(ArgumentError) end diff --git a/spec/unit/mixin/shell_out_spec.rb b/spec/unit/mixin/shell_out_spec.rb index 6ca700fcdb..c7ca56fe84 100644 --- a/spec/unit/mixin/shell_out_spec.rb +++ b/spec/unit/mixin/shell_out_spec.rb @@ -31,7 +31,7 @@ describe Chef::Mixin::ShellOut do let(:cmd) { "echo '#{rand(1000)}'" } let(:output) { StringIO.new } - let(:capture_log_output) { Chef::Log.logger = Logger.new(output) } + let!(:capture_log_output) { Chef::Log.logger = Logger.new(output) } let(:assume_deprecation_log_level) { Chef::Log.stub!(:level).and_return(:warn) } context 'without options' do diff --git a/spec/unit/mixin/template_spec.rb b/spec/unit/mixin/template_spec.rb index 039bc1984f..ca2c3c7318 100644 --- a/spec/unit/mixin/template_spec.rb +++ b/spec/unit/mixin/template_spec.rb @@ -33,6 +33,40 @@ describe Chef::Mixin::Template, "render_template" do output.should == "bar" end + template_contents = [ "Fancy\r\nTemplate\r\n\r\n", + "Fancy\nTemplate\n\n", + "Fancy\r\nTemplate\n\r\n"] + + describe "when running on windows" do + before do + Chef::Platform.stub!(:windows?).and_return(true) + end + + it "should render the templates with windows line endings" do + template_contents.each do |template_content| + output = @context.render_template_from_string(template_content) + output.each_line do |line| + line.should end_with("\r\n") + end + end + end + end + + describe "when running on unix" do + before do + Chef::Platform.stub!(:windows?).and_return(false) + end + + it "should render the templates with unix line endings" do + template_contents.each do |template_content| + output = @context.render_template_from_string(template_content) + output.each_line do |line| + line.should end_with("\n") + end + end + end + end + it "should provide a node method to access @node" do @context[:node] = "tehShizzle" output = @context.render_template_from_string("<%= @node %>") diff --git a/spec/unit/mixin/windows_architecture_helper_spec.rb b/spec/unit/mixin/windows_architecture_helper_spec.rb index c7813a5efc..f59602d716 100644 --- a/spec/unit/mixin/windows_architecture_helper_spec.rb +++ b/spec/unit/mixin/windows_architecture_helper_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -32,7 +32,7 @@ describe Chef::Mixin::WindowsArchitectureHelper do @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 @@ -67,7 +67,7 @@ describe Chef::Mixin::WindowsArchitectureHelper do 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 @@ -76,7 +76,7 @@ describe Chef::Mixin::WindowsArchitectureHelper do @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 ) + node_supports_windows_architecture?(new_node, supported_architecture).should == false if ! only_valid_combinations && (supported_architecture == :x86_64 && node_architecture == :i386 ) end end end diff --git a/spec/unit/mixin/xml_escape_spec.rb b/spec/unit/mixin/xml_escape_spec.rb index d05854ade4..83debb5907 100644 --- a/spec/unit/mixin/xml_escape_spec.rb +++ b/spec/unit/mixin/xml_escape_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb index 5aa563aedf..70905d334b 100644 --- a/spec/unit/node/attribute_spec.rb +++ b/spec/unit/node/attribute_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -20,9 +20,9 @@ require 'spec_helper' require 'chef/node/attribute' -describe Chef::Node::Attribute do +describe Chef::Node::Attribute do before(:each) do - @attribute_hash = + @attribute_hash = {"dmi"=>{}, "command"=>{"ps"=>"ps -ef"}, "platform_version"=>"10.5.7", @@ -193,7 +193,7 @@ describe Chef::Node::Attribute do @default_hash = { "domain" => "opscode.com", "hot" => { "day" => "saturday" }, - "music" => { + "music" => { "jimmy_eat_world" => "is fun!", "mastodon" => "rocks", "mars_volta" => "is loud and nutty", @@ -225,7 +225,7 @@ describe Chef::Node::Attribute do [ :normal, :default, :override, :automatic ].each do |accessor| it "should set #{accessor}" do na = Chef::Node::Attribute.new({ :normal => true }, { :default => true }, { :override => true }, { :automatic => true }) - na.send(accessor).should == { accessor.to_s => true } + na.send(accessor).should == { accessor.to_s => true } end end @@ -520,7 +520,7 @@ describe Chef::Node::Attribute do [:include?, :key?, :member?].each do |method| it "should alias the method #{method} to itself" do - @attributes.should respond_to(method) + @attributes.should respond_to(method) end it "#{method} should behave like has_key?" do @@ -582,7 +582,7 @@ describe Chef::Node::Attribute do collect.include?("snakes").should == true collect.include?("snack").should == true collect.include?("place").should == true - collect.length.should == 5 + collect.length.should == 5 end it "should yield lower if we go deeper" do @@ -593,7 +593,7 @@ describe Chef::Node::Attribute do collect.include?("two").should == true collect.include?("four").should == true collect.include?("six").should == true - collect.length.should == 3 + collect.length.should == 3 end it "should not raise an exception if one of the hashes has a nil value on a deep lookup" do @@ -667,7 +667,7 @@ describe Chef::Node::Attribute do @attributes.each_key do |k| collect << k end - + collect.should include("one") collect.should include("snack") collect.should include("hut") @@ -710,7 +710,7 @@ describe Chef::Node::Attribute do collect["snack"].should == "cookies" end end - + describe "each_value" do before do @attributes = Chef::Node::Attribute.new( diff --git a/spec/unit/node/immutable_collections_spec.rb b/spec/unit/node/immutable_collections_spec.rb index db4a79f21b..0c2b878cd2 100644 --- a/spec/unit/node/immutable_collections_spec.rb +++ b/spec/unit/node/immutable_collections_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb index 2906db34bc..bb567dbdf7 100644 --- a/spec/unit/node_spec.rb +++ b/spec/unit/node_spec.rb @@ -204,6 +204,11 @@ describe Chef::Node do node.fuu.bahrr.baz.should == "qux" end + it "should let you use tag as a convience method for the tags attribute" do + node.normal['tags'] = ['one', 'two'] + node.tag('three', 'four') + node['tags'].should == ['one', 'two', 'three', 'four'] + end end describe "default attributes" do diff --git a/spec/unit/platform_spec.rb b/spec/unit/platform_spec.rb index 21bc4298b0..3904435ea0 100644 --- a/spec/unit/platform_spec.rb +++ b/spec/unit/platform_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -28,10 +28,11 @@ describe "Chef::Platform supports" do :centos, :fedora, :suse, + :opensuse, :redhat, :oracle, :gentoo, - :arch, + :arch, :solaris, :mswin, :mingw32, @@ -49,11 +50,11 @@ describe Chef::Platform do before :all do @original_platform_map = Chef::Platform.platforms end - + after :all do || Chef::Platform.platforms = @original_platform_map end - + before(:each) do Chef::Platform.platforms = { :darwin => { @@ -79,13 +80,13 @@ describe Chef::Platform do } @events = Chef::EventDispatch::Dispatcher.new end - + it "should allow you to look up a platform by name and version, returning the provider map for it" do pmap = Chef::Platform.find("Darwin", "9.2.2") pmap.should be_a_kind_of(Hash) pmap[:file].should eql("darwinian") end - + it "should allow you to look up a platform by name and version using \"greater than\" style operators" do pmap = Chef::Platform.find("Darwin", "11.1.0") pmap.should be_a_kind_of(Hash) @@ -97,46 +98,46 @@ describe Chef::Platform do pmap.should be_a_kind_of(Hash) pmap[:file].should eql("old school") end - + it "should use the default providers if the os doesn't give me a default, but does exist" do pmap = Chef::Platform.find("mars_volta", "1") pmap.should be_a_kind_of(Hash) pmap[:file].should eql(Chef::Provider::File) end - + it "should use the default provider if the os does not exist" do pmap = Chef::Platform.find("AIX", "1") pmap.should be_a_kind_of(Hash) pmap[:file].should eql(Chef::Provider::File) end - + it "should merge the defaults for an os with the specific version" do pmap = Chef::Platform.find("Darwin", "9.2.2") pmap[:file].should eql("darwinian") pmap[:snicker].should eql("snack") end - + it "should merge the defaults for an os with the universal defaults" do pmap = Chef::Platform.find("Darwin", "9.2.2") pmap[:file].should eql("darwinian") pmap[:pax].should eql("brittania") end - + it "should allow you to look up a provider for a platform directly by symbol" do Chef::Platform.find_provider("Darwin", "9.2.2", :file).should eql("darwinian") end - + it "should raise an exception if a provider cannot be found for a resource type" do lambda { Chef::Platform.find_provider("Darwin", "9.2.2", :coffee) }.should raise_error(ArgumentError) end - + it "should look up a provider for a resource with a Chef::Resource object" do kitty = Chef::Resource::Cat.new("loulou") Chef::Platform.find_provider("Darwin", "9.2.2", kitty).should eql("nice") end - + it "should look up a provider with a node and a Chef::Resource object" do - kitty = Chef::Resource::Cat.new("loulou") + kitty = Chef::Resource::Cat.new("loulou") node = Chef::Node.new node.name("Intel") node.automatic_attrs[:platform] = "mac_os_x" @@ -149,7 +150,7 @@ describe Chef::Platform do end it "should prefer an explicit provider" do - kitty = Chef::Resource::Cat.new("loulou") + kitty = Chef::Resource::Cat.new("loulou") kitty.stub!(:provider).and_return(Chef::Provider::File) node = Chef::Node.new node.name("Intel") @@ -168,7 +169,7 @@ describe Chef::Platform do node.automatic_attrs[:platform_version] = "8.5" Chef::Platform.find_provider_for_node(node, kitty).should eql(Chef::Provider::Cat) end - + def setup_file_resource node = Chef::Node.new node.automatic_attrs[:platform] = "mac_os_x" @@ -184,7 +185,7 @@ describe Chef::Platform do provider.new_resource.should equal(file) provider.run_context.should equal(run_context) end - + it "returns a provider object given a Chef::Resource object which has a valid run context without an action" do file, run_context = setup_file_resource provider = Chef::Platform.provider_for_resource(file) @@ -192,7 +193,7 @@ describe Chef::Platform do provider.new_resource.should equal(file) provider.run_context.should equal(run_context) end - + it "raises an error when trying to find the provider for a resource with no run context" do file = Chef::Resource::File.new("whateva") lambda {Chef::Platform.provider_for_resource(file)}.should raise_error(ArgumentError) @@ -202,44 +203,44 @@ describe Chef::Platform do lambda {Chef::Platform.provider_for_node('node', 'resource')}.should raise_error(NotImplementedError) end - it "should update the provider map with map" do + it "should update the provider map with map" do Chef::Platform.set( :platform => :darwin, :version => "9.2.2", - :resource => :file, + :resource => :file, :provider => "masterful" ) Chef::Platform.platforms[:darwin]["9.2.2"][:file].should eql("masterful") Chef::Platform.set( :platform => :darwin, :resource => :file, - :provider => "masterful" + :provider => "masterful" ) Chef::Platform.platforms[:darwin][:default][:file].should eql("masterful") Chef::Platform.set( - :resource => :file, + :resource => :file, :provider => "masterful" - ) + ) Chef::Platform.platforms[:default][:file].should eql("masterful") - + Chef::Platform.set( :platform => :hero, :version => "9.2.2", - :resource => :file, + :resource => :file, :provider => "masterful" ) Chef::Platform.platforms[:hero]["9.2.2"][:file].should eql("masterful") - + Chef::Platform.set( - :resource => :file, + :resource => :file, :provider => "masterful" ) Chef::Platform.platforms[:default][:file].should eql("masterful") - + Chef::Platform.platforms = {} - + Chef::Platform.set( - :resource => :file, + :resource => :file, :provider => "masterful" ) Chef::Platform.platforms[:default][:file].should eql("masterful") @@ -247,8 +248,8 @@ describe Chef::Platform do Chef::Platform.platforms = { :neurosis => {} } Chef::Platform.set(:platform => :neurosis, :resource => :package, :provider => "masterful") Chef::Platform.platforms[:neurosis][:default][:package].should eql("masterful") - + end - - + + end diff --git a/spec/unit/provider/cron/solaris_spec.rb b/spec/unit/provider/cron/unix_spec.rb index 498d4fb1f5..ffdfa198b6 100644 --- a/spec/unit/provider/cron/solaris_spec.rb +++ b/spec/unit/provider/cron/unix_spec.rb @@ -20,7 +20,7 @@ require 'spec_helper' -describe Chef::Provider::Cron::Solaris do +describe Chef::Provider::Cron::Unix do before do @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @@ -30,7 +30,7 @@ describe Chef::Provider::Cron::Solaris do @new_resource.minute "30" @new_resource.command "/bin/true" - @provider = Chef::Provider::Cron::Solaris.new(@new_resource, @run_context) + @provider = Chef::Provider::Cron::Unix.new(@new_resource, @run_context) end it "should inherit from Chef::Provider:Cron" do @@ -86,7 +86,7 @@ CRONTAB describe "write_crontab" do before :each do @status = mock("Status", :exitstatus => 0) - @provider.stub!(:run_command).and_return(@status) + @provider.stub!(:run_command_and_return_stdout_stderr).and_return(@status, String.new, String.new) @tempfile = mock("foo", :path => "/tmp/foo", :close => true) Tempfile.stub!(:new).and_return(@tempfile) @tempfile.should_receive(:flush) @@ -95,13 +95,13 @@ CRONTAB end it "should call crontab for the user" do - @provider.should_receive(:run_command).with(hash_including(:user => @new_resource.user)) + @provider.should_receive(:run_command_and_return_stdout_stderr).with(hash_including(:user => @new_resource.user)) @tempfile.should_receive(:<<).with("Foo") @provider.send(:write_crontab, "Foo") end it "should call crontab with a file containing the crontab" do - @provider.should_receive(:run_command) do |args| + @provider.should_receive(:run_command_and_return_stdout_stderr) do |args| (args[:command] =~ %r{\A/usr/bin/crontab (/\S+)\z}).should be_true $1.should == "/tmp/foo" @status @@ -115,7 +115,7 @@ CRONTAB @status.stub!(:exitstatus).and_return(1) lambda do @provider.send(:write_crontab, "Foo") - end.should raise_error(Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: 1") + end.should raise_error(Chef::Exceptions::Cron, /Error updating state of #{@new_resource.name}, exit: 1/) end end end diff --git a/spec/unit/provider/cron_spec.rb b/spec/unit/provider/cron_spec.rb index 5a848a30e6..8a819b699c 100644 --- a/spec/unit/provider/cron_spec.rb +++ b/spec/unit/provider/cron_spec.rb @@ -181,7 +181,7 @@ CRONTAB before :each do @provider.stub!(:read_crontab).and_return(<<-CRONTAB) 0 2 * * * /some/other/command - + # Chef Name: cronhole some stuff * 5 * Jan Mon /bin/true param1 param2 # Chef Name: something else @@ -196,7 +196,7 @@ CRONTAB @provider.cron_exists.should == true @provider.cron_empty.should == false end - + it "should pull the details out of the cron line" do cron = @provider.load_current_resource cron.minute.should == '*' @@ -563,7 +563,7 @@ HOME=/home/foo @provider.stub!(:read_crontab).and_return(<<-CRONTAB) 0 2 * * * /some/other/command -# Chef Name: something else +# Chef Name: cronhole some stuff * 5 * * * /bin/true # Another comment @@ -581,6 +581,7 @@ CRONTAB end it "should log nothing changed" do + Chef::Log.should_receive(:debug).with("Found cron '#{@new_resource.name}'") Chef::Log.should_receive(:debug).with("Skipping existing cron entry '#{@new_resource.name}'") @provider.run_action(:create) end @@ -808,5 +809,22 @@ MAILTO=foo@example.com @provider.send(:write_crontab, "Foo") end.should raise_error(Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: 1") end + + it "should raise an exception if the command die's and parent tries to write" do + class WriteErrPipe + def write(str) + raise Errno::EPIPE, "Test" + end + end + @status.stub!(:exitstatus).and_return(1) + @provider.stub!(:popen4).and_yield(1234, WriteErrPipe.new, StringIO.new, StringIO.new).and_return(@status) + + Chef::Log.should_receive(:debug).with("Broken pipe - Test") + + lambda do + @provider.send(:write_crontab, "Foo") + end.should raise_error(Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: 1") + end + end end diff --git a/spec/unit/provider/deploy/timestamped_spec.rb b/spec/unit/provider/deploy/timestamped_spec.rb index b891a03ce2..a9cea1142e 100644 --- a/spec/unit/provider/deploy/timestamped_spec.rb +++ b/spec/unit/provider/deploy/timestamped_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,7 +19,7 @@ require 'spec_helper' describe Chef::Provider::Deploy::Timestamped do - + before do @release_time = Time.utc( 2004, 8, 15, 16, 23, 42) Time.stub!(:now).and_return(@release_time) @@ -32,9 +32,9 @@ describe Chef::Provider::Deploy::Timestamped do @runner = mock("runnah") Chef::Runner.stub!(:new).and_return(@runner) end - + it "gives a timestamp for release_slug" do @timestamped_deploy.send(:release_slug).should == "20040815162342" end - + end diff --git a/spec/unit/provider/deploy_spec.rb b/spec/unit/provider/deploy_spec.rb index 56ba50b7f0..1a9fee8831 100644 --- a/spec/unit/provider/deploy_spec.rb +++ b/spec/unit/provider/deploy_spec.rb @@ -43,6 +43,20 @@ describe Chef::Provider::Deploy do @provider.should respond_to(:action_rollback) end + context "when the deploy resource has a timeout attribute" do + let(:ten_seconds) { 10 } + before { @resource.timeout(ten_seconds) } + it "relays the timeout to the scm resource" do + @provider.scm_provider.new_resource.timeout.should == ten_seconds + end + end + + context "when the deploy resource has no timeout attribute" do + it "should not set a timeout on the scm resource" do + @provider.scm_provider.new_resource.timeout.should be_nil + end + end + context "when the deploy_to dir does not exist yet" do before do FileUtils.should_receive(:mkdir_p).with(@resource.deploy_to).ordered @@ -149,18 +163,18 @@ describe Chef::Provider::Deploy do @provider.stub!(:deploy).and_return{ raise "Unexpected error" } @provider.stub!(:previous_release_path).and_return('previous_release') @provider.should_not_receive(:rollback) - lambda { + lambda { @provider.run_action(:deploy) }.should raise_exception(RuntimeError, "Unexpected error") end - + it "rollbacks to previous release if error happens on deploy" do @resource.rollback_on_error true @provider.stub!(:all_releases).and_return(['previous_release']) @provider.stub!(:deploy).and_return{ raise "Unexpected error" } @provider.stub!(:previous_release_path).and_return('previous_release') @provider.should_receive(:rollback) - lambda { + lambda { @provider.run_action(:deploy) }.should raise_exception(RuntimeError, "Unexpected error") end @@ -211,15 +225,15 @@ describe Chef::Provider::Deploy do #FileUtils.should_receive(:rm_rf).with("/my/deploy/dir/releases/20040815162342") #@provider.run_action(:rollback) #@provider.release_path.should eql(NIL) -- no check needed since assertions will fail - lambda { + lambda { @provider.run_action(:rollback) }.should raise_exception(RuntimeError, "There is no release to rollback to!") end - + it "an exception is raised when there are no releases" do all_releases = [] Dir.stub!(:glob).with("/my/deploy/dir/releases/*").and_return(all_releases) - lambda { + lambda { @provider.run_action(:rollback) }.should raise_exception(RuntimeError, "There is no release to rollback to!") end @@ -419,7 +433,7 @@ describe Chef::Provider::Deploy do @provider.should_receive(:enforce_ownership) @provider.link_tempfiles_to_current_release end - + end it "does nothing for restart if restart_command is empty" do diff --git a/spec/unit/provider/env_spec.rb b/spec/unit/provider/env_spec.rb index 77aea42b43..673ba9798a 100644 --- a/spec/unit/provider/env_spec.rb +++ b/spec/unit/provider/env_spec.rb @@ -81,7 +81,7 @@ describe Chef::Provider::Env do @provider.action_create end - it "should set the the new_resources updated flag when it creates the key" do + it "should set the new_resources updated flag when it creates the key" do @provider.action_create @new_resource.should be_updated end @@ -99,7 +99,7 @@ describe Chef::Provider::Env do @provider.action_create end - it "should set the the new_resources updated flag when it updates an existing value" do + it "should set the new_resources updated flag when it updates an existing value" do @provider.key_exists = true @provider.stub!(:compare_value).and_return(true) @provider.stub!(:modify_env).and_return(true) diff --git a/spec/unit/provider/execute_spec.rb b/spec/unit/provider/execute_spec.rb index bf913cca12..0d108f521d 100644 --- a/spec/unit/provider/execute_spec.rb +++ b/spec/unit/provider/execute_spec.rb @@ -31,7 +31,7 @@ describe Chef::Provider::Execute do @provider = Chef::Provider::Execute.new(@new_resource, @run_context) @current_resource = Chef::Resource::Ifconfig.new("foo_resource", @run_context) @provider.current_resource = @current_resource - Chef::Log.level = :info + Chef::Log.level = :info # FIXME: There should be a test for how STDOUT.tty? changes the live_stream option being passed STDOUT.stub!(:tty?).and_return(true) end @@ -73,7 +73,7 @@ describe Chef::Provider::Execute do @provider.run_action(:run) @new_resource.should_not be_updated - end + end it "should warn if user specified relative path without cwd" do @new_resource.creates "foo_resource" diff --git a/spec/unit/provider/file/content_spec.rb b/spec/unit/provider/file/content_spec.rb index 693877760e..9262a35245 100644 --- a/spec/unit/provider/file/content_spec.rb +++ b/spec/unit/provider/file/content_spec.rb @@ -20,14 +20,6 @@ require 'spec_helper' describe Chef::Provider::File::Content do - before(:all) do - @original_config = Chef::Config.configuration - end - - after(:all) do - Chef::Config.configuration.replace(@original_config) - end - # # mock setup # diff --git a/spec/unit/provider/git_spec.rb b/spec/unit/provider/git_spec.rb index 763de240cc..2bf55930db 100644 --- a/spec/unit/provider/git_spec.rb +++ b/spec/unit/provider/git_spec.rb @@ -165,15 +165,35 @@ SHAS @provider.should respond_to(:revision_slug) end - it "runs a clone command with default git options" do - @resource.user "deployNinja" - @resource.ssh_wrapper "do_it_this_way.sh" - expected_cmd = "git clone \"git://github.com/opscode/chef.git\" \"/my/deploy/dir\"" - @provider.should_receive(:shell_out!).with(expected_cmd, :user => "deployNinja", - :environment =>{"GIT_SSH"=>"do_it_this_way.sh"}, - :log_tag => "git[web2.0 app]" ) - - @provider.clone + context "with an ssh wrapper" do + let(:deploy_user) { "deployNinja" } + let(:wrapper) { "do_it_this_way.sh" } + let(:expected_cmd) { 'git clone "git://github.com/opscode/chef.git" "/my/deploy/dir"' } + let(:default_options) do + { + :user => deploy_user, + :environment => { "GIT_SSH" => wrapper }, + :log_tag => "git[web2.0 app]" + } + end + before do + @resource.user deploy_user + @resource.ssh_wrapper wrapper + end + context "without a timeout set" do + it "clones a repo with default git options" do + @provider.should_receive(:shell_out!).with(expected_cmd, default_options) + @provider.clone + end + end + context "with a timeout set" do + let (:seconds) { 10 } + before { @resource.timeout(seconds) } + it "clones a repo with amended git options" do + @provider.should_receive(:shell_out!).with(expected_cmd, default_options.merge(:timeout => seconds)) + @provider.clone + end + end end it "runs a clone command with escaped destination" do diff --git a/spec/unit/provider/group/dscl_spec.rb b/spec/unit/provider/group/dscl_spec.rb index b526848dfd..28d78cbdbd 100644 --- a/spec/unit/provider/group/dscl_spec.rb +++ b/spec/unit/provider/group/dscl_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -27,14 +27,14 @@ describe Chef::Provider::Group::Dscl do @current_resource = Chef::Resource::Group.new("aj") @provider = Chef::Provider::Group::Dscl.new(@new_resource, @run_context) @provider.current_resource = @current_resource - @status = mock("Process::Status", :exitstatus => 0) + @status = mock("Process::Status", :exitstatus => 0) @pid = 2342 @stdin = StringIO.new @stdout = StringIO.new("\n") @stderr = StringIO.new("") @provider.stub!(:popen4).and_yield(@pid,@stdin,@stdout,@stderr).and_return(@status) end - + it "should run popen4 with the supplied array of arguments appended to the dscl command" do @provider.should_receive(:popen4).with("dscl . -cmd /Path arg1 arg2") @provider.dscl("cmd", "/Path", "arg1", "arg2") @@ -52,7 +52,7 @@ describe Chef::Provider::Group::Dscl do @provider = Chef::Provider::Group::Dscl.new(@node, @new_resource) @provider.stub!(:dscl).and_return(["cmd", @status, "stdout", "stderr"]) end - + it "should run dscl with the supplied cmd /Path args" do @provider.should_receive(:dscl).with("cmd /Path args") @provider.safe_dscl("cmd /Path args") @@ -84,7 +84,7 @@ describe Chef::Provider::Group::Dscl do lambda { @provider.safe_dscl("cmd /Path arguments") }.should raise_error(Chef::Exceptions::Group) end end - + describe "with the dscl command returning a zero exit status" do it "should return the third array element, the string of standard output" do safe_dscl_retval = @provider.safe_dscl("cmd /Path args") @@ -100,7 +100,7 @@ describe Chef::Provider::Group::Dscl do @provider = Chef::Provider::Group::Dscl.new(@node, @new_resource) @provider.stub!(:safe_dscl).and_return("\naj 200\njt 201\n") end - + it "should run safe_dscl with list /Groups gid" do @provider.should_receive(:safe_dscl).with("list /Groups gid") @provider.get_free_gid @@ -109,7 +109,7 @@ describe Chef::Provider::Group::Dscl do it "should return the first unused gid number on or above 200" do @provider.get_free_gid.should equal(202) end - + it "should raise an exception when the search limit is exhausted" do search_limit = 1 lambda { @provider.get_free_gid(search_limit) }.should raise_error(RuntimeError) @@ -127,7 +127,7 @@ describe Chef::Provider::Group::Dscl do @provider.should_receive(:safe_dscl).with("list /Groups gid") @provider.gid_used?(500) end - + it "should return true for a used gid number" do @provider.gid_used?(500).should be_true end @@ -151,7 +151,7 @@ describe Chef::Provider::Group::Dscl do lambda { @provider.set_gid }.should raise_error(Chef::Exceptions::Group) end end - + describe "with no gid number for the new resources" do it "should run get_free_gid and return a valid, unused gid number" do @provider.should_receive(:get_free_gid).and_return(501) @@ -220,7 +220,7 @@ describe Chef::Provider::Group::Dscl do @provider.set_members end end - + describe "with no members in the new resource" do before do @new_resource.append(true) @@ -276,7 +276,7 @@ describe Chef::Provider::Group::Dscl do @provider.should_receive(:set_gid) @provider.manage_group end - + it "should manage the members if it changed and the new resources members is not null" do @current_resource.members(%{charlie root}) @new_resource.members(%{crab revenge}) diff --git a/spec/unit/provider/group/gpasswd_spec.rb b/spec/unit/provider/group/gpasswd_spec.rb index 59da88e851..8889ba322e 100644 --- a/spec/unit/provider/group/gpasswd_spec.rb +++ b/spec/unit/provider/group/gpasswd_spec.rb @@ -36,8 +36,8 @@ describe Chef::Provider::Group::Gpasswd, "modify_group_members" do @provider.define_resource_requirements end - # Checking for required binaries is already done in the spec - # for Chef::Provider::Group - no need to repeat it here. We'll + # Checking for required binaries is already done in the spec + # for Chef::Provider::Group - no need to repeat it here. We'll # include only what's specific to this provider. it "should raise an error if the required binary /usr/bin/gpasswd doesn't exist" do File.stub!(:exists?).and_return(true) diff --git a/spec/unit/provider/group/groupadd_spec.rb b/spec/unit/provider/group/groupadd_spec.rb index 5e07da59b4..0cc1167142 100644 --- a/spec/unit/provider/group/groupadd_spec.rb +++ b/spec/unit/provider/group/groupadd_spec.rb @@ -27,10 +27,12 @@ describe Chef::Provider::Group::Groupadd, "set_options" do @new_resource.gid(50) @new_resource.members(["root", "aj"]) @new_resource.system false + @new_resource.non_unique false @current_resource = Chef::Resource::Group.new("aj") @current_resource.gid(50) @current_resource.members(["root", "aj"]) @current_resource.system false + @current_resource.non_unique false @provider = Chef::Provider::Group::Groupadd.new(@new_resource, @run_context) @provider.current_resource = @current_resource end @@ -72,6 +74,18 @@ describe Chef::Provider::Group::Groupadd, "set_options" do @provider.groupadd_options.should == " -r" end end + + describe "when we want to create a non_unique gid group" do + it "should not set groupadd_options '-o' when non_unique is false" do + @new_resource.non_unique(false) + @provider.groupadd_options.should_not =~ /-o/ + end + + it "should set groupadd -o if non_unique is true" do + @new_resource.non_unique(true) + @provider.groupadd_options.should == " -o" + end + end end describe Chef::Provider::Group::Groupadd, "create_group" do diff --git a/spec/unit/provider/group/groupmod_spec.rb b/spec/unit/provider/group/groupmod_spec.rb index c9c56313b5..69b96c6edb 100644 --- a/spec/unit/provider/group/groupmod_spec.rb +++ b/spec/unit/provider/group/groupmod_spec.rb @@ -29,7 +29,7 @@ describe Chef::Provider::Group::Groupmod do @new_resource.append false @provider = Chef::Provider::Group::Groupmod.new(@new_resource, @run_context) end - + describe "manage_group" do describe "when determining the current group state" do it "should raise an error if the required binary /usr/sbin/group doesn't exist" do @@ -41,25 +41,25 @@ describe Chef::Provider::Group::Groupmod do File.should_receive(:exists?).with("/usr/sbin/user").and_return(false) lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Group) end - + it "shouldn't raise an error if the required binaries exist" do File.stub!(:exists?).and_return(true) lambda { @provider.load_current_resource }.should_not raise_error(Chef::Exceptions::Group) end end - + describe "after the group's current state is known" do before do @current_resource = @new_resource.dup @provider.current_resource = @current_resource end - + describe "when no group members are specified and append is not set" do before do @new_resource.append(false) @new_resource.members([]) end - + it "logs a message and sets group's members to 'none', then removes existing group members" do Chef::Log.should_receive(:debug).with("group[wheel] setting group members to: none") Chef::Log.should_receive(:debug).with("group[wheel] removing members lobster, rage, fist") @@ -69,26 +69,26 @@ describe Chef::Provider::Group::Groupmod do @provider.manage_group end end - + describe "when no group members are specified and append is set" do before do @new_resource.append(true) @new_resource.members([]) end - + it "logs a message and does not modify group membership" do Chef::Log.should_receive(:debug).with("group[wheel] not changing group members, the group has no members to add") @provider.should_not_receive(:shell_out!) @provider.manage_group end end - + describe "when removing some group members" do before do @new_resource.append(false) @new_resource.members(%w{ lobster }) end - + it "updates group membership correctly" do Chef::Log.stub!(:debug) @provider.should_receive(:shell_out!).with("group mod -n wheel_bak wheel") @@ -100,14 +100,14 @@ describe Chef::Provider::Group::Groupmod do end end end - + describe "create_group" do describe "when creating a new group" do before do @current_resource = Chef::Resource::Group.new("wheel") @provider.current_resource = @current_resource end - + it "should run a group add command and some user mod commands" do @provider.should_receive(:shell_out!).with("group add -g '123' wheel") @provider.should_receive(:shell_out!).with("user mod -G wheel lobster") @@ -117,14 +117,14 @@ describe Chef::Provider::Group::Groupmod do end end end - + describe "remove_group" do describe "when removing an existing group" do before do @current_resource = @new_resource.dup @provider.current_resource = @current_resource end - + it "should run a group del command" do @provider.should_receive(:shell_out!).with("group del wheel") @provider.remove_group diff --git a/spec/unit/provider/group/pw_spec.rb b/spec/unit/provider/group/pw_spec.rb index a7dbdb8615..e7c38f9555 100644 --- a/spec/unit/provider/group/pw_spec.rb +++ b/spec/unit/provider/group/pw_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -23,7 +23,7 @@ describe Chef::Provider::Group::Pw do @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) - + @new_resource = Chef::Resource::Group.new("wheel") @new_resource.gid 50 @new_resource.members [ "root", "aj"] @@ -34,12 +34,12 @@ describe Chef::Provider::Group::Pw do @provider = Chef::Provider::Group::Pw.new(@new_resource, @run_context) @provider.current_resource = @current_resource end - + describe "when setting options for the pw command" do it "does not set the gid option if gids match or are unmanaged" do @provider.set_options.should == " wheel" end - + it "sets the option for gid if it is not nil" do @new_resource.gid(42) @provider.set_options.should eql(" wheel -g '42'") @@ -55,7 +55,7 @@ describe Chef::Provider::Group::Pw do end describe "when managing the group" do - + it "should run pw groupmod with the return of set_options" do @new_resource.gid(42) @provider.should_receive(:run_command).with({ :command => "pw groupmod wheel -g '42' -M root,aj" }).and_return(true) @@ -72,18 +72,18 @@ describe Chef::Provider::Group::Pw do end describe "when setting group membership" do - + describe "with an empty members array in both the new and current resource" do before do @new_resource.stub!(:members).and_return([]) @current_resource.stub!(:members).and_return([]) end - + it "should log an appropriate message" do Chef::Log.should_receive(:debug).with("group[wheel] not changing group members, the group has no members") @provider.set_members_option end - + it "should set no options" do @provider.set_members_option.should eql("") end @@ -94,28 +94,28 @@ describe Chef::Provider::Group::Pw do @new_resource.stub!(:members).and_return([]) @current_resource.stub!(:members).and_return(["all", "your", "base"]) end - + it "should log an appropriate message" do Chef::Log.should_receive(:debug).with("group[wheel] removing group members all, your, base") @provider.set_members_option end - + it "should set the -d option with the members joined by ','" do @provider.set_members_option.should eql(" -d all,your,base") end end - + describe "with supplied members array in the new resource and an empty members array in the current resource" do before do @new_resource.stub!(:members).and_return(["all", "your", "base"]) @current_resource.stub!(:members).and_return([]) end - + it "should log an appropriate debug message" do Chef::Log.should_receive(:debug).with("group[wheel] setting group members to all, your, base") @provider.set_members_option end - + it "should set the -M option with the members joined by ','" do @provider.set_members_option.should eql(" -M all,your,base") end @@ -123,7 +123,7 @@ describe Chef::Provider::Group::Pw do end describe"load_current_resource" do - before (:each) do + before (:each) do @provider.load_current_resource @provider.define_resource_requirements end @@ -131,7 +131,7 @@ describe Chef::Provider::Group::Pw do File.should_receive(:exists?).with("/usr/sbin/pw").and_return(false) lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Group) end - + it "shouldn't raise an error if /usr/sbin/pw exists" do File.stub!(:exists?).and_return(true) lambda { @provider.process_resource_requirements }.should_not raise_error(Chef::Exceptions::Group) diff --git a/spec/unit/provider/group/usermod_spec.rb b/spec/unit/provider/group/usermod_spec.rb index 1807aaf57d..7f2931f2e2 100644 --- a/spec/unit/provider/group/usermod_spec.rb +++ b/spec/unit/provider/group/usermod_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -28,26 +28,27 @@ describe Chef::Provider::Group::Usermod do @provider = Chef::Provider::Group::Usermod.new(@new_resource, @run_context) @provider.stub!(:run_command) end - + describe "modify_group_members" do - + describe "with an empty members array" do before do @new_resource.stub!(:members).and_return([]) end - + it "should log an appropriate message" do Chef::Log.should_receive(:debug).with("group[wheel] not changing group members, the group has no members") @provider.modify_group_members end end - + describe "with supplied members" do platforms = { "openbsd" => "-G", "netbsd" => "-G", "solaris" => "-a -G", "suse" => "-a -G", + "opensuse" => "-a -G", "smartos" => "-G" } @@ -60,10 +61,10 @@ describe Chef::Provider::Group::Usermod do @provider.define_resource_requirements @provider.load_current_resource @provider.instance_variable_set("@group_exists", true) - @provider.action = :modify + @provider.action = :modify lambda { @provider.run_action(@provider.process_resource_requirements) }.should raise_error(Chef::Exceptions::Group, "setting group members directly is not supported by #{@provider.to_s}, must set append true in group") end - + platforms.each do |platform, flags| it "should usermod each user when the append option is set on #{platform}" do @node.automatic_attrs[:platform] = platform @@ -88,7 +89,7 @@ describe Chef::Provider::Group::Usermod do File.should_receive(:exists?).with("/usr/sbin/usermod").and_return(false) lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Group) end - + it "shouldn't raise an error if the required binaries exist" do File.stub!(:exists?).and_return(true) lambda { @provider.process_resource_requirements }.should_not raise_error(Chef::Exceptions::Group) diff --git a/spec/unit/provider/group/windows_spec.rb b/spec/unit/provider/group/windows_spec.rb index 084d1d0acf..a65cfc241d 100644 --- a/spec/unit/provider/group/windows_spec.rb +++ b/spec/unit/provider/group/windows_spec.rb @@ -92,3 +92,17 @@ describe Chef::Provider::Group::Windows do end end end + +describe Chef::Provider::Group::Windows, "NetGroup" do + before do + @node = Chef::Node.new + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, {}, @events) + @new_resource = Chef::Resource::Group.new("Creating a new group") + @new_resource.group_name "Remote Desktop Users" + end + it 'sets group_name correctly' do + Chef::Util::Windows::NetGroup.should_receive(:new).with("Remote Desktop Users") + Chef::Provider::Group::Windows.new(@new_resource, @run_context) + end +end diff --git a/spec/unit/provider/group_spec.rb b/spec/unit/provider/group_spec.rb index 106a0db14c..caad9878b6 100644 --- a/spec/unit/provider/group_spec.rb +++ b/spec/unit/provider/group_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -33,7 +33,7 @@ describe Chef::Provider::User do @current_resource = Chef::Resource::Group.new("aj", @run_context) @current_resource.gid 500 @current_resource.members "aj" - + @provider.current_resource = @current_resource @pw_group = mock("Struct::Group", @@ -43,13 +43,13 @@ describe Chef::Provider::User do ) Etc.stub!(:getgrnam).with('wheel').and_return(@pw_group) end - + it "assumes the group exists by default" do @provider.group_exists.should be_true end describe "when establishing the current state of the group" do - + it "sets the group name of the current resource to the group name of the new resource" do @provider.load_current_resource @provider.current_resource.group_name.should == 'wheel' @@ -65,22 +65,22 @@ describe Chef::Provider::User do @provider.load_current_resource @new_resource.gid.should == 20 end - + it "looks up the group in /etc/group with getgrnam" do Etc.should_receive(:getgrnam).with(@new_resource.group_name).and_return(@pw_group) @provider.load_current_resource @provider.current_resource.gid.should == 20 @provider.current_resource.members.should == %w{root aj} end - + it "should flip the value of exists if it cannot be found in /etc/group" do Etc.stub!(:getgrnam).and_raise(ArgumentError) @provider.load_current_resource @provider.group_exists.should be_false end - + it "should return the current resource" do - @provider.load_current_resource.should equal(@provider.current_resource) + @provider.load_current_resource.should equal(@provider.current_resource) end end @@ -91,7 +91,7 @@ describe Chef::Provider::User do @provider.compare_group.should be_true end end - + it "should return false if gid and members are equal" do @provider.compare_group.should be_false end @@ -116,29 +116,29 @@ describe Chef::Provider::User do @provider.should_receive(:create_group).and_return(true) @provider.run_action(:create) end - - it "should set the the new_resources updated flag when it creates the group" do + + it "should set the new_resources updated flag when it creates the group" do @provider.group_exists = false @provider.stub!(:create_group) @provider.run_action(:create) @provider.new_resource.should be_updated end - + it "should check to see if the group has mismatched attributes if the group exists" do @provider.group_exists = true @provider.stub!(:compare_group).and_return(false) @provider.run_action(:create) @provider.new_resource.should_not be_updated end - + it "should call manage_group if the group exists and has mismatched attributes" do @provider.group_exists = true @provider.stub!(:compare_group).and_return(true) @provider.should_receive(:manage_group).and_return(true) @provider.run_action(:create) end - - it "should set the the new_resources updated flag when it creates the group if we call manage_group" do + + it "should set the new_resources updated flag when it creates the group if we call manage_group" do @provider.group_exists = true @provider.stub!(:compare_group).and_return(true) @provider.stub!(:manage_group).and_return(true) @@ -148,14 +148,14 @@ describe Chef::Provider::User do end describe "when removing a group" do - + it "should not call remove_group if the group does not exist" do @provider.group_exists = false - @provider.should_not_receive(:remove_group) + @provider.should_not_receive(:remove_group) @provider.run_action(:remove) @provider.new_resource.should_not be_updated end - + it "should call remove_group if the group exists" do @provider.group_exists = true @provider.should_receive(:remove_group) @@ -169,26 +169,26 @@ describe Chef::Provider::User do @provider.group_exists = true @provider.stub!(:manage_group).and_return(true) end - + it "should run manage_group if the group exists and has mismatched attributes" do @provider.should_receive(:compare_group).and_return(true) @provider.should_receive(:manage_group).and_return(true) @provider.run_action(:manage) end - + it "should set the new resources updated flag to true if manage_group is called" do @provider.stub!(:compare_group).and_return(true) @provider.stub!(:manage_group).and_return(true) @provider.run_action(:manage) @new_resource.should be_updated end - + it "should not run manage_group if the group does not exist" do @provider.group_exists = false @provider.should_not_receive(:manage_group) @provider.run_action(:manage) end - + it "should not run manage_group if the group exists but has no differing attributes" do @provider.should_receive(:compare_group).and_return(false) @provider.should_not_receive(:manage_group) @@ -201,26 +201,26 @@ describe Chef::Provider::User do @provider.group_exists = true @provider.stub!(:manage_group).and_return(true) end - + it "should run manage_group if the group exists and has mismatched attributes" do @provider.should_receive(:compare_group).and_return(true) @provider.should_receive(:manage_group).and_return(true) @provider.run_action(:modify) end - + it "should set the new resources updated flag to true if manage_group is called" do @provider.stub!(:compare_group).and_return(true) @provider.stub!(:manage_group).and_return(true) @provider.run_action(:modify) @new_resource.should be_updated end - + it "should not run manage_group if the group exists but has no differing attributes" do @provider.should_receive(:compare_group).and_return(false) @provider.should_not_receive(:manage_group) @provider.run_action(:modify) end - + it "should raise a Chef::Exceptions::Group if the group doesn't exist" do @provider.group_exists = false lambda { @provider.run_action(:modify) }.should raise_error(Chef::Exceptions::Group) @@ -230,7 +230,7 @@ describe Chef::Provider::User do describe "when determining the reason for a change" do it "should report which group members are missing if members are missing and appending to the group" do @new_resource.members << "user1" - @new_resource.members << "user2" + @new_resource.members << "user2" @new_resource.stub!(:append).and_return true @provider.compare_group.should be_true @provider.change_desc.should == "add missing member(s): user1, user2" @@ -238,7 +238,7 @@ describe Chef::Provider::User do it "should report that the group members will be overwritten if not appending" do @new_resource.members << "user1" - @new_resource.stub!(:append).and_return false + @new_resource.stub!(:append).and_return false @provider.compare_group.should be_true @provider.change_desc.should == "replace group members with new list of members" end diff --git a/spec/unit/provider/http_request_spec.rb b/spec/unit/provider/http_request_spec.rb index 436eaec558..e8ce5f9ae3 100644 --- a/spec/unit/provider/http_request_spec.rb +++ b/spec/unit/provider/http_request_spec.rb @@ -35,7 +35,7 @@ describe Chef::Provider::HttpRequest do describe "load_current_resource" do it "should set up a Chef::REST client, with no authentication" do - Chef::REST.should_receive(:new).with(@new_resource.url, nil, nil) + Chef::HTTP::Simple.should_receive(:new).with(@new_resource.url) @provider.load_current_resource end end @@ -45,21 +45,21 @@ describe Chef::Provider::HttpRequest do # run_action(x) forces load_current_resource to run; # that would overwrite our supplied mock Chef::Rest # object @provider.stub!(:load_current_resource).and_return(true) - @rest = mock("Chef::REST") - @provider.rest = @rest + @http = mock("Chef::REST") + @provider.http = @http end describe "action_get" do it "should inflate a message block at runtime" do @new_resource.message { "return" } - @rest.should_receive(:get).with("http://www.opscode.com/?message=return", false, {}) + @http.should_receive(:get).with("http://www.opscode.com/?message=return", {}) @provider.run_action(:get) @new_resource.should be_updated end it "should run a GET request" do - @rest.should_receive(:get).with("http://www.opscode.com/?message=is cool", false, {}) + @http.should_receive(:get).with("http://www.opscode.com/?message=is cool", {}) @provider.run_action(:get) @new_resource.should be_updated end @@ -67,14 +67,14 @@ describe Chef::Provider::HttpRequest do describe "action_put" do it "should run a PUT request with the message as the payload" do - @rest.should_receive(:put).with("http://www.opscode.com/", @new_resource.message, {}) + @http.should_receive(:put).with("http://www.opscode.com/", @new_resource.message, {}) @provider.run_action(:put) @new_resource.should be_updated end it "should inflate a message block at runtime" do @new_resource.stub!(:message).and_return(lambda { "return" }) - @rest.should_receive(:put).with("http://www.opscode.com/", "return", {}) + @http.should_receive(:put).with("http://www.opscode.com/", "return", {}) @provider.run_action(:put) @new_resource.should be_updated end @@ -82,14 +82,14 @@ describe Chef::Provider::HttpRequest do describe "action_post" do it "should run a PUT request with the message as the payload" do - @rest.should_receive(:post).with("http://www.opscode.com/", @new_resource.message, {}) + @http.should_receive(:post).with("http://www.opscode.com/", @new_resource.message, {}) @provider.run_action(:post) @new_resource.should be_updated end it "should inflate a message block at runtime" do @new_resource.message { "return" } - @rest.should_receive(:post).with("http://www.opscode.com/", "return", {}) + @http.should_receive(:post).with("http://www.opscode.com/", "return", {}) @provider.run_action(:post) @new_resource.should be_updated end @@ -97,7 +97,7 @@ describe Chef::Provider::HttpRequest do describe "action_delete" do it "should run a DELETE request" do - @rest.should_receive(:delete).with("http://www.opscode.com/", {}) + @http.should_receive(:delete).with("http://www.opscode.com/", {}) @provider.run_action(:delete) @new_resource.should be_updated end @@ -105,30 +105,30 @@ describe Chef::Provider::HttpRequest do describe "action_head" do before do - @provider.rest = @rest + @provider.http = @http end it "should inflate a message block at runtime" do @new_resource.message { "return" } - @rest.should_receive(:head).with("http://www.opscode.com/?message=return", {}).and_return("") + @http.should_receive(:head).with("http://www.opscode.com/?message=return", {}).and_return("") @provider.run_action(:head) @new_resource.should be_updated end it "should run a HEAD request" do - @rest.should_receive(:head).with("http://www.opscode.com/?message=is cool", {}).and_return("") + @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", {}).and_return("") @provider.run_action(:head) @new_resource.should be_updated end it "should run a HEAD request with If-Modified-Since header" do @new_resource.headers "If-Modified-Since" => File.mtime(__FILE__).httpdate - @rest.should_receive(:head).with("http://www.opscode.com/?message=is cool", @new_resource.headers) + @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", @new_resource.headers) @provider.run_action(:head) end it "doesn't call converge_by if HEAD does not return modified" do - @rest.should_receive(:head).and_return(false) + @http.should_receive(:head).and_return(false) @provider.should_not_receive(:converge_by) @provider.run_action(:head) end diff --git a/spec/unit/provider/ifconfig/aix_spec.rb b/spec/unit/provider/ifconfig/aix_spec.rb new file mode 100644 index 0000000000..39e9919740 --- /dev/null +++ b/spec/unit/provider/ifconfig/aix_spec.rb @@ -0,0 +1,180 @@ +# +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.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/exceptions' + +describe Chef::Provider::Ifconfig::Aix do + + before(:all) do + @ifconfig_output = <<-IFCONFIG +en1: flags=1e080863,480<UP,BROADCAST,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST,GROUPRT,64BIT,CHECKSUM_OFFLOAD(ACTIVE),CHAIN> + inet 10.153.11.59 netmask 0xffff0000 broadcast 10.153.255.255 + tcp_sendspace 262144 tcp_recvspace 262144 rfc1323 1 +en0: flags=1e080863,480<UP,BROADCAST,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST,GROUPRT,64BIT,CHECKSUM_OFFLOAD(ACTIVE),CHAIN> metric 1 + inet 172.29.174.58 netmask 0xffffc000 broadcast 172.29.191.255 + tcp_sendspace 262144 tcp_recvspace 262144 rfc1323 1 +lo0: flags=e08084b,c0<UP,BROADCAST,LOOPBACK,RUNNING,SIMPLEX,MULTICAST,GROUPRT,64BIT,LARGESEND,CHAIN> + inet 127.0.0.1 netmask 0xff000000 broadcast 127.255.255.255 + inet6 ::1%1/0 +IFCONFIG + end + + + before(:each) do + @node = Chef::Node.new + @cookbook_collection = Chef::CookbookCollection.new([]) + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events) + + @new_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context) + + @provider = Chef::Provider::Ifconfig::Aix.new(@new_resource, @run_context) + end + + describe "#load_current_resource" do + before do + status = double("Status", :exitstatus => 0) + @provider.should_receive(:popen4).with("ifconfig -a").and_yield(@pid,@stdin,StringIO.new(@ifconfig_output),@stderr).and_return(status) + @new_resource.device "en0" + end + it "should load given interface with attributes." do + current_resource = @provider.load_current_resource + expect(current_resource.inet_addr).to eq("172.29.174.58") + expect(current_resource.target).to eq(@new_resource.target) + expect(current_resource.mask).to eq("255.255.192.0") + expect(current_resource.bcast).to eq("172.29.191.255") + expect(current_resource.metric).to eq("1") + end + end + + describe "#action_add" do + + it "should add an interface if it does not exist" do + @new_resource.device "en10" + @provider.stub!(:load_current_resource) do + @provider.instance_variable_set("@status", double("Status", :exitstatus => 0)) + @provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)) + end + command = "chdev -l #{@new_resource.device} -a netaddr=#{@new_resource.name}" + @provider.should_receive(:run_command).with(:command => command) + + @provider.run_action(:add) + @new_resource.should be_updated + end + + it "should raise exception if metric attribute is set" do + @new_resource.device "en0" + @new_resource.metric "1" + @provider.stub!(:load_current_resource) do + @provider.instance_variable_set("@status", double("Status", :exitstatus => 0)) + @provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)) + end + + expect{@provider.run_action(:add)}.to raise_error(Chef::Exceptions::Ifconfig, "interface metric attribute cannot be set for :add action") + end + end + + describe "#action_enable" do + it "should enable an interface if it does not exist" do + @new_resource.device "en10" + @provider.stub!(:load_current_resource) do + @provider.instance_variable_set("@status", double("Status", :exitstatus => 0)) + @provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)) + end + command = "ifconfig #{@new_resource.device} #{@new_resource.name}" + @provider.should_receive(:run_command).with(:command => command) + + @provider.run_action(:enable) + @new_resource.should be_updated + end + end + + describe "#action_disable" do + + it "should not disable an interface if it does not exist" do + @new_resource.device "en10" + @provider.stub!(:load_current_resource) do + @provider.instance_variable_set("@status", double("Status", :exitstatus => 0)) + @provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)) + end + + @provider.should_not_receive(:run_command) + + @provider.run_action(:disable) + @new_resource.should_not be_updated + end + + context "interface exists" do + before do + @new_resource.device "en10" + @provider.stub!(:load_current_resource) do + @provider.instance_variable_set("@status", double("Status", :exitstatus => 0)) + current_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context) + current_resource.device @new_resource.device + @provider.instance_variable_set("@current_resource", current_resource) + end + end + + it "should disable an interface if it exists" do + command = "ifconfig #{@new_resource.device} down" + @provider.should_receive(:run_command).with(:command => command) + + @provider.run_action(:disable) + @new_resource.should be_updated + end + + end + end + + describe "#action_delete" do + + it "should not delete an interface if it does not exist" do + @new_resource.device "en10" + @provider.stub!(:load_current_resource) do + @provider.instance_variable_set("@status", double("Status", :exitstatus => 0)) + @provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)) + end + + @provider.should_not_receive(:run_command) + + @provider.run_action(:delete) + @new_resource.should_not be_updated + end + + context "interface exists" do + before do + @new_resource.device "en10" + @provider.stub!(:load_current_resource) do + @provider.instance_variable_set("@status", double("Status", :exitstatus => 0)) + current_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context) + current_resource.device @new_resource.device + @provider.instance_variable_set("@current_resource", current_resource) + end + end + + it "should delete an interface if it exists" do + command = "chdev -l #{@new_resource.device} -a state=down" + @provider.should_receive(:run_command).with(:command => command) + + @provider.run_action(:delete) + @new_resource.should be_updated + end + end + end +end diff --git a/spec/unit/provider/ifconfig_spec.rb b/spec/unit/provider/ifconfig_spec.rb index 1da14fc9ac..f4fdc23353 100644 --- a/spec/unit/provider/ifconfig_spec.rb +++ b/spec/unit/provider/ifconfig_spec.rb @@ -38,20 +38,20 @@ describe Chef::Provider::Ifconfig do status = mock("Status", :exitstatus => 0) @provider.instance_variable_set("@status", status) @provider.current_resource = @current_resource - + end - describe Chef::Provider::Ifconfig, "load_current_resource" do - before do + describe Chef::Provider::Ifconfig, "load_current_resource" do + before do status = mock("Status", :exitstatus => 1) - @provider.should_receive(:popen4).and_return status + @provider.should_receive(:popen4).and_return status @provider.load_current_resource end it "should track state of ifconfig failure." do @provider.instance_variable_get("@status").exitstatus.should_not == 0 end - it "should thrown an exception when ifconfig fails" do + it "should thrown an exception when ifconfig fails" do @provider.define_resource_requirements - lambda { @provider.process_resource_requirements }.should raise_error Chef::Exceptions::Ifconfig + lambda { @provider.process_resource_requirements }.should raise_error Chef::Exceptions::Ifconfig end end describe Chef::Provider::Ifconfig, "action_add" do @@ -72,7 +72,7 @@ describe Chef::Provider::Ifconfig do @provider.stub!(:load_current_resource) @provider.should_not_receive(:run_command) @current_resource.inet_addr "10.0.0.1" - @provider.should_receive(:generate_config) + @provider.should_not_receive(:generate_config) @provider.run_action(:add) @new_resource.should_not be_updated @@ -84,7 +84,7 @@ describe Chef::Provider::Ifconfig do end describe Chef::Provider::Ifconfig, "action_enable" do - + it "should enable interface if does not exist" do @provider.stub!(:load_current_resource) @current_resource.inet_addr nil @@ -129,7 +129,7 @@ describe Chef::Provider::Ifconfig do @new_resource.should_not be_updated end end - + describe Chef::Provider::Ifconfig, "action_disable" do it "should disable interface if it exists" do diff --git a/spec/unit/provider/link_spec.rb b/spec/unit/provider/link_spec.rb index 171e21171c..bd3204510b 100644 --- a/spec/unit/provider/link_spec.rb +++ b/spec/unit/provider/link_spec.rb @@ -241,8 +241,8 @@ describe Chef::Resource::Link, :not_supported_on_win2k3 do result end it 'create does no work' do - provider.file_class.should_not_receive(:symlink) - provider.file_class.should_not_receive(:link) + provider.file_class.should_not_receive(:symlink) + provider.file_class.should_not_receive(:link) provider.access_controls.should_not_receive(:set_all) provider.run_action(:create) end diff --git a/spec/unit/provider/log_spec.rb b/spec/unit/provider/log_spec.rb index fe3733240a..f6ff526dd4 100644 --- a/spec/unit/provider/log_spec.rb +++ b/spec/unit/provider/log_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -25,7 +25,7 @@ describe Chef::Provider::Log::ChefLog do @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) - end + end it "should be registered with the default platform hash" do Chef::Platform.platforms[:default][:log].should_not be_nil @@ -37,7 +37,7 @@ describe Chef::Provider::Log::ChefLog do Chef::Log.should_receive(:info).with(@log_str).and_return(true) @provider.action_write end - + it "should write the string to the Chef::Log object at debug level" do @new_resource = Chef::Resource::Log.new(@log_str) @new_resource.level :debug @@ -53,7 +53,7 @@ describe Chef::Provider::Log::ChefLog do Chef::Log.should_receive(:info).with(@log_str).and_return(true) @provider.action_write end - + it "should write the string to the Chef::Log object at warn level" do @new_resource = Chef::Resource::Log.new(@log_str) @new_resource.level :warn @@ -61,7 +61,7 @@ describe Chef::Provider::Log::ChefLog do Chef::Log.should_receive(:warn).with(@log_str).and_return(true) @provider.action_write end - + it "should write the string to the Chef::Log object at error level" do @new_resource = Chef::Resource::Log.new(@log_str) @new_resource.level :error @@ -69,7 +69,7 @@ describe Chef::Provider::Log::ChefLog do Chef::Log.should_receive(:error).with(@log_str).and_return(true) @provider.action_write end - + it "should write the string to the Chef::Log object at fatal level" do @new_resource = Chef::Resource::Log.new(@log_str) @new_resource.level :fatal @@ -77,5 +77,5 @@ describe Chef::Provider::Log::ChefLog do Chef::Log.should_receive(:fatal).with(@log_str).and_return(true) @provider.action_write end - + end diff --git a/spec/unit/provider/mdadm_spec.rb b/spec/unit/provider/mdadm_spec.rb index a818c37101..25991e4732 100644 --- a/spec/unit/provider/mdadm_spec.rb +++ b/spec/unit/provider/mdadm_spec.rb @@ -25,12 +25,8 @@ describe Chef::Provider::Mdadm do @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) - @new_resource = Chef::Resource::Mdadm.new('/dev/md1') - @new_resource.devices ["/dev/sdz1","/dev/sdz2"] - @new_resource.level 1 - @new_resource.chunk 256 - + @new_resource.devices ["/dev/sdz1","/dev/sdz2","/dev/sdz3"] @provider = Chef::Provider::Mdadm.new(@new_resource, @run_context) end @@ -58,9 +54,7 @@ describe Chef::Provider::Mdadm do describe "after the metadevice status is known" do before(:each) do @current_resource = Chef::Resource::Mdadm.new('/dev/md1') - @current_resource.devices ["/dev/sdz1","/dev/sdz2"] - @current_resource.level 1 - @current_resource.chunk 256 + @new_resource.level 5 @provider.stub!(:load_current_resource).and_return(true) @provider.current_resource = @current_resource end @@ -68,7 +62,7 @@ describe Chef::Provider::Mdadm do describe "when creating the metadevice" do it "should create the raid device if it doesnt exist" do @current_resource.exists(false) - expected_command = "yes | mdadm --create /dev/md1 --chunk=256 --level 1 --metadata=0.90 --raid-devices 2 /dev/sdz1 /dev/sdz2" + expected_command = "yes | mdadm --create /dev/md1 --level 5 --chunk=16 --metadata=0.90 --raid-devices 3 /dev/sdz1 /dev/sdz2 /dev/sdz3" @provider.should_receive(:shell_out!).with(expected_command) @provider.run_action(:create) end @@ -76,7 +70,16 @@ describe Chef::Provider::Mdadm do it "should specify a bitmap only if set" do @current_resource.exists(false) @new_resource.bitmap('grow') - expected_command = "yes | mdadm --create /dev/md1 --chunk=256 --level 1 --metadata=0.90 --bitmap=grow --raid-devices 2 /dev/sdz1 /dev/sdz2" + expected_command = "yes | mdadm --create /dev/md1 --level 5 --chunk=16 --metadata=0.90 --bitmap=grow --raid-devices 3 /dev/sdz1 /dev/sdz2 /dev/sdz3" + @provider.should_receive(:shell_out!).with(expected_command) + @provider.run_action(:create) + @new_resource.should be_updated_by_last_action + end + + it "should not specify a chunksize if raid level 1" do + @current_resource.exists(false) + @new_resource.level 1 + expected_command = "yes | mdadm --create /dev/md1 --level 1 --metadata=0.90 --raid-devices 3 /dev/sdz1 /dev/sdz2 /dev/sdz3" @provider.should_receive(:shell_out!).with(expected_command) @provider.run_action(:create) @new_resource.should be_updated_by_last_action @@ -93,7 +96,7 @@ describe Chef::Provider::Mdadm do describe "when asembling the metadevice" do it "should assemble the raid device if it doesnt exist" do @current_resource.exists(false) - expected_mdadm_cmd = "yes | mdadm --assemble /dev/md1 /dev/sdz1 /dev/sdz2" + expected_mdadm_cmd = "yes | mdadm --assemble /dev/md1 /dev/sdz1 /dev/sdz2 /dev/sdz3" @provider.should_receive(:shell_out!).with(expected_mdadm_cmd) @provider.run_action(:assemble) @new_resource.should be_updated_by_last_action diff --git a/spec/unit/provider/mount/aix_spec.rb b/spec/unit/provider/mount/aix_spec.rb new file mode 100644 index 0000000000..89de47038a --- /dev/null +++ b/spec/unit/provider/mount/aix_spec.rb @@ -0,0 +1,237 @@ +# +# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.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 'ostruct' + +describe Chef::Provider::Mount::Aix do + + before(:all) do + @mounted_output = <<-MOUNT + node mounted mounted over vfs date options +-------- --------------- --------------- ------ ------------ --------------- + /dev/sdz1 /tmp/foo jfs2 Jul 17 13:22 rw,log=/dev/hd8 +MOUNT + + @unmounted_output = <<-UNMOUNTED + node mounted mounted over vfs date options +-------- --------------- --------------- ------ ------------ --------------- + /dev/sdz2 / jfs2 Jul 17 13:22 rw,log=/dev/hd8 +UNMOUNTED + + @conflict_mounted_output = <<-MOUNT + node mounted mounted over vfs date options +-------- --------------- --------------- ------ ------------ --------------- + /dev/sdz3 /tmp/foo jfs2 Jul 17 13:22 rw,log=/dev/hd8 +MOUNT + + @enabled_output = <<-ENABLED +#MountPoint:Device:Vfs:Nodename:Type:Size:Options:AutoMount:Acct +/tmp/foo:/dev/sdz1:jfs2::bootfs:10485760:rw:yes:no +ENABLED + end + + before(:each) do + @node = Chef::Node.new + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, {}, @events) + + @new_resource = Chef::Resource::Mount.new("/tmp/foo") + @new_resource.device "/dev/sdz1" + @new_resource.device_type :device + @new_resource.fstype "jfs2" + + @new_resource.supports :remount => false + + @provider = Chef::Provider::Mount::Aix.new(@new_resource, @run_context) + + ::File.stub!(:exists?).with("/dev/sdz1").and_return true + ::File.stub!(:exists?).with("/tmp/foo").and_return true + end + + def stub_mounted(provider, mounted_output) + response = double("Mixlib::ShellOut command", :exitstatus => 0, :stdout => mounted_output, :stderr => "") + provider.should_receive(:shell_out!).with("mount").and_return(response) + end + + def stub_enabled(provider, enabled_output) + response = double("Mixlib::ShellOut command", :exitstatus => 0, :stdout => enabled_output, :stderr => "") + provider.should_receive(:shell_out).with("lsfs -c #{@new_resource.mount_point}").and_return(response) + end + + def stub_mounted_enabled(provider, mounted_output, enabled_output) + stub_mounted(provider, mounted_output) + stub_enabled(provider, enabled_output) + end + + describe "when discovering the current fs state" do + it "should set current_resource.mounted to true if device is already mounted" do + stub_mounted_enabled(@provider, @mounted_output, "") + @provider.load_current_resource + + expect(@provider.current_resource.mounted).to be_true + end + + it "should set current_resource.mounted to false if device is not mounted" do + stub_mounted_enabled(@provider, @unmounted_output, "") + + @provider.load_current_resource + + expect(@provider.current_resource.mounted).to be_false + end + + it "should set current_resource.mounted to false if the mount point is used for another device" do + stub_mounted_enabled(@provider, @conflict_mounted_output, "") + + @provider.load_current_resource + + expect(@provider.current_resource.mounted).to be_false + end + end + + # tests for #enabled? + it "should load current_resource with properties if device is already mounted and enabled" do + stub_mounted_enabled(@provider, @mounted_output, @enabled_output) + + @provider.load_current_resource + + expect(@provider.current_resource.enabled).to be_true + expect(@provider.current_resource.mounted).to be_true + expect(@provider.current_resource.mount_point).to eql(@new_resource.mount_point) + expect(@provider.current_resource.fstype).to eql("jfs2") + expect(@provider.current_resource.options).to eql(['rw']) + end + + describe "mount_fs" do + it "should mount resource if it is not mounted" do + stub_mounted_enabled(@provider, @unmounted_output, "") + + @provider.should_receive(:shell_out!).with("mount -v #{@new_resource.fstype} #{@new_resource.device} #{@new_resource.mount_point}") + + @provider.run_action(:mount) + end + + it "should not mount resource if it is already mounted" do + stub_mounted_enabled(@provider, @mounted_output, "") + + @provider.should_not_receive(:mount_fs) + + @provider.run_action(:mount) + end + end + + describe "umount_fs" do + it "should umount resource if it is already mounted" do + stub_mounted_enabled(@provider, @mounted_output, "") + + @provider.should_receive(:shell_out!).with("umount #{@new_resource.mount_point}") + + @provider.run_action(:umount) + end + + it "should not umount resource if it is not mounted" do + stub_mounted_enabled(@provider, @unmounted_output, "") + + @provider.should_not_receive(:umount_fs) + + @provider.run_action(:umount) + end + end + + describe "remount_fs" do + it "should remount resource if it is already mounted and it supports remounting" do + @new_resource.supports({:remount => true}) + stub_mounted_enabled(@provider, @mounted_output, "") + + @provider.should_receive(:shell_out!).with("mount -o remount #{@new_resource.device} #{@new_resource.mount_point}") + + @provider.run_action(:remount) + end + + it "should remount with new mount options if it is already mounted and it supports remounting" do + @new_resource.supports({:remount => true}) + @new_resource.options("nodev,rw") + stub_mounted_enabled(@provider, @mounted_output, "") + + @provider.should_receive(:shell_out!).with("mount -o remount,nodev,rw #{@new_resource.device} #{@new_resource.mount_point}") + + @provider.run_action(:remount) + end + end + + describe "enable_fs" do + it "should enable mount if it is mounted and not enabled" do + @new_resource.options("nodev,rw") + stub_mounted_enabled(@provider, @mounted_output, "") + filesystems = StringIO.new + ::File.stub!(:open).with("/etc/filesystems", "a").and_yield(filesystems) + + @provider.run_action(:enable) + + filesystems.string.should match(%r{^/tmp/foo:\n\tdev\t\t= /dev/sdz1\n\tvfs\t\t= jfs2\n\tmount\t\t= false\n\toptions\t\t= nodev,rw\n$}) + end + + it "should not enable mount if it is mounted and already enabled and mount options are unchanged" do + stub_mounted_enabled(@provider, @mounted_output, @enabled_output) + @new_resource.options "rw" + + @provider.should_not_receive(:enable_fs) + + @provider.run_action(:enable) + end + end + + describe "disable_fs" do + it "should disable mount if it is mounted and enabled" do + stub_mounted_enabled(@provider, @mounted_output, @enabled_output) + + ::File.stub!(:open).with("/etc/filesystems", "r").and_return(<<-ETCFILESYSTEMS) +/tmp/foo: + dev = /dev/sdz1 + vfs = jfs2 + log = /dev/hd8 + mount = true + check = true + vol = /opt + free = false + quota = no + +/tmp/abc: + dev = /dev/sdz2 + vfs = jfs2 + mount = true + options = rw +ETCFILESYSTEMS + + filesystems = StringIO.new + ::File.stub!(:open).with("/etc/filesystems", "w").and_yield(filesystems) + + @provider.run_action(:disable) + + filesystems.string.should match(%r{^/tmp/abc:\s+dev\s+= /dev/sdz2\s+vfs\s+= jfs2\s+mount\s+= true\s+options\s+= rw\n$}) + end + + it "should not disable mount if it is not mounted" do + stub_mounted_enabled(@provider, @unmounted_output, "") + + @provider.should_not_receive(:disable_fs) + + @provider.run_action(:disable) + end + end +end diff --git a/spec/unit/provider/mount/mount_spec.rb b/spec/unit/provider/mount/mount_spec.rb index 00cc9a10e2..cf0e8791de 100644 --- a/spec/unit/provider/mount/mount_spec.rb +++ b/spec/unit/provider/mount/mount_spec.rb @@ -36,6 +36,8 @@ describe Chef::Provider::Mount::Mount do ::File.stub!(:exists?).with("/dev/sdz1").and_return true ::File.stub!(:exists?).with("/tmp/foo").and_return true + ::File.stub!(:realpath).with("/dev/sdz1").and_return "/dev/sdz1" + ::File.stub!(:realpath).with("/tmp/foo").and_return "/tmp/foo" end describe "when discovering the current fs state" do diff --git a/spec/unit/provider/mount/windows_spec.rb b/spec/unit/provider/mount/windows_spec.rb index 74579b14fe..4c9916ae87 100644 --- a/spec/unit/provider/mount/windows_spec.rb +++ b/spec/unit/provider/mount/windows_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/provider/mount_spec.rb b/spec/unit/provider/mount_spec.rb index 1a98f10cb0..a44f9705ee 100644 --- a/spec/unit/provider/mount_spec.rb +++ b/spec/unit/provider/mount_spec.rb @@ -23,13 +23,13 @@ describe Chef::Provider::Mount do @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) - + @new_resource = Chef::Resource::Mount.new('/tmp/foo') @new_resource.device "/dev/sdz1" @new_resource.name "/tmp/foo" @new_resource.mount_point "/tmp/foo" @new_resource.fstype "ext3" - + @current_resource = Chef::Resource::Mount.new('/tmp/foo') @current_resource.device "/dev/sdz1" @current_resource.name "/tmp/foo" @@ -39,7 +39,7 @@ describe Chef::Provider::Mount do @provider = Chef::Provider::Mount.new(@new_resource, @run_context) @provider.current_resource = @current_resource end - + describe "when the target state is a mounted filesystem" do it "should mount the filesystem if it isn't mounted" do @@ -78,7 +78,7 @@ describe Chef::Provider::Mount do before do @new_resource.supports[:remount] = true end - + it "should remount the filesystem if it is mounted" do @current_resource.stub!(:mounted).and_return(true) @provider.should_receive(:remount_fs).and_return(true) @@ -93,8 +93,8 @@ describe Chef::Provider::Mount do @new_resource.should_not be_updated_by_last_action end end - describe "when the filesystem should be remounted and the resource does not support remounting" do - before do + describe "when the filesystem should be remounted and the resource does not support remounting" do + before do @new_resource.supports[:remount] = false end diff --git a/spec/unit/provider/package/aix_spec.rb b/spec/unit/provider/package/aix_spec.rb new file mode 100644 index 0000000000..6e936156a0 --- /dev/null +++ b/spec/unit/provider/package/aix_spec.rb @@ -0,0 +1,171 @@ +# +# Author:: Deepali Jagtap (deepali.jagtap@clogeny.com) +# Author:: Prabhu Das (prabhu.das@clogeny.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::Package::Aix do + before(:each) do + @node = Chef::Node.new + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, {}, @events) + + @new_resource = Chef::Resource::Package.new("samba.base") + @new_resource.source("/tmp/samba.base") + + @provider = Chef::Provider::Package::Aix.new(@new_resource, @run_context) + ::File.stub!(:exists?).and_return(true) + end + + describe "assessing the current package status" do + before do + @bffinfo ="/usr/lib/objrepos:samba.base:3.3.12.0::COMMITTED:I:Samba for AIX: + /etc/objrepos:samba.base:3.3.12.0::COMMITTED:I:Samba for AIX:" + + @status = mock("Status", :exitstatus => 0) + end + + it "should create a current resource with the name of new_resource" do + @provider.stub!(:popen4).and_return(@status) + @provider.load_current_resource + @provider.current_resource.name.should == "samba.base" + end + + it "should set the current resource bff package name to the new resource bff package name" do + @provider.stub!(:popen4).and_return(@status) + @provider.load_current_resource + @provider.current_resource.package_name.should == "samba.base" + end + + it "should raise an exception if a source is supplied but not found" do + @provider.stub!(:popen4).and_return(@status) + ::File.stub!(:exists?).and_return(false) + @provider.define_resource_requirements + @provider.load_current_resource + lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Package) + end + + + it "should get the source package version from lslpp if provided" do + @stdout = StringIO.new(@bffinfo) + @stdin, @stderr = StringIO.new, StringIO.new + @provider.should_receive(:popen4).with("installp -L -d /tmp/samba.base").and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + @provider.should_receive(:popen4).with("lslpp -lcq samba.base").and_return(@status) + @provider.load_current_resource + + @provider.current_resource.package_name.should == "samba.base" + @new_resource.version.should == "3.3.12.0" + end + + it "should return the current version installed if found by lslpp" do + @stdout = StringIO.new(@bffinfo) + @stdin, @stderr = StringIO.new, StringIO.new + @provider.should_receive(:popen4).with("installp -L -d /tmp/samba.base").and_return(@status) + @provider.should_receive(:popen4).with("lslpp -lcq samba.base").and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + @provider.load_current_resource + @provider.current_resource.version.should == "3.3.12.0" + end + + it "should raise an exception if the source is not set but we are installing" do + @new_resource = Chef::Resource::Package.new("samba.base") + @provider = Chef::Provider::Package::Aix.new(@new_resource, @run_context) + @provider.stub!(:popen4).and_return(@status) + lambda { @provider.run_action(:install) }.should raise_error(Chef::Exceptions::Package) + end + + it "should raise an exception if installp/lslpp fails to run" do + @status = mock("Status", :exitstatus => -1) + @provider.stub!(:popen4).and_return(@status) + lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Package) + end + + it "should return a current resource with a nil version if the package is not found" do + @stdout = StringIO.new + @provider.should_receive(:popen4).with("installp -L -d /tmp/samba.base").and_return(@status) + @provider.should_receive(:popen4).with("lslpp -lcq samba.base").and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + @provider.load_current_resource + @provider.current_resource.version.should be_nil + end + end + + describe "candidate_version" do + it "should return the candidate_version variable if already setup" do + @provider.candidate_version = "3.3.12.0" + @provider.should_not_receive(:popen4) + @provider.candidate_version + end + + it "should lookup the candidate_version if the variable is not already set" do + @status = mock("Status", :exitstatus => 0) + @provider.should_receive(:popen4).and_return(@status) + @provider.candidate_version + end + + it "should throw and exception if the exitstatus is not 0" do + @status = mock("Status", :exitstatus => 1) + @provider.stub!(:popen4).and_return(@status) + lambda { @provider.candidate_version }.should raise_error(Chef::Exceptions::Package) + end + + end + + describe "install and upgrade" do + it "should run installp -aYF -d with the package source to install" do + @provider.should_receive(:run_command_with_systems_locale).with({ + :command => "installp -aYF -d /tmp/samba.base samba.base" + }) + @provider.install_package("samba.base", "3.3.12.0") + end + + it "should run when the package is a path to install" do + @new_resource = Chef::Resource::Package.new("/tmp/samba.base") + @provider = Chef::Provider::Package::Aix.new(@new_resource, @run_context) + @new_resource.source.should == "/tmp/samba.base" + @provider.should_receive(:run_command_with_systems_locale).with({ + :command => "installp -aYF -d /tmp/samba.base /tmp/samba.base" + }) + @provider.install_package("/tmp/samba.base", "3.3.12.0") + end + + it "should run installp with -eLogfile option." do + @new_resource.stub!(:options).and_return("-e/tmp/installp.log") + @provider.should_receive(:run_command_with_systems_locale).with({ + :command => "installp -aYF -e/tmp/installp.log -d /tmp/samba.base samba.base" + }) + @provider.install_package("samba.base", "3.3.12.0") + end + end + + describe "remove" do + it "should run installp -u samba.base to remove the package" do + @provider.should_receive(:run_command_with_systems_locale).with({ + :command => "installp -u samba.base" + }) + @provider.remove_package("samba.base", "3.3.12.0") + end + + it "should run installp -u -e/tmp/installp.log with options -e/tmp/installp.log" do + @new_resource.stub!(:options).and_return("-e/tmp/installp.log") + @provider.should_receive(:run_command_with_systems_locale).with({ + :command => "installp -u -e/tmp/installp.log samba.base" + }) + @provider.remove_package("samba.base", "3.3.12.0") + end + + end +end + diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb index 06ada5189e..32b55163b4 100644 --- a/spec/unit/provider/package/apt_spec.rb +++ b/spec/unit/provider/package/apt_spec.rb @@ -25,11 +25,9 @@ describe Chef::Provider::Package::Apt do @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) @new_resource = Chef::Resource::Package.new("irssi", @run_context) - @current_resource = Chef::Resource::Package.new("irssi", @run_context) @status = mock("Status", :exitstatus => 0) @provider = Chef::Provider::Package::Apt.new(@new_resource, @run_context) - Chef::Resource::Package.stub!(:new).and_return(@current_resource) @stdin = StringIO.new @stdout =<<-PKG_STATUS irssi: @@ -39,34 +37,21 @@ irssi: 0.8.14-1ubuntu4 0 500 http://us.archive.ubuntu.com/ubuntu/ lucid/main Packages PKG_STATUS - @stderr = StringIO.new - @pid = 12345 + @stderr = "" @shell_out = OpenStruct.new(:stdout => @stdout,:stdin => @stdin,:stderr => @stderr,:status => @status,:exitstatus => 0) end describe "when loading current resource" do it "should create a current resource with the name of the new_resource" do - @provider.should_receive(:shell_out!).and_return(@shell_out) - Chef::Resource::Package.should_receive(:new).and_return(@current_resource) - @provider.load_current_resource - end - - it "should set the current resources package name to the new resources package name" do - @provider.should_receive(:shell_out!).and_return(@shell_out) - @current_resource.should_receive(:package_name).with(@new_resource.package_name) - @provider.load_current_resource - end - - it "should run apt-cache policy with the package name" do @provider.should_receive(:shell_out!).with("apt-cache policy #{@new_resource.package_name}").and_return(@shell_out) @provider.load_current_resource - end - it "should set the installed version to nil on the current resource if package state is not installed" do - @provider.should_receive(:shell_out!).and_return(@shell_out) - @current_resource.should_receive(:version).with(nil).and_return(true) - @provider.load_current_resource + current_resource = @provider.current_resource + current_resource.should be_a(Chef::Resource::Package) + current_resource.name.should == "irssi" + current_resource.package_name.should == "irssi" + current_resource.version.should be_nil end it "should set the installed version if package has one" do @@ -84,15 +69,10 @@ sudo: INSTALLED @provider.should_receive(:shell_out!).and_return(@shell_out) @provider.load_current_resource - @current_resource.version.should == "1.7.2p1-1ubuntu5.3" + @provider.current_resource.version.should == "1.7.2p1-1ubuntu5.3" @provider.candidate_version.should eql("1.7.2p1-1ubuntu5.3") end - it "should return the current resouce" do - @provider.should_receive(:shell_out!).and_return(@shell_out) - @provider.load_current_resource.should eql(@current_resource) - end - # libmysqlclient-dev is a real package in newer versions of debian + ubuntu # list of virtual packages: http://www.debian.org/doc/packaging-manuals/virtual-package-names-list.txt it "should not install the virtual package there is a single provider package and it is installed" do @@ -107,18 +87,18 @@ VPKG_STDOUT @provider.should_receive(:shell_out!).with("apt-cache policy libmysqlclient15-dev").and_return(virtual_package) showpkg_out =<<-SHOWPKG_STDOUT Package: libmysqlclient15-dev -Versions: +Versions: -Reverse Depends: +Reverse Depends: libmysqlclient-dev,libmysqlclient15-dev libmysqlclient-dev,libmysqlclient15-dev libmysqlclient-dev,libmysqlclient15-dev libmysqlclient-dev,libmysqlclient15-dev libmysqlclient-dev,libmysqlclient15-dev libmysqlclient-dev,libmysqlclient15-dev -Dependencies: -Provides: -Reverse Provides: +Dependencies: +Provides: +Reverse Provides: libmysqlclient-dev 5.1.41-3ubuntu12.7 libmysqlclient-dev 5.1.41-3ubuntu12.10 libmysqlclient-dev 5.1.41-3ubuntu12 @@ -140,7 +120,6 @@ libmysqlclient-dev: RPKG_STDOUT real_package = mock(:stdout => real_package_out,:exitstatus => 0) @provider.should_receive(:shell_out!).with("apt-cache policy libmysqlclient-dev").and_return(real_package) - @provider.should_not_receive(:run_command_with_systems_locale) @provider.load_current_resource end @@ -156,17 +135,17 @@ VPKG_STDOUT @provider.should_receive(:shell_out!).with("apt-cache policy mp3-decoder").and_return(virtual_package) showpkg_out=<<-SHOWPKG_STDOUT Package: mp3-decoder -Versions: +Versions: -Reverse Depends: +Reverse Depends: nautilus,mp3-decoder vux,mp3-decoder plait,mp3-decoder ecasound,mp3-decoder nautilus,mp3-decoder -Dependencies: -Provides: -Reverse Provides: +Dependencies: +Provides: +Reverse Provides: vlc-nox 1.0.6-1ubuntu1.8 vlc 1.0.6-1ubuntu1.8 vlc-nox 1.0.6-1ubuntu1 @@ -192,160 +171,140 @@ SHOWPKG_STDOUT end - describe "install_package" do - it "should run apt-get install with the package name and version" do - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "apt-get -q -y install irssi=0.8.12-7", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }) - @provider.install_package("irssi", "0.8.12-7") - end - - it "should run apt-get install with the package name and version and options if specified" do - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "apt-get -q -y --force-yes install irssi=0.8.12-7", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }) - @new_resource.stub!(:options).and_return("--force-yes") - - @provider.install_package("irssi", "0.8.12-7") - end - - it "should run apt-get install with the package name and version and default_release if there is one and provider is explicitly defined" do - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "apt-get -q -y -o APT::Default-Release=lenny-backports install irssi=0.8.12-7", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }) - @new_resource.stub!(:default_release).and_return("lenny-backports") - @new_resource.stub!(:provider).and_return("Chef::Provider::Package::Apt") - - @provider.install_package("irssi", "0.8.12-7") - end - end - - describe Chef::Provider::Package::Apt, "upgrade_package" do - - it "should run install_package with the name and version" do - @provider.should_receive(:install_package).with("irssi", "0.8.12-7") - @provider.upgrade_package("irssi", "0.8.12-7") + context "after loading the current resource" do + before do + @current_resource = Chef::Resource::Package.new("irssi", @run_context) + @provider.current_resource = @current_resource end - end - describe Chef::Provider::Package::Apt, "remove_package" do - - it "should run apt-get remove with the package name" do - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "apt-get -q -y remove irssi", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }) - @provider.remove_package("irssi", "0.8.12-7") + describe "install_package" do + it "should run apt-get install with the package name and version" do + @provider.should_receive(:shell_out!). + with("apt-get -q -y install irssi=0.8.12-7", + :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil}) + @provider.install_package("irssi", "0.8.12-7") + end + + it "should run apt-get install with the package name and version and options if specified" do + @provider.should_receive(:shell_out!). + with("apt-get -q -y --force-yes install irssi=0.8.12-7", + :env => {"DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil }) + @new_resource.options("--force-yes") + @provider.install_package("irssi", "0.8.12-7") + end + + it "should run apt-get install with the package name and version and default_release if there is one and provider is explicitly defined" do + @new_resource = nil + @new_resource = Chef::Resource::AptPackage.new("irssi", @run_context) + @new_resource.default_release("lenny-backports") + + @provider.new_resource = @new_resource + + @provider.should_receive(:shell_out!). + with("apt-get -q -y -o APT::Default-Release=lenny-backports install irssi=0.8.12-7", + :env => {"DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil }) + + @provider.install_package("irssi", "0.8.12-7") + end end - it "should run apt-get remove with the package name and options if specified" do - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "apt-get -q -y --force-yes remove irssi", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }) - @new_resource.stub!(:options).and_return("--force-yes") + describe Chef::Provider::Package::Apt, "upgrade_package" do - @provider.remove_package("irssi", "0.8.12-7") + it "should run install_package with the name and version" do + @provider.should_receive(:install_package).with("irssi", "0.8.12-7") + @provider.upgrade_package("irssi", "0.8.12-7") + end end - end - describe "when purging a package" do + describe Chef::Provider::Package::Apt, "remove_package" do - it "should run apt-get purge with the package name" do - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "apt-get -q -y purge irssi", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }) - @provider.purge_package("irssi", "0.8.12-7") - end + it "should run apt-get remove with the package name" do + @provider.should_receive(:shell_out!). + with("apt-get -q -y remove irssi", + :env => {"DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil}) + @provider.remove_package("irssi", "0.8.12-7") + end - it "should run apt-get purge with the package name and options if specified" do - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "apt-get -q -y --force-yes purge irssi", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }) - @new_resource.stub!(:options).and_return("--force-yes") + it "should run apt-get remove with the package name and options if specified" do + @provider.should_receive(:shell_out!). + with("apt-get -q -y --force-yes remove irssi", + :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil }) + @new_resource.options("--force-yes") - @provider.purge_package("irssi", "0.8.12-7") + @provider.remove_package("irssi", "0.8.12-7") + end end - end - describe "when preseeding a package" do - before(:each) do - @provider.stub!(:get_preseed_file).and_return("/tmp/irssi-0.8.12-7.seed") - @provider.stub!(:run_command_with_systems_locale).and_return(true) - end + describe "when purging a package" do - it "should get the full path to the preseed response file" do - @provider.should_receive(:get_preseed_file).with("irssi", "0.8.12-7").and_return("/tmp/irssi-0.8.12-7.seed") - file = @provider.get_preseed_file("irssi", "0.8.12-7") - @provider.preseed_package(file) - end + it "should run apt-get purge with the package name" do + @provider.should_receive(:shell_out!). + with("apt-get -q -y purge irssi", + :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil }) + @provider.purge_package("irssi", "0.8.12-7") + end - it "should run debconf-set-selections on the preseed file if it has changed" do - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "debconf-set-selections /tmp/irssi-0.8.12-7.seed", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }).and_return(true) - file = @provider.get_preseed_file("irssi", "0.8.12-7") - @provider.preseed_package(file) - end + it "should run apt-get purge with the package name and options if specified" do + @provider.should_receive(:shell_out!). + with("apt-get -q -y --force-yes purge irssi", + :env => { "DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil }) + @new_resource.options("--force-yes") - it "should not run debconf-set-selections if the preseed file has not changed" do - @provider.stub(:check_package_state) - @current_resource.version "0.8.11" - @new_resource.response_file "/tmp/file" - @provider.stub!(:get_preseed_file).and_return(false) - @provider.should_not_receive(:run_command_with_systems_locale) - @provider.run_action(:reconfig) + @provider.purge_package("irssi", "0.8.12-7") + end end - end - describe "when reconfiguring a package" do - before(:each) do - @provider.stub!(:run_command_with_systems_locale).and_return(true) + describe "when preseeding a package" do + before(:each) do + @provider.stub!(:get_preseed_file).and_return("/tmp/irssi-0.8.12-7.seed") + end + + it "should get the full path to the preseed response file" do + @provider.should_receive(:get_preseed_file).with("irssi", "0.8.12-7").and_return("/tmp/irssi-0.8.12-7.seed") + file = @provider.get_preseed_file("irssi", "0.8.12-7") + + @provider.should_receive(:shell_out!). + with("debconf-set-selections /tmp/irssi-0.8.12-7.seed", + :env => {"DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil}) + + @provider.preseed_package(file) + end + + it "should run debconf-set-selections on the preseed file if it has changed" do + @provider.should_receive(:shell_out!). + with("debconf-set-selections /tmp/irssi-0.8.12-7.seed", + :env => {"DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil}) + file = @provider.get_preseed_file("irssi", "0.8.12-7") + @provider.preseed_package(file) + end + + it "should not run debconf-set-selections if the preseed file has not changed" do + @provider.stub(:check_package_state) + @current_resource.version "0.8.11" + @new_resource.response_file "/tmp/file" + @provider.stub!(:get_preseed_file).and_return(false) + @provider.should_not_receive(:shell_out!) + @provider.run_action(:reconfig) + end end - it "should run dpkg-reconfigure package" do - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "dpkg-reconfigure irssi", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }).and_return(true) - @provider.reconfig_package("irssi", "0.8.12-7") + describe "when reconfiguring a package" do + it "should run dpkg-reconfigure package" do + @provider.should_receive(:shell_out!). + with("dpkg-reconfigure irssi", + :env => {"DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil }) + @provider.reconfig_package("irssi", "0.8.12-7") + end end - end - describe "when installing a virtual package" do - it "should install the package without specifying a version" do - @provider.is_virtual_package = true - @provider.should_receive(:run_command_with_systems_locale).with({ - :command => "apt-get -q -y install libmysqlclient-dev", - :environment => { - "DEBIAN_FRONTEND" => "noninteractive" - } - }) - @provider.install_package("libmysqlclient-dev", "not_a_real_version") + describe "when installing a virtual package" do + it "should install the package without specifying a version" do + @provider.is_virtual_package = true + @provider.should_receive(:shell_out!). + with("apt-get -q -y install libmysqlclient-dev", + :env => {"DEBIAN_FRONTEND" => "noninteractive", "LC_ALL" => nil }) + @provider.install_package("libmysqlclient-dev", "not_a_real_version") + end end end end diff --git a/spec/unit/provider/package/dpkg_spec.rb b/spec/unit/provider/package/dpkg_spec.rb index aa22e0a2a3..30021e31f3 100644 --- a/spec/unit/provider/package/dpkg_spec.rb +++ b/spec/unit/provider/package/dpkg_spec.rb @@ -60,15 +60,15 @@ describe Chef::Provider::Package::Dpkg do @provider.current_resource.package_name.should == "wget" @new_resource.version.should == version end - + it 'if short version provided' do check_version('1.11.4') end - + it 'if extended version provided' do check_version('1.11.4-1ubuntu1') end - + it 'if distro-specific version provided' do check_version('1.11.4-1ubuntu1~lucid') end diff --git a/spec/unit/provider/package/freebsd_spec.rb b/spec/unit/provider/package/freebsd_spec.rb index 270c85d934..2901b84f49 100644 --- a/spec/unit/provider/package/freebsd_spec.rb +++ b/spec/unit/provider/package/freebsd_spec.rb @@ -211,6 +211,34 @@ describe Chef::Provider::Package::Freebsd, "load_current_resource" do end end + # CHEF-4371 + # There are some port names that contain special characters such as +'s. This breaks the regular expression used to determine what + # version of a package is currently installed and to get the port_path. + # Example package name: bonnie++ + + describe Chef::Provider::Package::Freebsd, "bonnie++ (package with a plus in the name :: CHEF-4371)" do + before(:each) do + @new_resource = Chef::Resource::Package.new("bonnie++") + @current_resource = Chef::Resource::Package.new("bonnie++") + @provider = Chef::Provider::Package::Freebsd.new(@new_resource, @run_context) + @provider.current_resource = @current_resource + end + + it "should return the port path for a valid port name" do + whereis = OpenStruct.new(:stdout => "bonnie++: /usr/ports/benchmarks/bonnie++") + @provider.should_receive(:shell_out!).with("whereis -s bonnie++", :env => nil).and_return(whereis) + @provider.stub!(:port_name).and_return("bonnie++") + @provider.port_path.should == "/usr/ports/benchmarks/bonnie++" + end + + it "should return the version number when it is installed" do + pkg_info = OpenStruct.new(:stdout => "bonnie++-1.96") + @provider.should_receive(:shell_out!).with('pkg_info -E "bonnie++*"', :env => nil, :returns => [0,1]).and_return(pkg_info) + @provider.stub!(:package_name).and_return("bonnie++") + @provider.current_installed_version.should == "1.96" + end + end + # A couple of examples to show up the difficulty of determining the command to install the binary package given the port: # PORT DIRECTORY INSTALLED PACKAGE NAME COMMAND TO INSTALL PACKAGE # /usr/ports/lang/perl5.8 perl-5.8.8_1 pkg_add -r perl diff --git a/spec/unit/provider/package/ips_spec.rb b/spec/unit/provider/package/ips_spec.rb index 641a527012..95839dbe89 100644 --- a/spec/unit/provider/package/ips_spec.rb +++ b/spec/unit/provider/package/ips_spec.rb @@ -170,7 +170,7 @@ PKG_STATUS before do @new_resource.stub!(:accept_license).and_return(true) end - + it "should run pkg install with the --accept flag" do @provider.should_receive(:run_command_with_systems_locale).with({ :command => "pkg install -q --accept crypto/gnupg@2.0.17" diff --git a/spec/unit/provider/package/rpm_spec.rb b/spec/unit/provider/package/rpm_spec.rb index 9dd94a7441..86327be42b 100644 --- a/spec/unit/provider/package/rpm_spec.rb +++ b/spec/unit/provider/package/rpm_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -23,35 +23,35 @@ describe Chef::Provider::Package::Rpm do @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) - + @new_resource = Chef::Resource::Package.new("emacs") @new_resource.source "/tmp/emacs-21.4-20.el5.i386.rpm" - + @provider = Chef::Provider::Package::Rpm.new(@new_resource, @run_context) - + @status = mock("Status", :exitstatus => 0) ::File.stub!(:exists?).and_return(true) end - + describe "when determining the current state of the package" do - + it "should create a current resource with the name of new_resource" do @provider.stub!(:popen4).and_return(@status) @provider.load_current_resource @provider.current_resource.name.should == "emacs" end - + it "should set the current reource package name to the new resource package name" do @provider.stub!(:popen4).and_return(@status) @provider.load_current_resource @provider.current_resource.package_name.should == 'emacs' end - + it "should raise an exception if a source is supplied but not found" do ::File.stub!(:exists?).and_return(false) lambda { @provider.run_action(:any) }.should raise_error(Chef::Exceptions::Package) end - + it "should get the source package version from rpm if provided" do @stdout = StringIO.new("emacs 21.4-20.el5") @provider.should_receive(:popen4).with("rpm -qp --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' /tmp/emacs-21.4-20.el5.i386.rpm").and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) @@ -60,7 +60,7 @@ describe Chef::Provider::Package::Rpm do @provider.current_resource.package_name.should == "emacs" @provider.new_resource.version.should == "21.4-20.el5" end - + it "should return the current version installed if found by rpm" do @stdout = StringIO.new("emacs 21.4-20.el5") @provider.should_receive(:popen4).with("rpm -qp --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' /tmp/emacs-21.4-20.el5.i386.rpm").and_return(@status) @@ -68,20 +68,20 @@ describe Chef::Provider::Package::Rpm do @provider.load_current_resource @provider.current_resource.version.should == "21.4-20.el5" end - + it "should raise an exception if the source is not set but we are installing" do new_resource = Chef::Resource::Package.new("emacs") provider = Chef::Provider::Package::Rpm.new(new_resource, @run_context) lambda { provider.run_action(:any) }.should raise_error(Chef::Exceptions::Package) end - + it "should raise an exception if rpm fails to run" do status = mock("Status", :exitstatus => -1) @provider.stub!(:popen4).and_return(status) lambda { @provider.run_action(:any) }.should raise_error(Chef::Exceptions::Package) end end - + describe "after the current resource is loaded" do before do @current_resource = Chef::Resource::Package.new("emacs") @@ -95,7 +95,7 @@ describe Chef::Provider::Package::Rpm do }) @provider.install_package("emacs", "21.4-20.el5") end - + it "should run rpm -U with the package source to upgrade" do @current_resource.version("21.4-19.el5") @provider.should_receive(:run_command_with_systems_locale).with({ diff --git a/spec/unit/provider/package/smartos_spec.rb b/spec/unit/provider/package/smartos_spec.rb index 47db00988c..e5092f69d9 100644 --- a/spec/unit/provider/package/smartos_spec.rb +++ b/spec/unit/provider/package/smartos_spec.rb @@ -27,8 +27,8 @@ describe Chef::Provider::Package::SmartOS, "load_current_resource" do @run_context = Chef::RunContext.new(@node, {}, @events) @new_resource = Chef::Resource::Package.new("varnish") @current_resource = Chef::Resource::Package.new("varnish") - - + + @status = mock("Status", :exitstatus => 0) @provider = Chef::Provider::Package::SmartOS.new(@new_resource, @run_context) Chef::Resource::Package.stub!(:new).and_return(@current_resource) @@ -69,8 +69,26 @@ describe Chef::Provider::Package::SmartOS, "load_current_resource" do end + describe "candidate_version" do + it "should return the candidate_version variable if already setup" do + @provider.candidate_version = "2.1.1" + @provider.should_not_receive(:shell_out!) + @provider.candidate_version + end + + it "should lookup the candidate_version if the variable is not already set" do + search = mock() + search.should_receive(:each_line). + and_yield("something-varnish-1.1.1 something varnish like\n"). + and_yield("varnish-2.3.4 actual varnish\n") + @shell_out = mock('shell_out!', :stdout => search) + @provider.should_receive(:shell_out!).with('/opt/local/bin/pkgin se varnish', :env => nil, :returns => [0,1]).and_return(@shell_out) + @provider.candidate_version.should == "2.3.4" + end + end + describe "when manipulating a resource" do - + it "run pkgin and install the package" do out = OpenStruct.new(:stdout => nil) @provider.should_receive(:shell_out!).with("/opt/local/sbin/pkg_info -E \"varnish*\"", {:env => nil, :returns=>[0,1]}).and_return(@shell_out) diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb index 6e4cf6fe16..f80eed17bd 100644 --- a/spec/unit/provider/package_spec.rb +++ b/spec/unit/provider/package_spec.rb @@ -286,7 +286,7 @@ describe Chef::Provider::Package do @provider.should_not_receive(:reconfig_package) @provider.run_action(:reconfig) @new_resource.should_not be_updated_by_last_action - end + end it "should debug log and not reconfigure the package if no response_file is given" do @current_resource.stub!(:version).and_return('1.0') @@ -345,7 +345,9 @@ describe Chef::Provider::Package do cl = Chef::CookbookLoader.new(@cookbook_repo) cl.load_cookbooks @cookbook_collection = Chef::CookbookCollection.new(cl) + @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events) + @provider.run_context = @run_context @node.automatic_attrs[:platform] = 'PLATFORM: just testing' @node.automatic_attrs[:platform_version] = 'PLATFORM VERSION: just testing' @@ -358,8 +360,8 @@ describe Chef::Provider::Package do before do Chef::FileCache.should_receive(:create_cache_path).with('preseed/java').and_return("/tmp/preseed/java") end + it "sets the preseed resource's runcontext to its own run context" do - Chef::FileCache.rspec_reset Chef::FileCache.stub!(:create_cache_path).and_return("/tmp/preseed/java") @provider.preseed_resource('java', '6').run_context.should_not be_nil @provider.preseed_resource('java', '6').run_context.should equal(@provider.run_context) diff --git a/spec/unit/provider/powershell_spec.rb b/spec/unit/provider/powershell_spec.rb index ac4160080e..33c402836b 100644 --- a/spec/unit/provider/powershell_spec.rb +++ b/spec/unit/provider/powershell_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -24,7 +24,7 @@ describe Chef::Provider::PowershellScript, "action_run" do @node.default["kernel"] = Hash.new @node.default["kernel"][:machine] = :x86_64.to_s - + @run_context = Chef::RunContext.new(@node, {}, @events) @new_resource = Chef::Resource::PowershellScript.new('run some powershell code', @run_context) diff --git a/spec/unit/provider/remote_directory_spec.rb b/spec/unit/provider/remote_directory_spec.rb index f2bb1b4a3f..d3f1438f0f 100644 --- a/spec/unit/provider/remote_directory_spec.rb +++ b/spec/unit/provider/remote_directory_spec.rb @@ -57,10 +57,10 @@ describe Chef::Provider::RemoteDirectory do @provider_second_run.run_action(:create) end it "identifies that the state has changed the after first run" do - @provider_second_run.new_resource.updated_by_last_action? == true + @provider_second_run.new_resource.updated_by_last_action? == true end it "identifies that the state has not changed after the second run" do - @provider_second_run.new_resource.updated_by_last_action? == false + @provider_second_run.new_resource.updated_by_last_action? == false end end diff --git a/spec/unit/provider/remote_file/ftp_spec.rb b/spec/unit/provider/remote_file/ftp_spec.rb index 4022fb25d3..8dd1ef248e 100644 --- a/spec/unit/provider/remote_file/ftp_spec.rb +++ b/spec/unit/provider/remote_file/ftp_spec.rb @@ -200,16 +200,11 @@ describe Chef::Provider::RemoteFile::FTP do context "and proxying is enabled" do before do - @original_config = Chef::Config.hash_dup Chef::Config[:ftp_proxy] = "socks5://socks.example.com:5000" Chef::Config[:ftp_proxy_user] = "bill" Chef::Config[:ftp_proxy_pass] = "ted" end - after do - Chef::Config.configuration = @original_config - end - it "fetches the file via the proxy" do current_socks_server = ENV["SOCKS_SERVER"] ENV.should_receive(:[]=).with("SOCKS_SERVER", "socks5://bill:ted@socks.example.com:5000").ordered diff --git a/spec/unit/provider/remote_file/http_spec.rb b/spec/unit/provider/remote_file/http_spec.rb index 6ae19327eb..cb7271900d 100644 --- a/spec/unit/provider/remote_file/http_spec.rb +++ b/spec/unit/provider/remote_file/http_spec.rb @@ -155,16 +155,16 @@ describe Chef::Provider::RemoteFile::HTTP do describe "when fetching the uri" do let(:expected_http_opts) { {} } - let(:expected_http_args) { [uri, nil, nil, expected_http_opts] } + let(:expected_http_args) { [uri, expected_http_opts] } let(:tempfile_path) { "/tmp/chef-mock-tempfile-abc123" } - let(:tempfile) { mock(Tempfile, :path => tempfile_path) } + let(:tempfile) { mock(Tempfile, :path => tempfile_path, :close => nil) } let(:last_response) { {} } let(:rest) do - rest = mock(Chef::REST) + rest = mock(Chef::HTTP::Simple) rest.stub!(:streaming_request).and_return(tempfile) rest.stub!(:last_response).and_return(last_response) rest @@ -175,7 +175,7 @@ describe Chef::Provider::RemoteFile::HTTP do new_resource.use_last_modified(false) Chef::Provider::RemoteFile::CacheControlData.should_receive(:load_and_validate).with(uri, current_resource_checksum).and_return(cache_control_data) - Chef::REST.should_receive(:new).with(*expected_http_args).and_return(rest) + Chef::HTTP::Simple.should_receive(:new).with(*expected_http_args).and_return(rest) end @@ -188,7 +188,7 @@ describe Chef::Provider::RemoteFile::HTTP do lambda { fetcher.fetch }.should raise_error(Net::HTTPServerException) end - it "should return HTTPRetriableError when Chef::REST returns a 301" do + it "should return HTTPRetriableError when Chef::HTTP::Simple returns a 301" do r = Net::HTTPMovedPermanently.new("one", "two", "three") e = Net::HTTPRetriableError.new("301", r) rest.stub!(:streaming_request).and_raise(e) @@ -290,21 +290,21 @@ describe Chef::Provider::RemoteFile::HTTP do # CHEF-3140 # Some servers return tarballs as content type tar and encoding gzip, which - # is totally wrong. When this happens and gzip isn't disabled, Chef::REST + # is totally wrong. When this happens and gzip isn't disabled, Chef::HTTP::Simple # will decompress the file for you, which is not at all what you expected # to happen (you end up with an uncomressed tar archive instead of the # gzipped tar archive you expected). To work around this behavior, we # detect when users are fetching gzipped files and turn off gzip in - # Chef::REST. + # Chef::HTTP::Simple. it "should disable gzip compression in the client" do # Before block in the parent context has set an expectation on - # Chef::REST.new() being called with expected arguments. Here we fufil + # Chef::HTTP::Simple.new() being called with expected arguments. Here we fufil # that expectation, so that we can explicitly set it for this test. # This is intended to provide insurance that refactoring of the parent # context does not negate the value of this particular example. - Chef::REST.new(*expected_http_args) - Chef::REST.should_receive(:new).once.with(*expected_http_args).and_return(rest) + Chef::HTTP::Simple.new(*expected_http_args) + Chef::HTTP::Simple.should_receive(:new).once.with(*expected_http_args).and_return(rest) fetcher.fetch cache_control_data.etag.should be_nil cache_control_data.mtime.should be_nil diff --git a/spec/unit/provider/remote_file/local_file_spec.rb b/spec/unit/provider/remote_file/local_file_spec.rb index 6b318f972a..00634f50eb 100644 --- a/spec/unit/provider/remote_file/local_file_spec.rb +++ b/spec/unit/provider/remote_file/local_file_spec.rb @@ -40,7 +40,7 @@ describe Chef::Provider::RemoteFile::LocalFile do describe "when fetching the object" do - let(:tempfile) { mock("Tempfile", :path => "/tmp/foo/bar/nyan.png") } + let(:tempfile) { mock("Tempfile", :path => "/tmp/foo/bar/nyan.png", :close => nil) } let(:chef_tempfile) { mock("Chef::FileContentManagement::Tempfile", :tempfile => tempfile) } before do @@ -50,6 +50,7 @@ describe Chef::Provider::RemoteFile::LocalFile do it "stages the local file to a temporary file" do Chef::FileContentManagement::Tempfile.should_receive(:new).with(new_resource).and_return(chef_tempfile) ::FileUtils.should_receive(:cp).with(uri.path, tempfile.path) + tempfile.should_receive(:close) result = fetcher.fetch result.should == tempfile diff --git a/spec/unit/provider/route_spec.rb b/spec/unit/provider/route_spec.rb index 072cb2a698..863f12641c 100644 --- a/spec/unit/provider/route_spec.rb +++ b/spec/unit/provider/route_spec.rb @@ -111,13 +111,13 @@ describe Chef::Provider::Route do it "should not delete config file for :add action (CHEF-3332)" do @node.automatic_attrs[:platform] = 'centos' - + route_file = StringIO.new File.should_receive(:new).and_return(route_file) @resource_add = Chef::Resource::Route.new('192.168.1.0/24 via 192.168.0.1') @run_context.resource_collection << @resource_add @provider.stub!(:run_command).and_return(true) - + @resource_add.action(:add) @provider.run_action(:add) route_file.string.split("\n").should have(1).items diff --git a/spec/unit/provider/ruby_block_spec.rb b/spec/unit/provider/ruby_block_spec.rb index 7fc58c9c70..6e5c9a638b 100644 --- a/spec/unit/provider/ruby_block_spec.rb +++ b/spec/unit/provider/ruby_block_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/provider/service/arch_service_spec.rb b/spec/unit/provider/service/arch_service_spec.rb index a7afa28da1..0865fdae86 100644 --- a/spec/unit/provider/service/arch_service_spec.rb +++ b/spec/unit/provider/service/arch_service_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -61,8 +61,8 @@ describe Chef::Provider::Service::Arch, "load_current_resource" do @provider.should_receive(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(:exitstatus => 0)) @provider.load_current_resource end - - it "should set running to true if the the status command returns 0" do + + it "should set running to true if the status command returns 0" do @provider.stub!(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(:exitstatus => 0)) @provider.load_current_resource @provider.current_resource.running.should be_true @@ -92,7 +92,7 @@ describe Chef::Provider::Service::Arch, "load_current_resource" do @provider.should_receive(:shell_out).with("/etc/rc.d/chefhasmonkeypants status").and_return(OpenStruct.new(:exitstatus => 0)) @provider.load_current_resource end - + end it "should raise error if the node has a nil ps attribute and no other means to get status" do @@ -129,7 +129,7 @@ aj 8119 6041 0 21:34 pts/3 00:00:03 vi init_service_spec.rb DEFAULT_PS @status = mock("Status", :exitstatus => 0, :stdout => @stdout) @provider.stub!(:shell_out!).and_return(@status) - + @node.automatic_attrs[:command] = {:ps => "ps -ef"} end @@ -139,7 +139,7 @@ aj 7842 5057 0 21:26 pts/2 00:00:06 chef aj 7842 5057 0 21:26 pts/2 00:00:06 poos RUNNING_PS @status.stub!(:stdout).and_return(@stdout) - @provider.load_current_resource + @provider.load_current_resource @provider.current_resource.running.should be_true end @@ -162,13 +162,13 @@ RUNNING_PS ::File.stub!(:read).with("/etc/rc.conf").and_return("DAEMONS=(network !apache ssh)") @provider.daemons.should == ['network', '!apache', 'ssh'] end - + context "when the current service status is known" do before do @current_resource = Chef::Resource::Service.new("chef") @provider.current_resource = @current_resource end - + describe Chef::Provider::Service::Arch, "enable_service" do # before(:each) do # @new_resource = mock("Chef::Resource::Service", @@ -178,7 +178,7 @@ RUNNING_PS # :running => false # ) # @new_resource.stub!(:start_command).and_return(false) - # + # # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource) # Chef::Resource::Service.stub!(:new).and_return(@current_resource) # end @@ -199,7 +199,7 @@ RUNNING_PS # :running => false # ) # @new_resource.stub!(:start_command).and_return(false) - # + # # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource) # Chef::Resource::Service.stub!(:new).and_return(@current_resource) # end @@ -221,11 +221,11 @@ RUNNING_PS # :running => false # ) # @new_resource.stub!(:start_command).and_return(false) - # + # # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource) # Chef::Resource::Service.stub!(:new).and_return(@current_resource) # end - + it "should call the start command if one is specified" do @new_resource.stub!(:start_command).and_return("/etc/rc.d/chef startyousillysally") @provider.should_receive(:shell_out!).with("/etc/rc.d/chef startyousillysally") @@ -235,7 +235,7 @@ RUNNING_PS it "should call '/etc/rc.d/service_name start' if no start command is specified" do @provider.should_receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} start") @provider.start_service() - end + end end describe Chef::Provider::Service::Arch, "stop_service" do @@ -247,7 +247,7 @@ RUNNING_PS # :running => false # ) # @new_resource.stub!(:stop_command).and_return(false) - # + # # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource) # Chef::Resource::Service.stub!(:new).and_return(@current_resource) # end @@ -274,7 +274,7 @@ RUNNING_PS # ) # @new_resource.stub!(:restart_command).and_return(false) # @new_resource.stub!(:supports).and_return({:restart => false}) - # + # # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource) # Chef::Resource::Service.stub!(:new).and_return(@current_resource) # end @@ -309,7 +309,7 @@ RUNNING_PS # ) # @new_resource.stub!(:reload_command).and_return(false) # @new_resource.stub!(:supports).and_return({:reload => false}) - # + # # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource) # Chef::Resource::Service.stub!(:new).and_return(@current_resource) # end diff --git a/spec/unit/provider/service/debian_service_spec.rb b/spec/unit/provider/service/debian_service_spec.rb index bea9360561..ff0f4f421b 100644 --- a/spec/unit/provider/service/debian_service_spec.rb +++ b/spec/unit/provider/service/debian_service_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -18,7 +18,7 @@ require 'spec_helper' -describe Chef::Provider::Service::Debian, "load_current_resource" do +describe Chef::Provider::Service::Debian do before(:each) do @node = Chef::Node.new @node.automatic_attrs[:command] = {:ps => 'fuuuu'} @@ -26,95 +26,41 @@ describe Chef::Provider::Service::Debian, "load_current_resource" do @run_context = Chef::RunContext.new(@node, {}, @events) @new_resource = Chef::Resource::Service.new("chef") + @provider = Chef::Provider::Service::Debian.new(@new_resource, @run_context) @current_resource = Chef::Resource::Service.new("chef") - - @provider = Chef::Provider::Service::Debian.new(@new_resource, @run_context) @provider.current_resource = @current_resource @pid, @stdin, @stdout, @stderr = nil, nil, nil, nil - end - it "ensures /usr/sbin/update-rc.d is available" do - File.should_receive(:exists?).with("/usr/sbin/update-rc.d").and_return(false) - @provider.define_resource_requirements - lambda { @provider.process_resource_requirements } .should raise_error(Chef::Exceptions::Service) - end + describe "load_current_resource" do + it "ensures /usr/sbin/update-rc.d is available" do + File.should_receive(:exists?).with("/usr/sbin/update-rc.d") .and_return(false) - describe "when update-rc.d shows the init script linked to rc*.d/" do - before do - @provider.stub!(:assert_update_rcd_available) - - result=<<-UPDATE_RC_D_SUCCESS -Removing any system startup links for /etc/init.d/chef ... - /etc/rc0.d/K20chef - /etc/rc1.d/K20chef - /etc/rc2.d/S20chef - /etc/rc3.d/S20chef - /etc/rc4.d/S20chef - /etc/rc5.d/S20chef - /etc/rc6.d/K20chef - UPDATE_RC_D_SUCCESS - @stdout = StringIO.new(result) - @stderr = StringIO.new - @status = mock("Status", :exitstatus => 0, :stdout => @stdout) - @provider.stub!(:shell_out!).and_return(@status) - @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) - end - - it "says the service is enabled" do - @provider.service_currently_enabled?(@provider.get_priority).should be_true + @provider.define_resource_requirements + lambda { + @provider.process_resource_requirements + }.should raise_error(Chef::Exceptions::Service) end - it "stores the 'enabled' state" do - Chef::Resource::Service.stub!(:new).and_return(@current_resource) - @provider.load_current_resource.should equal(@current_resource) - @current_resource.enabled.should be_true - end - end - - {"Debian/Lenny and older" => { - "linked" => { - "stdout" => " Removing any system startup links for /etc/init.d/chef ... - /etc/rc0.d/K20chef - /etc/rc1.d/K20chef - /etc/rc2.d/S20chef - /etc/rc3.d/S20chef - /etc/rc4.d/S20chef - /etc/rc5.d/S20chef - /etc/rc6.d/K20chef", - "stderr" => "" - }, - "not linked" => { - "stdout" => " Removing any system startup links for /etc/init.d/chef ...", - "stderr" => "" - }, - }, - "Debian/Squeeze and earlier" => { - "linked" => { - "stdout" => "update-rc.d: using dependency based boot sequencing", - "stderr" => "insserv: remove service /etc/init.d/../rc0.d/K20chef-client -insserv: remove service /etc/init.d/../rc1.d/K20chef-client -insserv: remove service /etc/init.d/../rc2.d/S20chef-client -insserv: remove service /etc/init.d/../rc3.d/S20chef-client -insserv: remove service /etc/init.d/../rc4.d/S20chef-client -insserv: remove service /etc/init.d/../rc5.d/S20chef-client -insserv: remove service /etc/init.d/../rc6.d/K20chef-client -insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop" - }, - "not linked" => { - "stdout" => "update-rc.d: using dependency based boot sequencing", - "stderr" => "" - } - } - }.each do |model, streams| - describe "when update-rc.d shows the init script linked to rc*.d/" do + context "when update-rc.d shows init linked to rc*.d/" do before do @provider.stub!(:assert_update_rcd_available) - @stdout = StringIO.new(streams["linked"]["stdout"]) - @stderr = StringIO.new(streams["linked"]["stderr"]) + result = <<-UPDATE_RC_D_SUCCESS + Removing any system startup links for /etc/init.d/chef ... + /etc/rc0.d/K20chef + /etc/rc1.d/K20chef + /etc/rc2.d/S20chef + /etc/rc3.d/S20chef + /etc/rc4.d/S20chef + /etc/rc5.d/S20chef + /etc/rc6.d/K20chef + UPDATE_RC_D_SUCCESS + + @stdout = StringIO.new(result) + @stderr = StringIO.new @status = mock("Status", :exitstatus => 0, :stdout => @stdout) @provider.stub!(:shell_out!).and_return(@status) @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) @@ -129,25 +75,15 @@ insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop" @provider.load_current_resource.should equal(@current_resource) @current_resource.enabled.should be_true end - - it "stores the start/stop priorities of the service" do - @provider.load_current_resource - expected_priorities = {"6"=>[:stop, "20"], - "0"=>[:stop, "20"], - "1"=>[:stop, "20"], - "2"=>[:start, "20"], - "3"=>[:start, "20"], - "4"=>[:start, "20"], - "5"=>[:start, "20"]} - @provider.current_resource.priority.should == expected_priorities - end end - describe "when using squeeze/earlier and update-rc.d shows the init script isn't linked to rc*.d" do + context "when update-rc.d shows init isn't linked to rc*.d/" do before do @provider.stub!(:assert_update_rcd_available) - @stdout = StringIO.new(streams["not linked"]["stdout"]) - @stderr = StringIO.new(streams["not linked"]["stderr"]) + @status = mock("Status", :exitstatus => 0) + @stdout = StringIO.new( + " Removing any system startup links for /etc/init.d/chef ...") + @stderr = StringIO.new @status = mock("Status", :exitstatus => 0, :stdout => @stdout) @provider.stub!(:shell_out!).and_return(@status) @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) @@ -163,92 +99,246 @@ insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop" @current_resource.enabled.should be_false end end - end - describe "when update-rc.d shows the init script isn't linked to rc*.d" do - before do - @provider.stub!(:assert_update_rcd_available) - @status = mock("Status", :exitstatus => 0) - @stdout = StringIO.new(" Removing any system startup links for /etc/init.d/chef ...") - @stderr = StringIO.new - @status = mock("Status", :exitstatus => 0, :stdout => @stdout) - @provider.stub!(:shell_out!).and_return(@status) - @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) - end + context "when update-rc.d fails" do + before do + @status = mock("Status", :exitstatus => -1) + @provider.stub!(:popen4).and_return(@status) + end - it "says the service is disabled" do - @provider.service_currently_enabled?(@provider.get_priority).should be_false + it "raises an error" do + @provider.define_resource_requirements + lambda { + @provider.process_resource_requirements + }.should raise_error(Chef::Exceptions::Service) + end end - it "stores the 'disabled' state" do - Chef::Resource::Service.stub!(:new).and_return(@current_resource) - @provider.load_current_resource.should equal(@current_resource) - @current_resource.enabled.should be_false + {"Debian/Lenny and older" => { + "linked" => { + "stdout" => <<-STDOUT, + Removing any system startup links for /etc/init.d/chef ... + /etc/rc0.d/K20chef + /etc/rc1.d/K20chef + /etc/rc2.d/S20chef + /etc/rc3.d/S20chef + /etc/rc4.d/S20chef + /etc/rc5.d/S20chef + /etc/rc6.d/K20chef + STDOUT + "stderr" => "" + }, + "not linked" => { + "stdout" => + " Removing any system startup links for /etc/init.d/chef ...", + "stderr" => "" + }, + }, + "Debian/Squeeze and earlier" => { + "linked" => { + "stdout" => "update-rc.d: using dependency based boot sequencing", + "stderr" => <<-STDERR, +insserv: remove service /etc/init.d/../rc0.d/K20chef-client + insserv: remove service /etc/init.d/../rc1.d/K20chef-client + insserv: remove service /etc/init.d/../rc2.d/S20chef-client + insserv: remove service /etc/init.d/../rc3.d/S20chef-client + insserv: remove service /etc/init.d/../rc4.d/S20chef-client + insserv: remove service /etc/init.d/../rc5.d/S20chef-client + insserv: remove service /etc/init.d/../rc6.d/K20chef-client + insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop + STDERR + }, + "not linked" => { + "stdout" => "update-rc.d: using dependency based boot sequencing", + "stderr" => "" + } + } + }.each do |model, streams| + context "on #{model}" do + context "when update-rc.d shows init linked to rc*.d/" do + before do + @provider.stub!(:assert_update_rcd_available) + + @stdout = StringIO.new(streams["linked"]["stdout"]) + @stderr = StringIO.new(streams["linked"]["stderr"]) + @status = mock("Status", :exitstatus => 0, :stdout => @stdout) + @provider.stub!(:shell_out!).and_return(@status) + @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + end + + it "says the service is enabled" do + @provider.service_currently_enabled?(@provider.get_priority).should be_true + end + + it "stores the 'enabled' state" do + Chef::Resource::Service.stub!(:new).and_return(@current_resource) + @provider.load_current_resource.should equal(@current_resource) + @current_resource.enabled.should be_true + end + + it "stores the start/stop priorities of the service" do + @provider.load_current_resource + expected_priorities = {"6"=>[:stop, "20"], + "0"=>[:stop, "20"], + "1"=>[:stop, "20"], + "2"=>[:start, "20"], + "3"=>[:start, "20"], + "4"=>[:start, "20"], + "5"=>[:start, "20"]} + @provider.current_resource.priority.should == expected_priorities + end + end + + context "when update-rc.d shows init isn't linked to rc*.d/" do + before do + @provider.stub!(:assert_update_rcd_available) + @stdout = StringIO.new(streams["not linked"]["stdout"]) + @stderr = StringIO.new(streams["not linked"]["stderr"]) + @status = mock("Status", :exitstatus => 0, :stdout => @stdout) + @provider.stub!(:shell_out!).and_return(@status) + @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + end + + it "says the service is disabled" do + @provider.service_currently_enabled?(@provider.get_priority).should be_false + end + + it "stores the 'disabled' state" do + Chef::Resource::Service.stub!(:new).and_return(@current_resource) + @provider.load_current_resource.should equal(@current_resource) + @current_resource.enabled.should be_false + end + end + end end + end - describe "when update-rc.d fails" do - before do - @status = mock("Status", :exitstatus => -1) - @provider.stub!(:popen4).and_return(@status) + describe "action_enable" do + shared_examples_for "the service is up to date" do + it "does not enable the service" do + @provider.should_not_receive(:enable_service) + @provider.action_enable + @provider.set_updated_status + @provider.new_resource.should_not be_updated + end end - it "raises an error" do - @provider.define_resource_requirements - lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service) + shared_examples_for "the service is not up to date" do + it "enables the service and sets the resource as updated" do + @provider.should_receive(:enable_service).and_return(true) + @provider.action_enable + @provider.set_updated_status + @provider.new_resource.should be_updated + end end - end - describe "when enabling a service without priority" do - it "should call update-rc.d 'service_name' defaults" do - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"}) - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} defaults"}) - @provider.enable_service() + context "when the service is disabled" do + before do + @current_resource.enabled(false) + end + + it_behaves_like "the service is not up to date" end - end - describe "when enabling a service with simple priority" do - before do - @new_resource.priority(75) + context "when the service is enabled" do + before do + @current_resource.enabled(true) + end + + context "and the service sets no priority" do + it_behaves_like "the service is up to date" + end + + context "and the service requests the same priority as is set" do + before do + @current_resource.priority(80) + @new_resource.priority(80) + end + it_behaves_like "the service is up to date" + end + + context "and the service requests a different priority than is set" do + before do + @current_resource.priority(20) + @new_resource.priority(80) + end + it_behaves_like "the service is not up to date" + end end + end - it "should call update-rc.d 'service_name' defaults" do - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"}) - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} defaults 75 25"}) - @provider.enable_service() + def expect_commands(provider, commands) + commands.each do |command| + provider.should_receive(:run_command).with({:command => command}) end end - describe "when enabling a service with complex priorities" do - before do - @new_resource.priority(2 => [:start, 20], 3 => [:stop, 55]) + describe "enable_service" do + let(:service_name) { @new_resource.service_name } + context "when the service doesn't set a priority" do + it "calls update-rc.d 'service_name' defaults" do + expect_commands(@provider, [ + "/usr/sbin/update-rc.d -f #{service_name} remove", + "/usr/sbin/update-rc.d #{service_name} defaults" + ]) + @provider.enable_service + end end - it "should call update-rc.d 'service_name' defaults" do - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"}) - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} start 20 2 . stop 55 3 . "}) - @provider.enable_service() + context "when the service sets a simple priority" do + before do + @new_resource.priority(75) + end + + it "calls update-rc.d 'service_name' defaults" do + expect_commands(@provider, [ + "/usr/sbin/update-rc.d -f #{service_name} remove", + "/usr/sbin/update-rc.d #{service_name} defaults 75 25" + ]) + @provider.enable_service + end end - end - describe "when disabling a service without a priority" do + context "when the service sets complex priorities" do + before do + @new_resource.priority(2 => [:start, 20], 3 => [:stop, 55]) + end - it "should call update-rc.d -f 'service_name' remove + stop with a default priority" do - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"}) - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop 80 2 3 4 5 ."}) - @provider.disable_service() + it "calls update-rc.d 'service_name' with those priorities" do + expect_commands(@provider, [ + "/usr/sbin/update-rc.d -f #{service_name} remove", + "/usr/sbin/update-rc.d #{service_name} start 20 2 . stop 55 3 . " + ]) + @provider.enable_service + end end end - describe "when disabling a service with simple priority" do - before do - @new_resource.priority(75) + describe "disable_service" do + let(:service_name) { @new_resource.service_name } + context "when the service doesn't set a priority" do + it "calls update-rc.d -f 'service_name' remove + stop with default priority" do + expect_commands(@provider, [ + "/usr/sbin/update-rc.d -f #{service_name} remove", + "/usr/sbin/update-rc.d -f #{service_name} stop 80 2 3 4 5 ." + ]) + @provider.disable_service + end end - it "should call update-rc.d -f 'service_name' remove + stop with a specified priority" do - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"}) - @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop #{100 - @new_resource.priority} 2 3 4 5 ."}) - @provider.disable_service() + context "when the service sets a simple priority" do + before do + @new_resource.priority(75) + end + + it "calls update-rc.d -f 'service_name' remove + stop with the specified priority" do + expect_commands(@provider, [ + "/usr/sbin/update-rc.d -f #{service_name} remove", + "/usr/sbin/update-rc.d -f #{service_name} stop #{100 - @new_resource.priority} 2 3 4 5 ." + ]) + @provider.disable_service + end end end end diff --git a/spec/unit/provider/service/freebsd_service_spec.rb b/spec/unit/provider/service/freebsd_service_spec.rb index 6dd06bde2c..7861764309 100644 --- a/spec/unit/provider/service/freebsd_service_spec.rb +++ b/spec/unit/provider/service/freebsd_service_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -88,7 +88,7 @@ RC_SAMPLE @provider.load_current_resource end - it "should set running to true if the the status command returns 0" do + it "should set running to true if the status command returns 0" do @provider.should_receive(:shell_out).with("/usr/local/etc/rc.d/#{@current_resource.service_name} status").and_return(@status) @current_resource.should_receive(:running).with(true) @provider.load_current_resource @@ -125,7 +125,7 @@ RC_SAMPLE @provider.define_resource_requirements lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service) end - + describe "when executing assertions" do it "should verify that /etc/rc.conf exists" do ::File.should_receive(:exists?).with("/etc/rc.conf") @@ -138,7 +138,7 @@ RC_SAMPLE it "should raise an exception when the action is #{action}" do ::File.stub!(:exists?).and_return(false) @provider.load_current_resource - @provider.define_resource_requirements + @provider.define_resource_requirements @provider.instance_variable_get("@rcd_script_found").should be_false @provider.action = action lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service) @@ -157,7 +157,7 @@ RC_SAMPLE ::File.should_receive(:exists?).with("/etc/rc.conf").and_return false @provider.load_current_resource @provider.instance_variable_get("@enabled_state_found").should be_false - end + end it "update state when current resource enabled state could be determined" do ::File.stub!(:exist?).with("/usr/local/etc/rc.d/#{@new_resource.service_name}").and_return(true) @@ -165,10 +165,10 @@ RC_SAMPLE @provider.load_current_resource @provider.instance_variable_get("@enabled_state_found").should be_false @provider.instance_variable_get("@rcd_script_found").should be_true - @provider.define_resource_requirements + @provider.define_resource_requirements lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service, "Could not find the service name in /usr/local/etc/rc.d/#{@current_resource.service_name} and rcvar") - end + end it "should throw an exception if service line is missing from rc.d script" do pending "not implemented" do @@ -197,7 +197,7 @@ RC_SAMPLE it "should set running to true if the regex matches the output" do @stdout.stub!(:each_line).and_yield("555 ?? Ss 0:05.16 /usr/sbin/cron -s"). and_yield(" 9881 ?? Ss 0:06.67 /usr/local/sbin/httpd -DNOHTTPACCEPT") - @provider.load_current_resource + @provider.load_current_resource @current_resource.running.should be_true end diff --git a/spec/unit/provider/service/gentoo_service_spec.rb b/spec/unit/provider/service/gentoo_service_spec.rb index 8d4ada043b..b658cab4d8 100644 --- a/spec/unit/provider/service/gentoo_service_spec.rb +++ b/spec/unit/provider/service/gentoo_service_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -24,10 +24,10 @@ describe Chef::Provider::Service::Gentoo do @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) - + @new_resource = Chef::Resource::Service.new("chef") @current_resource = Chef::Resource::Service.new("chef") - + @provider = Chef::Provider::Service::Gentoo.new(@new_resource, @run_context) Chef::Resource::Service.stub!(:new).and_return(@current_resource) @status = mock("Status", :exitstatus => 0, :stdout => @stdout) @@ -39,7 +39,7 @@ describe Chef::Provider::Service::Gentoo do end # new test: found_enabled state # - describe "load_current_resource" do + describe "load_current_resource" do it "should raise Chef::Exceptions::Service if /sbin/rc-update does not exist" do File.should_receive(:exists?).with("/sbin/rc-update").and_return(false) @provider.define_resource_requirements @@ -79,7 +79,7 @@ describe Chef::Provider::Service::Gentoo do File.stub!(:exists?).with("/etc/runlevels/default/chef").and_return(true) File.stub!(:readable?).with("/etc/runlevels/default/chef").and_return(false) end - + it "should set enabled to false" do @provider.load_current_resource @current_resource.enabled.should be_false @@ -101,10 +101,10 @@ describe Chef::Provider::Service::Gentoo do end end - + it "should return the current_resource" do @provider.load_current_resource.should == @current_resource - end + end it "should support the status command automatically" do @provider.load_current_resource @@ -122,7 +122,7 @@ describe Chef::Provider::Service::Gentoo do end end - + describe "action_methods" do before(:each) { @provider.stub!(:load_current_resource).and_return(@current_resource) } diff --git a/spec/unit/provider/service/init_service_spec.rb b/spec/unit/provider/service/init_service_spec.rb index 650fca8320..c7d47e6281 100644 --- a/spec/unit/provider/service/init_service_spec.rb +++ b/spec/unit/provider/service/init_service_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -40,7 +40,7 @@ PS @status = mock("Status", :exitstatus => 0, :stdout => @stdout) @provider.stub!(:shell_out!).and_return(@status) end - + it "should create a current resource with the name of the new resource" do @provider.load_current_resource @provider.current_resource.should equal(@current_resource) @@ -60,8 +60,8 @@ PS @provider.should_receive(:shell_out).with("/etc/init.d/#{@current_resource.service_name} status").and_return(@status) @provider.load_current_resource end - - it "should set running to true if the the status command returns 0" do + + it "should set running to true if the status command returns 0" do @provider.stub!(:shell_out).with("/etc/init.d/#{@current_resource.service_name} status").and_return(@status) @provider.load_current_resource @current_resource.running.should be_true @@ -90,9 +90,9 @@ PS @provider.should_receive(:shell_out).with("/etc/init.d/chefhasmonkeypants status").and_return(@status) @provider.load_current_resource end - + end - + describe "when an init command has been specified" do before do @new_resource.stub!(:init_command).and_return("/opt/chef-server/service/erchef") @@ -107,7 +107,7 @@ PS end describe "when the node has not specified a ps command" do - + it "should raise an error if the node has a nil ps attribute" do @node.automatic_attrs[:command] = {:ps => nil} @provider.load_current_resource @@ -123,7 +123,7 @@ PS @provider.define_resource_requirements lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service) end - + end @@ -139,7 +139,7 @@ aj 7842 5057 0 21:26 pts/2 00:00:06 chef aj 7842 5057 0 21:26 pts/2 00:00:06 poos RUNNING_PS @status.stub!(:stdout).and_return(@stdout) - @provider.load_current_resource + @provider.load_current_resource @current_resource.running.should be_true end @@ -172,7 +172,7 @@ RUNNING_PS it "should call '/etc/init.d/service_name start' if no start command is specified" do @provider.should_receive(:shell_out!).with("/etc/init.d/#{@new_resource.service_name} start") @provider.start_service() - end + end end describe Chef::Provider::Service::Init, "stop_service" do diff --git a/spec/unit/provider/service/insserv_service_spec.rb b/spec/unit/provider/service/insserv_service_spec.rb index c823d511b5..8b5f09e78c 100644 --- a/spec/unit/provider/service/insserv_service_spec.rb +++ b/spec/unit/provider/service/insserv_service_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -35,7 +35,7 @@ describe Chef::Provider::Service::Insserv do describe "load_current_resource" do describe "when startup links exist" do - before do + before do Dir.stub!(:glob).with("/etc/rc**/S*initgrediant").and_return(["/etc/rc5.d/S18initgrediant", "/etc/rc2.d/S18initgrediant", "/etc/rc4.d/S18initgrediant", "/etc/rc3.d/S18initgrediant"]) end @@ -46,7 +46,7 @@ describe Chef::Provider::Service::Insserv do end describe "when startup links do not exist" do - before do + before do Dir.stub!(:glob).with("/etc/rc**/S*initgrediant").and_return([]) end @@ -65,7 +65,7 @@ describe Chef::Provider::Service::Insserv do @provider.enable_service end end - + describe "disable_service" do it "should call insserv and remove the links" do @provider.should_receive(:run_command).with({:command=>"/sbin/insserv -r -f #{@new_resource.service_name}"}) diff --git a/spec/unit/provider/service/invokercd_service_spec.rb b/spec/unit/provider/service/invokercd_service_spec.rb index ace2ad24e3..ca20657405 100644 --- a/spec/unit/provider/service/invokercd_service_spec.rb +++ b/spec/unit/provider/service/invokercd_service_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -40,7 +40,7 @@ PS @status = mock("Status", :exitstatus => 0, :stdout => @stdout) @provider.stub!(:shell_out!).and_return(@status) end - + it "should create a current resource with the name of the new resource" do @provider.load_current_resource @provider.current_resource.should equal(@current_resource) @@ -60,8 +60,8 @@ PS @provider.should_receive(:shell_out).with("/usr/sbin/invoke-rc.d #{@current_resource.service_name} status").and_return(@status) @provider.load_current_resource end - - it "should set running to true if the the status command returns 0" do + + it "should set running to true if the status command returns 0" do @provider.stub!(:shell_out).with("/usr/sbin/invoke-rc.d #{@current_resource.service_name} status").and_return(@status) @provider.load_current_resource @current_resource.running.should be_true @@ -90,9 +90,9 @@ PS @provider.should_receive(:shell_out).with("/usr/sbin/invoke-rc.d chefhasmonkeypants status").and_return(@status) @provider.load_current_resource end - + end - + describe "when the node has not specified a ps command" do it "should raise error if the node has a nil ps attribute and no other means to get status" do @node.automatic_attrs[:command] = {:ps => nil} @@ -107,7 +107,7 @@ PS @provider.define_resource_requirements lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service) end - + end @@ -125,7 +125,7 @@ aj 7842 5057 0 21:26 pts/2 00:00:06 poos RUNNING_PS @status = mock("Status", :exitstatus => 0, :stdout => @stdout) @provider.should_receive(:shell_out!).and_return(@status) - @provider.load_current_resource + @provider.load_current_resource @current_resource.running.should be_true end @@ -159,7 +159,7 @@ RUNNING_PS it "should call '/usr/sbin/invoke-rc.d service_name start' if no start command is specified" do @provider.should_receive(:shell_out!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} start") @provider.start_service() - end + end end describe Chef::Provider::Service::Invokercd, "stop_service" do diff --git a/spec/unit/provider/service/redhat_spec.rb b/spec/unit/provider/service/redhat_spec.rb index dd874a4f05..3ce4301026 100644 --- a/spec/unit/provider/service/redhat_spec.rb +++ b/spec/unit/provider/service/redhat_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -47,7 +47,7 @@ describe "Chef::Provider::Service::Redhat" do @node.automatic_attrs[:command] = {:ps => 'foo'} @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) - + @new_resource = Chef::Resource::Service.new("chef") @current_resource = Chef::Resource::Service.new("chef") @@ -73,7 +73,7 @@ describe "Chef::Provider::Service::Redhat" do @provider.load_current_resource @current_resource.enabled.should be_true end - + it "sets the current enabled status to false if the regex does not match" do status = mock("Status", :exitstatus => 0, :stdout => "" , :stderr => "") @provider.should_receive(:shell_out).with("/sbin/service chef status").and_return(status) @@ -84,10 +84,10 @@ describe "Chef::Provider::Service::Redhat" do @current_resource.enabled.should be_false end end - + describe "define resource requirements" do it_should_behave_like "define_resource_requirements_common" - + context "when the service does not exist" do before do status = mock("Status", :exitstatus => 1, :stdout => "", :stderr => "chef: unrecognized service") diff --git a/spec/unit/provider/service/simple_service_spec.rb b/spec/unit/provider/service/simple_service_spec.rb index cc0173e246..73cb3766d2 100644 --- a/spec/unit/provider/service/simple_service_spec.rb +++ b/spec/unit/provider/service/simple_service_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -39,7 +39,7 @@ NOMOCKINGSTRINGSPLZ @status = mock("Status", :exitstatus => 0, :stdout => @stdout) @provider.stub!(:shell_out!).and_return(@status) end - + it "should create a current resource with the name of the new resource" do Chef::Resource::Service.should_receive(:new).and_return(@current_resource) @provider.load_current_resource @@ -81,7 +81,7 @@ aj 7842 5057 0 21:26 pts/2 00:00:06 poos NOMOCKINGSTRINGSPLZ @status = mock("Status", :exitstatus => 0, :stdout => @stdout) @provider.stub!(:shell_out!).and_return(@status) - @provider.load_current_resource + @provider.load_current_resource @current_resource.running.should be_true end @@ -117,7 +117,7 @@ NOMOCKINGSTRINGSPLZ @provider.define_resource_requirements @provider.action = :start lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service) - end + end end describe "when stopping a service" do @@ -144,7 +144,7 @@ NOMOCKINGSTRINGSPLZ it "should raise an exception if the resource doesn't support restart, no restart command is provided, and no stop command is provided" do @provider.define_resource_requirements @provider.action = :restart - lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service) + lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service) end it "should just call stop, then start when the resource doesn't support restart and no restart_command is specified" do diff --git a/spec/unit/provider/service/solaris_smf_service_spec.rb b/spec/unit/provider/service/solaris_smf_service_spec.rb index 5cda6ddb77..64afee078c 100644 --- a/spec/unit/provider/service/solaris_smf_service_spec.rb +++ b/spec/unit/provider/service/solaris_smf_service_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -44,7 +44,7 @@ describe Chef::Provider::Service::Solaris do it "should raise an error if /bin/svcs does not exist" do File.should_receive(:exists?).with("/bin/svcs").and_return(false) lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Service) - end + end describe "on a host with /bin/svcs" do @@ -63,7 +63,7 @@ describe Chef::Provider::Service::Solaris do it "should return the current resource" do @provider.stub!(:popen4).with("/bin/svcs -l chef").and_return(@status) @provider.load_current_resource.should eql(@current_resource) - end + end it "should popen4 '/bin/svcs -l service_name'" do @provider.should_receive(:popen4).with("/bin/svcs -l chef").and_return(@status) diff --git a/spec/unit/provider/service/systemd_service_spec.rb b/spec/unit/provider/service/systemd_service_spec.rb index bca28a2d92..a107888b0b 100644 --- a/spec/unit/provider/service/systemd_service_spec.rb +++ b/spec/unit/provider/service/systemd_service_spec.rb @@ -79,19 +79,19 @@ describe Chef::Provider::Service::Systemd do @provider.load_current_resource @provider.instance_variable_get("@status_check_success").should be_true end - + it "should set running to false if it catches a Chef::Exceptions::Exec when using a status command" do @provider.stub!(:run_command_with_systems_locale).and_raise(Chef::Exceptions::Exec) @current_resource.should_receive(:running).with(false) @provider.load_current_resource end - + it "should update state to indicate status check failed when an exception is thrown using a status command" do @provider.stub!(:run_command_with_systems_locale).and_raise(Chef::Exceptions::Exec) @provider.load_current_resource @provider.instance_variable_get("@status_check_success").should be_false end - end + end it "should check if the service is enabled" do @provider.should_receive(:is_enabled?) diff --git a/spec/unit/provider/service/upstart_service_spec.rb b/spec/unit/provider/service/upstart_service_spec.rb index 4604d1b697..8628a4eaf7 100644 --- a/spec/unit/provider/service/upstart_service_spec.rb +++ b/spec/unit/provider/service/upstart_service_spec.rb @@ -73,7 +73,7 @@ describe Chef::Provider::Service::Upstart do @stdout = StringIO.new @stderr = StringIO.new @pid = mock("PID") - + ::File.stub!(:exists?).and_return(true) ::File.stub!(:open).and_return(true) end @@ -97,7 +97,7 @@ describe Chef::Provider::Service::Upstart do before do end - it "should set running to true if the the status command returns 0" do + it "should set running to true if the status command returns 0" do @stdout = StringIO.new("rsyslog start/running") @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) @provider.load_current_resource @@ -113,7 +113,7 @@ describe Chef::Provider::Service::Upstart do end describe "when the status command uses the old format" do - it "should set running to true if the the status command returns 0" do + it "should set running to true if the status command returns 0" do @stdout = StringIO.new("rsyslog (start) running, process 32225") @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) @provider.load_current_resource @@ -172,7 +172,7 @@ describe Chef::Provider::Service::Upstart do @provider.load_current_resource end - it "should track state when the user-provided status command fails" do + it "should track state when the user-provided status command fails" do @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_raise(Chef::Exceptions::Exec) @provider.load_current_resource @provider.instance_variable_get("@command_success").should == false @@ -190,7 +190,7 @@ describe Chef::Provider::Service::Upstart do @provider.load_current_resource @provider.instance_variable_get("@command_success").should == false end - + it "should return the current resource" do @provider.load_current_resource.should eql(@current_resource) end diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb index a68e798d36..7ec4ccf96a 100644 --- a/spec/unit/provider/service/windows_spec.rb +++ b/spec/unit/provider/service/windows_spec.rb @@ -95,7 +95,7 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do end describe Chef::Provider::Service::Windows, "stop_service" do - + before(:each) do Win32::Service.stub!(:status).with(@new_resource.service_name).and_return( mock("StatusStruct", :current_state => "running"), @@ -143,9 +143,9 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do it "should stop then start the service if it is running" do Win32::Service.stub!(:status).with(@new_resource.service_name).and_return( - mock("StatusStruct", :current_state => "running"), - mock("StatusStruct", :current_state => "stopped"), - mock("StatusStruct", :current_state => "stopped"), + mock("StatusStruct", :current_state => "running"), + mock("StatusStruct", :current_state => "stopped"), + mock("StatusStruct", :current_state => "stopped"), mock("StatusStruct", :current_state => "running")) Win32::Service.should_receive(:stop).with(@new_resource.service_name) Win32::Service.should_receive(:start).with(@new_resource.service_name) @@ -155,8 +155,8 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do it "should just start the service if it is stopped" do Win32::Service.stub!(:status).with(@new_resource.service_name).and_return( - mock("StatusStruct", :current_state => "stopped"), - mock("StatusStruct", :current_state => "stopped"), + mock("StatusStruct", :current_state => "stopped"), + mock("StatusStruct", :current_state => "stopped"), mock("StatusStruct", :current_state => "running")) Win32::Service.should_receive(:start).with(@new_resource.service_name) @provider.restart_service @@ -201,7 +201,7 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do @new_resource.updated_by_last_action?.should be_false end end - + describe Chef::Provider::Service::Windows, "disable_service" do before(:each) do diff --git a/spec/unit/provider/subversion_spec.rb b/spec/unit/provider/subversion_spec.rb index 81e5860225..dd020d4597 100644 --- a/spec/unit/provider/subversion_spec.rb +++ b/spec/unit/provider/subversion_spec.rb @@ -247,7 +247,7 @@ describe Chef::Provider::Subversion do ::File.stub!(:directory?).with("/my/deploy").and_return(true) ::File.should_receive(:exist?).with("/my/deploy/dir/.svn").twice.and_return(false) @provider.should_receive(:action_checkout) - @provider.run_action(:sync) + @provider.run_action(:sync) end it "runs the sync_command on action_sync if the deploy dir exists and isn't empty" do diff --git a/spec/unit/provider/user/dscl_spec.rb b/spec/unit/provider/user/dscl_spec.rb index 3894cd61b4..dd98c55bd1 100644 --- a/spec/unit/provider/user/dscl_spec.rb +++ b/spec/unit/provider/user/dscl_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -29,7 +29,7 @@ describe Chef::Provider::User::Dscl do @new_resource = Chef::Resource::User.new("toor") @provider = Chef::Provider::User::Dscl.new(@new_resource, @run_context) end - + describe "when shelling out to dscl" do it "should run dscl with the supplied cmd /Path args" do shell_return = ShellCmdResult.new('stdout', 'err', 0) @@ -66,7 +66,7 @@ describe Chef::Provider::User::Dscl do before do @provider.stub!(:safe_dscl).and_return("\nwheel 200\nstaff 201\n") end - + it "should run safe_dscl with list /Users uid" do @provider.should_receive(:safe_dscl).with("list /Users uid") @provider.get_free_uid @@ -75,7 +75,7 @@ describe Chef::Provider::User::Dscl do it "should return the first unused uid number on or above 200" do @provider.get_free_uid.should == 202 end - + it "should raise an exception when the search limit is exhausted" do search_limit = 1 lambda { @provider.get_free_uid(search_limit) }.should raise_error(RuntimeError) @@ -91,7 +91,7 @@ describe Chef::Provider::User::Dscl do @provider.should_receive(:safe_dscl).with("list /Users uid") @provider.uid_used?(500) end - + it "should return true for a used uid number" do @provider.uid_used?(500).should be_true end @@ -111,7 +111,7 @@ describe Chef::Provider::User::Dscl do @provider.should_receive(:get_free_uid).and_return(501) lambda { @provider.set_uid }.should raise_error(Chef::Exceptions::RequestedUIDUnavailable) end - + it "finds a valid, unused uid when none is specified" do @provider.should_receive(:safe_dscl).with("list /Users uid").and_return('') @provider.should_receive(:safe_dscl).with("create /Users/toor UniqueID 501") @@ -119,7 +119,7 @@ describe Chef::Provider::User::Dscl do @provider.set_uid @new_resource.uid.should == 501 end - + it "sets the uid specified in the resource" do @new_resource.uid(1000) @provider.should_receive(:safe_dscl).with("create /Users/toor UniqueID 1000").and_return(true) @@ -132,7 +132,7 @@ describe Chef::Provider::User::Dscl do before do @new_resource.supports({ :manage_home => true }) @new_resource.home('/Users/toor') - + @current_resource = @new_resource.dup @provider.current_resource = @current_resource end @@ -142,7 +142,7 @@ describe Chef::Provider::User::Dscl do @provider.should_receive(:safe_dscl).with("delete /Users/toor NFSHomeDirectory").and_return(true) @provider.modify_home end - + it "raises InvalidHomeDirectory when the resource's home directory doesn't look right" do @new_resource.home('epic-fail') @@ -151,20 +151,20 @@ describe Chef::Provider::User::Dscl do it "moves the users home to the new location if it exists and the target location is different" do @new_resource.supports(:manage_home => true) - + current_home = CHEF_SPEC_DATA + '/old_home_dir' current_home_files = [current_home + '/my-dot-emacs', current_home + '/my-dot-vim'] @current_resource.home(current_home) @new_resource.gid(23) ::File.stub!(:exists?).with('/old/home/toor').and_return(true) ::File.stub!(:exists?).with('/Users/toor').and_return(true) - + FileUtils.should_receive(:mkdir_p).with('/Users/toor').and_return(true) FileUtils.should_receive(:rmdir).with(current_home) ::Dir.should_receive(:glob).with("#{CHEF_SPEC_DATA}/old_home_dir/*",::File::FNM_DOTMATCH).and_return(current_home_files) FileUtils.should_receive(:mv).with(current_home_files, "/Users/toor", :force => true) FileUtils.should_receive(:chown_R).with('toor','23','/Users/toor') - + @provider.should_receive(:safe_dscl).with("create /Users/toor NFSHomeDirectory '/Users/toor'") @provider.modify_home end @@ -251,7 +251,7 @@ describe Chef::Provider::User::Dscl do before do @new_resource.password("F"*48) end - + it "should write a shadow hash file with the expected salted sha1" do uuid = "B398449E-CEE0-45E0-80F8-B0B5B1BFDEAA" File.should_receive(:open).with('/var/db/shadow/hash/B398449E-CEE0-45E0-80F8-B0B5B1BFDEAA', "w", 384).and_yield(@output) @@ -262,7 +262,7 @@ describe Chef::Provider::User::Dscl do expected_shadow_hash[168] = expected_salted_sha1 @provider.modify_password @output.string.strip.should == expected_shadow_hash - end + end end describe "when given a shadow hash file for the password" do @@ -292,7 +292,7 @@ describe Chef::Provider::User::Dscl do @provider.should_receive(:safe_dscl).with("read /Users/toor").and_return("\nAuthenticationAuthority: ;ShadowHash;\n") @provider.modify_password @output.string.strip.should match(/^0{168}(FFFFFFFF1C1AA7935D4E1190AFEC92343F31F7671FBF126D)0{1071}$/) - end + end end it "should write the output directly to the shadow hash file at /var/db/shadow/hash/GUID" do @@ -392,7 +392,7 @@ describe Chef::Provider::User::Dscl do before do @current_resource = @new_resource.dup @provider.current_resource = @current_resource - + # These are all different from @current_resource @new_resource.username "mud" @new_resource.uid 2342 @@ -400,7 +400,7 @@ describe Chef::Provider::User::Dscl do @new_resource.home '/Users/death' @new_resource.password 'goaway' end - + it "sets the user, comment field, uid, gid, moves the home directory, sets the shell, and sets the password" do @provider.should_receive :dscl_create_user @provider.should_receive :dscl_create_comment @@ -417,11 +417,11 @@ describe Chef::Provider::User::Dscl do before do @current_resource = @new_resource.dup @provider.current_resource = @current_resource - + # This is different from @current_resource @new_resource.gid 2342 end - + it "sets the gid" do @provider.should_receive :dscl_set_gid @provider.manage_user @@ -436,7 +436,7 @@ describe Chef::Provider::User::Dscl do FileUtils.should_receive(:rm_rf).with("/Users/fuuuuuuuuuuuuu") @provider.remove_user end - + it "removes the user from any group memberships" do Etc.stub(:group).and_yield(OpenStruct.new(:name => 'ragefisters', :mem => 'toor')) @provider.should_receive(:safe_dscl).with("delete /Users/toor") diff --git a/spec/unit/provider/user/pw_spec.rb b/spec/unit/provider/user/pw_spec.rb index b7503ea15f..ea5bcfe740 100644 --- a/spec/unit/provider/user/pw_spec.rb +++ b/spec/unit/provider/user/pw_spec.rb @@ -23,7 +23,7 @@ describe Chef::Provider::User::Pw do @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) - + @new_resource = Chef::Resource::User.new("adam") @new_resource.comment "Adam Jacob" @new_resource.uid 1000 @@ -31,7 +31,7 @@ describe Chef::Provider::User::Pw do @new_resource.home "/home/adam" @new_resource.shell "/usr/bin/zsh" @new_resource.password "abracadabra" - + @new_resource.supports :manage_home => true @current_resource = Chef::Resource::User.new("adam") diff --git a/spec/unit/provider/user/windows_spec.rb b/spec/unit/provider/user/windows_spec.rb index 6ede11b28c..b11eeaebe5 100644 --- a/spec/unit/provider/user/windows_spec.rb +++ b/spec/unit/provider/user/windows_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -41,7 +41,7 @@ describe Chef::Provider::User::Windows do @provider = Chef::Provider::User::Windows.new(@new_resource, @run_context) @provider.current_resource = @current_resource end - + describe "when comparing the user's current attributes to the desired attributes" do before do @new_resource.comment "Adam Jacob" @@ -79,7 +79,7 @@ describe Chef::Provider::User::Windows do end end - + describe "and the attributes do not match" do before do @current_resource = Chef::Resource::User.new("adam") @@ -130,7 +130,7 @@ describe Chef::Provider::User::Windows do before(:each) do @provider.stub!(:set_options).and_return(:name=> "monkey") end - + it "should call @net_user.update with the return of set_options" do @net_user.should_receive(:update).with(:name=> "monkey") @provider.manage_user diff --git a/spec/unit/provider/user_spec.rb b/spec/unit/provider/user_spec.rb index 9c4e2847f7..d054fcc440 100644 --- a/spec/unit/provider/user_spec.rb +++ b/spec/unit/provider/user_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -58,7 +58,7 @@ describe Chef::Provider::User do describe "executing load_current_resource" do before(:each) do @node = Chef::Node.new - #@new_resource = mock("Chef::Resource::User", + #@new_resource = mock("Chef::Resource::User", # :null_object => true, # :username => "adam", # :comment => "Adam Jacob", @@ -152,17 +152,17 @@ describe Chef::Provider::User do @new_resource.password "some new password" Etc.stub!(:getpwnam).and_return(user) end - + unless shadow_lib_unavail? context "and we have the ruby-shadow gem" do - pending "and we are not root (rerun this again as root)", :requires_unprivileged_user => true - + pending "and we are not root (rerun this again as root)", :requires_unprivileged_user => true + context "and we are root", :requires_root => true do it "should pass assertions when ruby-shadow can be loaded" do @provider.action = 'create' original_method = @provider.method(:require) @provider.should_receive(:require) { |*args| original_method.call(*args) } - passwd_info = Struct::PasswdEntry.new(:sp_namp => "adm ", :sp_pwdp => "$1$T0N0Q.lc$nyG6pFI3Dpqa5cxUz/57j0", :sp_lstchg => 14861, :sp_min => 0, :sp_max => 99999, + passwd_info = Struct::PasswdEntry.new(:sp_namp => "adm ", :sp_pwdp => "$1$T0N0Q.lc$nyG6pFI3Dpqa5cxUz/57j0", :sp_lstchg => 14861, :sp_min => 0, :sp_max => 99999, :sp_warn => 7, :sp_inact => -1, :sp_expire => -1, :sp_flag => -1) Shadow::Passwd.should_receive(:getspnam).with("adam").and_return(passwd_info) @provider.load_current_resource @@ -177,58 +177,50 @@ describe Chef::Provider::User do @provider.should_receive(:require).with("shadow") { raise LoadError } @provider.load_current_resource @provider.define_resource_requirements - lambda {@provider.process_resource_requirements}.should raise_error Chef::Exceptions::MissingLibrary + lambda {@provider.process_resource_requirements}.should raise_error Chef::Exceptions::MissingLibrary end end end describe "compare_user" do - before(:each) do - # @node = Chef::Node.new - # @new_resource = mock("Chef::Resource::User", - # :null_object => true, - # :username => "adam", - # :comment => "Adam Jacob", - # :uid => 1000, - # :gid => 1000, - # :home => "/home/adam", - # :shell => "/usr/bin/zsh", - # :password => nil, - # :updated => nil - # ) - # @current_resource = mock("Chef::Resource::User", - # :null_object => true, - # :username => "adam", - # :comment => "Adam Jacob", - # :uid => 1000, - # :gid => 1000, - # :home => "/home/adam", - # :shell => "/usr/bin/zsh", - # :password => nil, - # :updated => nil - # ) - # @provider = Chef::Provider::User.new(@node, @new_resource) - # @provider.current_resource = @current_resource - end + let(:mapping) { + { + 'username' => ["adam", "Adam"], + 'comment' => ["Adam Jacob", "adam jacob"], + 'uid' => [1000, 1001], + 'gid' => [1000, 1001], + 'home' => ["/home/adam", "/Users/adam"], + 'shell'=> ["/usr/bin/zsh", "/bin/bash"], + 'password'=> ["abcd","12345"] + } + } %w{uid gid comment home shell password}.each do |attribute| it "should return true if #{attribute} doesn't match" do - @new_resource.should_receive(attribute).exactly(2).times.and_return(true) - @current_resource.should_receive(attribute).once.and_return(false) + @new_resource.send(attribute, mapping[attribute][0]) + @current_resource.send(attribute, mapping[attribute][1]) @provider.compare_user.should eql(true) end end + %w{uid gid}.each do |attribute| + it "should return false if string #{attribute} matches fixnum" do + @new_resource.send(attribute, "100") + @current_resource.send(attribute, 100) + @provider.compare_user.should eql(false) + end + end + it "should return false if the objects are identical" do @provider.compare_user.should eql(false) - end + end end describe "action_create" do before(:each) do @provider.stub!(:load_current_resource) - # @current_resource = mock("Chef::Resource::User", + # @current_resource = mock("Chef::Resource::User", # :null_object => true, # :username => "adam", # :comment => "Adam Jacob", @@ -261,7 +253,7 @@ describe Chef::Provider::User do @provider.action_create end - it "should set the the new_resources updated flag when it creates the user if we call manage_user" do + it "should set the new_resources updated flag when it creates the user if we call manage_user" do @provider.user_exists = true @provider.stub!(:compare_user).and_return(true) @provider.stub!(:manage_user).and_return(true) @@ -278,7 +270,7 @@ describe Chef::Provider::User do it "should not call remove_user if the user does not exist" do @provider.user_exists = false - @provider.should_not_receive(:remove_user) + @provider.should_not_receive(:remove_user) @provider.action_remove end @@ -301,10 +293,10 @@ describe Chef::Provider::User do before(:each) do @provider.stub!(:load_current_resource) # @node = Chef::Node.new - # @new_resource = mock("Chef::Resource::User", + # @new_resource = mock("Chef::Resource::User", # :null_object => true # ) - # @current_resource = mock("Chef::Resource::User", + # @current_resource = mock("Chef::Resource::User", # :null_object => true # ) # @provider = Chef::Provider::User.new(@node, @new_resource) @@ -344,10 +336,10 @@ describe Chef::Provider::User do before(:each) do @provider.stub!(:load_current_resource) # @node = Chef::Node.new - # @new_resource = mock("Chef::Resource::User", + # @new_resource = mock("Chef::Resource::User", # :null_object => true # ) - # @current_resource = mock("Chef::Resource::User", + # @current_resource = mock("Chef::Resource::User", # :null_object => true # ) # @provider = Chef::Provider::User.new(@node, @new_resource) @@ -413,10 +405,10 @@ describe Chef::Provider::User do before(:each) do @provider.stub!(:load_current_resource) # @node = Chef::Node.new - # @new_resource = mock("Chef::Resource::User", + # @new_resource = mock("Chef::Resource::User", # :null_object => true # ) - # @current_resource = mock("Chef::Resource::User", + # @current_resource = mock("Chef::Resource::User", # :null_object => true # ) # @provider = Chef::Provider::User.new(@node, @new_resource) diff --git a/spec/unit/resource/apt_package_spec.rb b/spec/unit/resource/apt_package_spec.rb index 795ffc6fc4..58b007c327 100644 --- a/spec/unit/resource/apt_package_spec.rb +++ b/spec/unit/resource/apt_package_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,19 +19,19 @@ require 'spec_helper' describe Chef::Resource::AptPackage, "initialize" do - + before(:each) do @resource = Chef::Resource::AptPackage.new("foo") end - + it "should return a Chef::Resource::AptPackage" do @resource.should be_a_kind_of(Chef::Resource::AptPackage) end - + it "should set the resource_name to :apt_package" do @resource.resource_name.should eql(:apt_package) end - + it "should set the provider to Chef::Provider::Package::Apt" do @resource.provider.should eql(Chef::Provider::Package::Apt) end diff --git a/spec/unit/resource/bash_spec.rb b/spec/unit/resource/bash_spec.rb index c7f31e1de6..d729db6977 100644 --- a/spec/unit/resource/bash_spec.rb +++ b/spec/unit/resource/bash_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -22,17 +22,17 @@ describe Chef::Resource::Bash do before(:each) do @resource = Chef::Resource::Bash.new("fakey_fakerton") - end + end it "should create a new Chef::Resource::Bash" do @resource.should be_a_kind_of(Chef::Resource) @resource.should be_a_kind_of(Chef::Resource::Bash) end - + it "should have a resource name of :bash" do @resource.resource_name.should eql(:bash) end - + it "should have an interpreter of bash" do @resource.interpreter.should eql("bash") end diff --git a/spec/unit/resource/batch_spec.rb b/spec/unit/resource/batch_spec.rb index 91b840908e..b74c7d24a7 100644 --- a/spec/unit/resource/batch_spec.rb +++ b/spec/unit/resource/batch_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -27,22 +27,22 @@ describe Chef::Resource::Batch do 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 + 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" + it_should_behave_like "a Windows script resource" end - + end diff --git a/spec/unit/resource/breakpoint_spec.rb b/spec/unit/resource/breakpoint_spec.rb index 8eaabb546d..412211a038 100644 --- a/spec/unit/resource/breakpoint_spec.rb +++ b/spec/unit/resource/breakpoint_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,25 +19,25 @@ require 'spec_helper' describe Chef::Resource::Breakpoint do - + before do @breakpoint = Chef::Resource::Breakpoint.new end - + it "allows the action :break" do @breakpoint.allowed_actions.should include(:break) end - + it "defaults to the break action" do @breakpoint.action.should == "break" end - + it "names itself after the line number of the file where it's created" do @breakpoint.name.should match(/breakpoint_spec\.rb\:[\d]{2}\:in \`new\'$/) end - + it "uses the breakpoint provider" do @breakpoint.provider.should == Chef::Provider::Breakpoint end - + end diff --git a/spec/unit/resource/chef_gem_spec.rb b/spec/unit/resource/chef_gem_spec.rb index 54def9a49d..1d7ca8a81e 100644 --- a/spec/unit/resource/chef_gem_spec.rb +++ b/spec/unit/resource/chef_gem_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -20,19 +20,19 @@ require 'spec_helper' describe Chef::Resource::ChefGem, "initialize" do - + before(:each) do @resource = Chef::Resource::ChefGem.new("foo") end - + it "should return a Chef::Resource::ChefGem" do @resource.should be_a_kind_of(Chef::Resource::ChefGem) end - + it "should set the resource_name to :chef_gem" do @resource.resource_name.should eql(:chef_gem) end - + it "should set the provider to Chef::Provider::Package::Rubygems" do @resource.provider.should eql(Chef::Provider::Package::Rubygems) end diff --git a/spec/unit/resource/cookbook_file_spec.rb b/spec/unit/resource/cookbook_file_spec.rb index d0408c251a..6c55c8035a 100644 --- a/spec/unit/resource/cookbook_file_spec.rb +++ b/spec/unit/resource/cookbook_file_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -23,29 +23,29 @@ describe Chef::Resource::CookbookFile do before do @cookbook_file = Chef::Resource::CookbookFile.new('sourcecode_tarball.tgz') end - + it "uses the name parameter for the source parameter" do @cookbook_file.name.should == 'sourcecode_tarball.tgz' end - + it "has a source parameter" do @cookbook_file.name('config_file.conf') @cookbook_file.name.should == 'config_file.conf' end - + it "defaults to a nil cookbook parameter (current cookbook will be used)" do @cookbook_file.cookbook.should be_nil end - + it "has a cookbook parameter" do @cookbook_file.cookbook("munin") @cookbook_file.cookbook.should == 'munin' end - + it "sets the provider to Chef::Provider::CookbookFile" do @cookbook_file.provider.should == Chef::Provider::CookbookFile end - + describe "when it has a backup number, group, mode, owner, source, checksum, and cookbook on nix or path, rights, deny_rights, checksum on windows" do before do if Chef::Platform.windows? @@ -63,21 +63,21 @@ describe Chef::Resource::CookbookFile do @cookbook_file.checksum("1" * 64) end - + it "describes the state" do state = @cookbook_file.state if Chef::Platform.windows? puts state state[:rights].should == [{:permissions => :read, :principals => "Everyone"}] state[:deny_rights].should == [{:permissions => :full_control, :principals => "Clumsy_Sam"}] - else + else state[:group].should == "wheel" state[:mode].should == "0664" state[:owner].should == "root" end state[:checksum].should == "1" * 64 end - + it "returns the path as its identity" do if Chef::Platform.windows? @cookbook_file.identity.should == "C:/temp/origin/file.txt" diff --git a/spec/unit/resource/cron_spec.rb b/spec/unit/resource/cron_spec.rb index 403ffb009b..7f294fae11 100644 --- a/spec/unit/resource/cron_spec.rb +++ b/spec/unit/resource/cron_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -23,21 +23,21 @@ describe Chef::Resource::Cron do before(:each) do @resource = Chef::Resource::Cron.new("cronify") - end + end it "should create a new Chef::Resource::Cron" do @resource.should be_a_kind_of(Chef::Resource) @resource.should be_a_kind_of(Chef::Resource::Cron) end - + it "should have a name" do @resource.name.should eql("cronify") end - + it "should have a default action of 'create'" do @resource.action.should eql(:create) end - + it "should accept create or delete for action" do lambda { @resource.action :create }.should_not raise_error(ArgumentError) lambda { @resource.action :delete }.should_not raise_error(ArgumentError) @@ -63,7 +63,7 @@ describe Chef::Resource::Cron do @resource.hour "6" @resource.hour.should eql("6") end - + it "should allow you to specify the day" do @resource.day "10" @resource.day.should eql("10") @@ -110,7 +110,7 @@ describe Chef::Resource::Cron do @resource.send(x, "*").should eql("*") end end - + it "should allow ranges for all time and date values" do [ "minute", "hour", "day", "month", "weekday" ].each do |x| @resource.send(x, "1-2,5").should eql("1-2,5") @@ -130,31 +130,31 @@ describe Chef::Resource::Cron do it "should reject any minute over 59" do lambda { @resource.minute "60" }.should raise_error(RangeError) end - + it "should reject any hour over 23" do lambda { @resource.hour "24" }.should raise_error(RangeError) end - + it "should reject any day over 31" do lambda { @resource.day "32" }.should raise_error(RangeError) end - + it "should reject any month over 12" do lambda { @resource.month "13" }.should raise_error(RangeError) end - + it "should reject any weekday over 7" do lambda { @resource.weekday "8" }.should raise_error(RangeError) end - + it "should convert integer schedule values to a string" do [ "minute", "hour", "day", "month", "weekday" ].each do |x| @resource.send(x, 5).should eql("5") end end - + describe "when it has a time (minute, hour, day, month, weeekend) and user" do - before do + before do @resource.command("tackle") @resource.minute("1") @resource.hour("2") diff --git a/spec/unit/resource/csh_spec.rb b/spec/unit/resource/csh_spec.rb index 291c6ea745..e1534a8f5f 100644 --- a/spec/unit/resource/csh_spec.rb +++ b/spec/unit/resource/csh_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -22,17 +22,17 @@ describe Chef::Resource::Csh do before(:each) do @resource = Chef::Resource::Csh.new("fakey_fakerton") - end + end it "should create a new Chef::Resource::Csh" do @resource.should be_a_kind_of(Chef::Resource) @resource.should be_a_kind_of(Chef::Resource::Csh) end - + it "should have a resource name of :csh" do @resource.resource_name.should eql(:csh) end - + it "should have an interpreter of csh" do @resource.interpreter.should eql("csh") end diff --git a/spec/unit/resource/deploy_revision_spec.rb b/spec/unit/resource/deploy_revision_spec.rb index 671ba9a1f6..1f509992aa 100644 --- a/spec/unit/resource/deploy_revision_spec.rb +++ b/spec/unit/resource/deploy_revision_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,7 +19,7 @@ require 'spec_helper' describe Chef::Resource::DeployRevision do - + it "defaults to the revision deploy provider" do @resource = Chef::Resource::DeployRevision.new("deploy _this_!") @resource.provider.should == Chef::Provider::Deploy::Revision @@ -29,11 +29,11 @@ describe Chef::Resource::DeployRevision do @resource = Chef::Resource::DeployRevision.new("deploy _this_!") @resource.resource_name.should == :deploy_revision end - + end describe Chef::Resource::DeployBranch do - + it "defaults to the revision deploy provider" do @resource = Chef::Resource::DeployBranch.new("deploy _this_!") @resource.provider.should == Chef::Provider::Deploy::Revision @@ -43,5 +43,5 @@ describe Chef::Resource::DeployBranch do @resource = Chef::Resource::DeployBranch.new("deploy _this_!") @resource.resource_name.should == :deploy_branch end - + end diff --git a/spec/unit/resource/deploy_spec.rb b/spec/unit/resource/deploy_spec.rb index 98c9fa1581..7cc25ed41c 100644 --- a/spec/unit/resource/deploy_spec.rb +++ b/spec/unit/resource/deploy_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,7 +19,7 @@ require 'spec_helper' describe Chef::Resource::Deploy do - + class << self def resource_has_a_string_attribute(attr_name) it "has a String attribute for #{attr_name.to_s}" do @@ -28,7 +28,7 @@ describe Chef::Resource::Deploy do lambda {@resource.send(attr_name, 8675309)}.should raise_error(ArgumentError) end end - + def resource_has_a_boolean_attribute(attr_name, opts={:defaults_to=>false}) it "has a Boolean attribute for #{attr_name.to_s}" do @resource.send(attr_name).should eql(opts[:defaults_to]) @@ -36,7 +36,7 @@ describe Chef::Resource::Deploy do @resource.send(attr_name).should eql( !opts[:defaults_to] ) end end - + def resource_has_a_callback_attribute(attr_name) it "has a Callback attribute #{attr_name}" do callback_block = lambda { :noop } @@ -49,11 +49,11 @@ describe Chef::Resource::Deploy do end end end - + before do @resource = Chef::Resource::Deploy.new("/my/deploy/dir") end - + resource_has_a_string_attribute(:repo) resource_has_a_string_attribute(:deploy_to) resource_has_a_string_attribute(:role) @@ -70,15 +70,15 @@ describe Chef::Resource::Deploy do resource_has_a_string_attribute(:svn_password) resource_has_a_string_attribute(:svn_arguments) resource_has_a_string_attribute(:svn_info_args) - + resource_has_a_boolean_attribute(:migrate, :defaults_to=>false) resource_has_a_boolean_attribute(:enable_submodules, :defaults_to=>false) resource_has_a_boolean_attribute(:shallow_clone, :defaults_to=>false) - + it "uses the first argument as the deploy directory" do @resource.deploy_to.should eql("/my/deploy/dir") end - + # For git, any revision, branch, tag, whatever is resolved to a SHA1 ref. # For svn, the branch is included in the repo URL. # Therefore, revision and branch ARE NOT SEPARATE THINGS @@ -86,19 +86,19 @@ describe Chef::Resource::Deploy do @resource.branch "stable" @resource.revision.should eql("stable") end - + it "takes the SCM resource to use as a constant, and defaults to git" do @resource.scm_provider.should eql(Chef::Provider::Git) @resource.scm_provider Chef::Provider::Subversion @resource.scm_provider.should eql(Chef::Provider::Subversion) end - + it "allows scm providers to be set via symbol" do @resource.scm_provider.should == Chef::Provider::Git @resource.scm_provider :subversion @resource.scm_provider.should == Chef::Provider::Subversion end - + it "allows scm providers to be set via string" do @resource.scm_provider.should == Chef::Provider::Git @resource.scm_provider "subversion" @@ -111,105 +111,105 @@ describe Chef::Resource::Deploy do @resource.svn_force_export.should be_true lambda {@resource.svn_force_export(10053)}.should raise_error(ArgumentError) end - + it "takes arbitrary environment variables in a hash" do @resource.environment "RAILS_ENV" => "production" @resource.environment.should == {"RAILS_ENV" => "production"} end - + it "takes string arguments to environment for backwards compat, setting RAILS_ENV, RACK_ENV, and MERB_ENV" do @resource.environment "production" @resource.environment.should == {"RAILS_ENV"=>"production", "RACK_ENV"=>"production","MERB_ENV"=>"production"} end - + it "sets destination to $deploy_to/shared/$repository_cache" do @resource.destination.should eql("/my/deploy/dir/shared/cached-copy") end - + it "sets shared_path to $deploy_to/shared" do @resource.shared_path.should eql("/my/deploy/dir/shared") end - + it "sets current_path to $deploy_to/current" do @resource.current_path.should eql("/my/deploy/dir/current") end - + it "gets the current_path correct even if the shared_path is set (regression test)" do @resource.shared_path @resource.current_path.should eql("/my/deploy/dir/current") end - + it "gives #depth as 5 if shallow clone is true, nil otherwise" do @resource.depth.should be_nil @resource.shallow_clone true @resource.depth.should eql("5") end - + it "aliases repo as repository" do @resource.repository "git@github.com/opcode/cookbooks.git" @resource.repo.should eql("git@github.com/opcode/cookbooks.git") end - + it "aliases git_ssh_wrapper as ssh_wrapper" do @resource.ssh_wrapper "git_my_repo.sh" @resource.git_ssh_wrapper.should eql("git_my_repo.sh") end - + it "has an Array attribute purge_before_symlink, default: log, tmp/pids, public/system" do @resource.purge_before_symlink.should == %w{ log tmp/pids public/system } @resource.purge_before_symlink %w{foo bar baz} @resource.purge_before_symlink.should == %w{foo bar baz} end - + it "has an Array attribute create_dirs_before_symlink, default: tmp, public, config" do @resource.create_dirs_before_symlink.should == %w{tmp public config} @resource.create_dirs_before_symlink %w{foo bar baz} @resource.create_dirs_before_symlink.should == %w{foo bar baz} end - + it 'has a Hash attribute symlinks, default: {"system" => "public/system", "pids" => "tmp/pids", "log" => "log"}' do default = { "system" => "public/system", "pids" => "tmp/pids", "log" => "log"} @resource.symlinks.should == default @resource.symlinks "foo" => "bar/baz" @resource.symlinks.should == {"foo" => "bar/baz"} end - + it 'has a Hash attribute symlink_before_migrate, default "config/database.yml" => "config/database.yml"' do @resource.symlink_before_migrate.should == {"config/database.yml" => "config/database.yml"} @resource.symlink_before_migrate "wtf?" => "wtf is going on" @resource.symlink_before_migrate.should == {"wtf?" => "wtf is going on"} end - + resource_has_a_callback_attribute :before_migrate resource_has_a_callback_attribute :before_symlink resource_has_a_callback_attribute :before_restart resource_has_a_callback_attribute :after_restart - + it "aliases restart_command as restart" do @resource.restart "foobaz" @resource.restart_command.should == "foobaz" end - + it "takes a block for the restart parameter" do restart_like_this = lambda {p :noop} @resource.restart(&restart_like_this) @resource.restart.should == restart_like_this end - + it "defaults to using the Deploy::Timestamped provider" do @resource.provider.should == Chef::Provider::Deploy::Timestamped end - + it "allows providers to be set with a full class name" do @resource.provider Chef::Provider::Deploy::Timestamped @resource.provider.should == Chef::Provider::Deploy::Timestamped end - + it "allows deploy providers to be set via symbol" do @resource.provider :revision @resource.provider.should == Chef::Provider::Deploy::Revision end - + it "allows deploy providers to be set via string" do @resource.provider "revision" @resource.provider.should == Chef::Provider::Deploy::Revision @@ -229,9 +229,23 @@ describe Chef::Resource::Deploy do @resource.keep_releases.should == 1 end + describe "when it has a timeout attribute" do + let(:ten_seconds) { 10 } + before { @resource.timeout(ten_seconds) } + it "stores this timeout" do + @resource.timeout.should == ten_seconds + end + end + + describe "when it has no timeout attribute" do + it "should have no default timeout" do + @resource.timeout.should be_nil + end + end + describe "when it has meta application root, revision, user, group, scm provider, repository cache, environment, simlinks and migrate" do - before do + before do @resource.repository("http://uri.org") @resource.deploy_to("/") @resource.revision("1.2.3") @@ -242,7 +256,7 @@ describe Chef::Resource::Deploy do @resource.environment({"SUDO" => "TRUE"}) @resource.symlinks({"system" => "public/system"}) @resource.migrate(false) - + end it "describes its state" do @@ -255,5 +269,5 @@ describe Chef::Resource::Deploy do @resource.identity.should == "http://uri.org" end end - + end diff --git a/spec/unit/resource/directory_spec.rb b/spec/unit/resource/directory_spec.rb index 9b0c8242e6..dc042c5a77 100644 --- a/spec/unit/resource/directory_spec.rb +++ b/spec/unit/resource/directory_spec.rb @@ -61,7 +61,7 @@ describe Chef::Resource::Directory do end describe "when it has group, mode, and owner" do - before do + before do @resource.path("/tmp/foo/bar/") @resource.group("wheel") @resource.mode("0664") diff --git a/spec/unit/resource/dpkg_package_spec.rb b/spec/unit/resource/dpkg_package_spec.rb index 000908712f..9ef498a577 100644 --- a/spec/unit/resource/dpkg_package_spec.rb +++ b/spec/unit/resource/dpkg_package_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,19 +19,19 @@ require 'spec_helper' describe Chef::Resource::DpkgPackage, "initialize" do - + before(:each) do @resource = Chef::Resource::DpkgPackage.new("foo") end - + it "should return a Chef::Resource::DpkgPackage" do @resource.should be_a_kind_of(Chef::Resource::DpkgPackage) end - + it "should set the resource_name to :dpkg_package" do @resource.resource_name.should eql(:dpkg_package) end - + it "should set the provider to Chef::Provider::Package::Dpkg" do @resource.provider.should eql(Chef::Provider::Package::Dpkg) end diff --git a/spec/unit/resource/env_spec.rb b/spec/unit/resource/env_spec.rb index 6862c669b2..b53cbe478f 100644 --- a/spec/unit/resource/env_spec.rb +++ b/spec/unit/resource/env_spec.rb @@ -66,7 +66,7 @@ describe Chef::Resource::Env do end describe "when it has key name and value" do - before do + before do @resource.key_name("charmander") @resource.value("level7") @resource.delim("hi") diff --git a/spec/unit/resource/erl_call_spec.rb b/spec/unit/resource/erl_call_spec.rb index ccad371723..49df9639d1 100644 --- a/spec/unit/resource/erl_call_spec.rb +++ b/spec/unit/resource/erl_call_spec.rb @@ -68,7 +68,7 @@ describe Chef::Resource::ErlCall do end describe "when it has cookie and node_name" do - before do + before do @resource.code("erl-call:function()") @resource.cookie("cookie") @resource.node_name("raster") diff --git a/spec/unit/resource/freebsd_package_spec.rb b/spec/unit/resource/freebsd_package_spec.rb index 697f5fff06..b80a94f98d 100644 --- a/spec/unit/resource/freebsd_package_spec.rb +++ b/spec/unit/resource/freebsd_package_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,19 +19,19 @@ require 'spec_helper' describe Chef::Resource::FreebsdPackage, "initialize" do - + before(:each) do @resource = Chef::Resource::FreebsdPackage.new("foo") end - + it "should return a Chef::Resource::FreebsdPackage" do @resource.should be_a_kind_of(Chef::Resource::FreebsdPackage) end - + it "should set the resource_name to :freebsd_package" do @resource.resource_name.should eql(:freebsd_package) end - + it "should set the provider to Chef::Provider::Package::freebsd" do @resource.provider.should eql(Chef::Provider::Package::Freebsd) end diff --git a/spec/unit/resource/gem_package_spec.rb b/spec/unit/resource/gem_package_spec.rb index 2404afa03a..98703455de 100644 --- a/spec/unit/resource/gem_package_spec.rb +++ b/spec/unit/resource/gem_package_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,19 +19,19 @@ require 'spec_helper' describe Chef::Resource::GemPackage, "initialize" do - + before(:each) do @resource = Chef::Resource::GemPackage.new("foo") end - + it "should return a Chef::Resource::GemPackage" do @resource.should be_a_kind_of(Chef::Resource::GemPackage) end - + it "should set the resource_name to :gem_package" do @resource.resource_name.should eql(:gem_package) end - + it "should set the provider to Chef::Provider::Package::Rubygems" do @resource.provider.should eql(Chef::Provider::Package::Rubygems) end diff --git a/spec/unit/resource/git_spec.rb b/spec/unit/resource/git_spec.rb index 69b40ffd42..95a30c28a4 100644 --- a/spec/unit/resource/git_spec.rb +++ b/spec/unit/resource/git_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,28 +19,28 @@ require 'spec_helper' describe Chef::Resource::Git do - + before(:each) do @git = Chef::Resource::Git.new("my awesome webapp") end - + it "is a kind of Scm Resource" do @git.should be_a_kind_of(Chef::Resource::Scm) @git.should be_an_instance_of(Chef::Resource::Git) end - + it "uses the git provider" do @git.provider.should eql(Chef::Provider::Git) end - + it "uses aliases revision as branch" do @git.branch "HEAD" @git.revision.should eql("HEAD") end - + it "aliases revision as reference" do @git.reference "v1.0 tag" @git.revision.should eql("v1.0 tag") end - + end diff --git a/spec/unit/resource/group_spec.rb b/spec/unit/resource/group_spec.rb index 4e6828ca30..df68c5691f 100644 --- a/spec/unit/resource/group_spec.rb +++ b/spec/unit/resource/group_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -22,7 +22,7 @@ require 'spec_helper' describe Chef::Resource::Group, "initialize" do before(:each) do @resource = Chef::Resource::Group.new("admin") - end + end it "should create a new Chef::Resource::Group" do @resource.should be_a_kind_of(Chef::Resource) @@ -32,7 +32,7 @@ describe Chef::Resource::Group, "initialize" do it "should set the resource_name to :group" do @resource.resource_name.should eql(:group) end - + it "should set the group_name equal to the argument to initialize" do @resource.group_name.should eql("admin") end @@ -40,7 +40,7 @@ describe Chef::Resource::Group, "initialize" do it "should default gid to nil" do @resource.gid.should eql(nil) end - + it "should default members to an empty array" do @resource.members.should eql([]) end @@ -48,11 +48,11 @@ describe Chef::Resource::Group, "initialize" do it "should alias users to members, also an empty array" do @resource.users.should eql([]) end - + it "should set action to :create" do @resource.action.should eql(:create) end - + %w{create remove modify manage}.each do |action| it "should allow action #{action}" do @resource.allowed_actions.detect { |a| a == action.to_sym }.should eql(action.to_sym) @@ -125,11 +125,11 @@ describe Chef::Resource::Group, "append" do before(:each) do @resource = Chef::Resource::Group.new("admin") end - + it "should default to false" do @resource.append.should eql(false) end - + it "should allow a boolean" do @resource.append true @resource.append.should eql(true) @@ -138,9 +138,9 @@ describe Chef::Resource::Group, "append" do it "should not allow a hash" do lambda { @resource.send(:gid, { :aj => "is freakin awesome" }) }.should raise_error(ArgumentError) end - + describe "when it has members" do - before do + before do @resource.group_name("pokemon") @resource.members(["blastoise", "pikachu"]) end diff --git a/spec/unit/resource/http_request_spec.rb b/spec/unit/resource/http_request_spec.rb index 924cf66fc2..b636ca9994 100644 --- a/spec/unit/resource/http_request_spec.rb +++ b/spec/unit/resource/http_request_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -23,7 +23,7 @@ describe Chef::Resource::HttpRequest do before(:each) do @resource = Chef::Resource::HttpRequest.new("fakey_fakerton") - end + end it "should create a new Chef::Resource::HttpRequest" do @resource.should be_a_kind_of(Chef::Resource) @@ -34,18 +34,18 @@ describe Chef::Resource::HttpRequest do @resource.url "http://slashdot.org" @resource.url.should eql("http://slashdot.org") end - + it "should set the message to the name by default" do @resource.message.should eql("fakey_fakerton") end - + it "should set message to a string" do @resource.message "monkeybars" @resource.message.should eql("monkeybars") end describe "when it has a message and headers" do - before do + before do @resource.url("http://www.trololol.net") @resource.message("Get sum post brah.") @resource.headers({"head" => "tail"}) @@ -55,5 +55,5 @@ describe Chef::Resource::HttpRequest do @resource.identity.should == "http://www.trololol.net" end end - + end diff --git a/spec/unit/resource/ifconfig_spec.rb b/spec/unit/resource/ifconfig_spec.rb index 58869d5107..10a4d09982 100644 --- a/spec/unit/resource/ifconfig_spec.rb +++ b/spec/unit/resource/ifconfig_spec.rb @@ -28,7 +28,7 @@ describe Chef::Resource::Ifconfig do end describe "when it has target, hardware address, inet address, and a mask" do - before do + before do @resource.device("charmander") @resource.target("team_rocket") @resource.hwaddr("11.2223.223") diff --git a/spec/unit/resource/ips_package_spec.rb b/spec/unit/resource/ips_package_spec.rb index 92e62606de..61661922fa 100644 --- a/spec/unit/resource/ips_package_spec.rb +++ b/spec/unit/resource/ips_package_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,19 +19,19 @@ require 'spec_helper' describe Chef::Resource::IpsPackage, "initialize" do - + before(:each) do @resource = Chef::Resource::IpsPackage.new("crypto/gnupg") end - + it "should return a Chef::Resource::IpsPackage" do @resource.should be_a_kind_of(Chef::Resource::IpsPackage) end - + it "should set the resource_name to :ips_package" do @resource.resource_name.should eql(:ips_package) end - + it "should set the provider to Chef::Provider::Package::Ips" do @resource.provider.should eql(Chef::Provider::Package::Ips) end diff --git a/spec/unit/resource/link_spec.rb b/spec/unit/resource/link_spec.rb index bf01bce766..fc3f7ff41c 100644 --- a/spec/unit/resource/link_spec.rb +++ b/spec/unit/resource/link_spec.rb @@ -97,7 +97,7 @@ describe Chef::Resource::Link do end describe "when it has to, link_type, owner, and group" do - before do + before do @resource.target_file("/var/target.tar") @resource.to("/to/dir/file.tar") @resource.link_type(:symbolic) diff --git a/spec/unit/resource/log_spec.rb b/spec/unit/resource/log_spec.rb index 4c6b2c122d..c0201e57f3 100644 --- a/spec/unit/resource/log_spec.rb +++ b/spec/unit/resource/log_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -24,12 +24,16 @@ describe Chef::Resource::Log do before(:each) do @log_str = "this is my string to log" @resource = Chef::Resource::Log.new(@log_str) - end - + end + it "should create a new Chef::Resource::Log" do - @resource.should be_a_kind_of(Chef::Resource) - @resource.should be_a_kind_of(Chef::Resource::Log) - end + @resource.should be_a_kind_of(Chef::Resource) + @resource.should be_a_kind_of(Chef::Resource::Log) + end + + it "supports the :write actions" do + @resource.allowed_actions.should include(:write) + end it "should have a name of log" do @resource.resource_name.should == :log @@ -47,7 +51,7 @@ describe Chef::Resource::Log do @resource.message "this is different" @resource.message.should == "this is different" end - + it "should accept a vaild level option" do @resource.level :debug @resource.level :info @@ -58,7 +62,7 @@ describe Chef::Resource::Log do end describe "when the identity is defined" do - before do + before do @resource = Chef::Resource::Log.new("ery day I'm loggin-in") end @@ -67,4 +71,3 @@ describe Chef::Resource::Log do end end end - diff --git a/spec/unit/resource/macports_package_spec.rb b/spec/unit/resource/macports_package_spec.rb index 7420fafeb5..7e2e200487 100644 --- a/spec/unit/resource/macports_package_spec.rb +++ b/spec/unit/resource/macports_package_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/resource/mdadm_spec.rb b/spec/unit/resource/mdadm_spec.rb index c4e6704ceb..310f420659 100644 --- a/spec/unit/resource/mdadm_spec.rb +++ b/spec/unit/resource/mdadm_spec.rb @@ -80,13 +80,13 @@ describe Chef::Resource::Mdadm do end describe "when it has devices, level, and chunk" do - before do + before do @resource.raid_device("raider") @resource.devices(["device1", "device2"]) @resource.level(1) @resource.chunk(42) end - + it "describes its state" do state = @resource.state state[:devices].should eql(["device1", "device2"]) @@ -98,5 +98,5 @@ describe Chef::Resource::Mdadm do @resource.identity.should == "raider" end end - + end diff --git a/spec/unit/resource/mount_spec.rb b/spec/unit/resource/mount_spec.rb index 9f9a534a4e..fb414018ba 100644 --- a/spec/unit/resource/mount_spec.rb +++ b/spec/unit/resource/mount_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -23,7 +23,7 @@ describe Chef::Resource::Mount do before(:each) do @resource = Chef::Resource::Mount.new("filesystem") end - + it "should create a new Chef::Resource::Mount" do @resource.should be_a_kind_of(Chef::Resource) @resource.should be_a_kind_of(Chef::Resource::Mount) @@ -36,18 +36,18 @@ describe Chef::Resource::Mount do it "should set mount_point to the name" do @resource.mount_point.should eql("filesystem") end - + it "should have a default action of mount" do @resource.action.should eql(:mount) end - + it "should accept mount, umount and remount as actions" do lambda { @resource.action :mount }.should_not raise_error(ArgumentError) lambda { @resource.action :umount }.should_not raise_error(ArgumentError) lambda { @resource.action :remount }.should_not raise_error(ArgumentError) lambda { @resource.action :brooklyn }.should raise_error(ArgumentError) end - + it "should allow you to set the device attribute" do @resource.device "/dev/sdb3" @resource.device.should eql("/dev/sdb3") @@ -76,19 +76,19 @@ describe Chef::Resource::Mount do @resource.options "rw,noexec" @resource.options.should be_a_kind_of(Array) end - + it "should allow options attribute as an array" do @resource.options ["ro", "nosuid"] @resource.options.should be_a_kind_of(Array) end it "should accept true for mounted" do - @resource.mounted(true) + @resource.mounted(true) @resource.mounted.should eql(true) end it "should accept false for mounted" do - @resource.mounted(false) + @resource.mounted(false) @resource.mounted.should eql(false) end @@ -101,12 +101,12 @@ describe Chef::Resource::Mount do end it "should accept true for enabled" do - @resource.enabled(true) + @resource.enabled(true) @resource.enabled.should eql(true) end it "should accept false for enabled" do - @resource.enabled(false) + @resource.enabled(false) @resource.enabled.should eql(false) end @@ -152,7 +152,7 @@ describe Chef::Resource::Mount do end describe "when it has mount point, device type, and fstype" do - before do + before do @resource.device("charmander") @resource.mount_point("123.456") @resource.device_type(:device) @@ -172,7 +172,7 @@ describe Chef::Resource::Mount do end describe "when it has username, password and domain" do - before do + before do @resource.mount_point("T:") @resource.device("charmander") @resource.username("Administrator") diff --git a/spec/unit/resource/ohai_spec.rb b/spec/unit/resource/ohai_spec.rb index 82df61e509..b8d062b4c9 100644 --- a/spec/unit/resource/ohai_spec.rb +++ b/spec/unit/resource/ohai_spec.rb @@ -43,7 +43,7 @@ describe Chef::Resource::Ohai do end describe "when it has a plugin value" do - before do + before do @resource.name("test") @resource.plugin("passwd") end diff --git a/spec/unit/resource/package_spec.rb b/spec/unit/resource/package_spec.rb index 3f9cc7a408..0f175dda12 100644 --- a/spec/unit/resource/package_spec.rb +++ b/spec/unit/resource/package_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -23,7 +23,7 @@ describe Chef::Resource::Package do before(:each) do @resource = Chef::Resource::Package.new("emacs") - end + end it "should create a new Chef::Resource::Package" do @resource.should be_a_kind_of(Chef::Resource) @@ -38,12 +38,12 @@ describe Chef::Resource::Package do @resource.package_name "something" @resource.package_name.should eql("something") end - + it "should accept a string for the version" do @resource.version "something" @resource.version.should eql("something") end - + it "should accept a string for the response file" do @resource.response_file "something" @resource.response_file.should eql("something") @@ -71,7 +71,7 @@ describe Chef::Resource::Package do state[:version].should == "10.9.8" state[:options].should == "-al" end - + it "returns the file path as its identity" do @resource.identity.should == "tomcat" end diff --git a/spec/unit/resource/pacman_package_spec.rb b/spec/unit/resource/pacman_package_spec.rb index 53ecd296c9..ec5feeb82c 100644 --- a/spec/unit/resource/pacman_package_spec.rb +++ b/spec/unit/resource/pacman_package_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,19 +19,19 @@ require 'spec_helper' describe Chef::Resource::PacmanPackage, "initialize" do - + before(:each) do @resource = Chef::Resource::PacmanPackage.new("foo") end - + it "should return a Chef::Resource::PacmanPackage" do @resource.should be_a_kind_of(Chef::Resource::PacmanPackage) end - + it "should set the resource_name to :pacman_package" do @resource.resource_name.should eql(:pacman_package) end - + it "should set the provider to Chef::Provider::Package::Pacman" do @resource.provider.should eql(Chef::Provider::Package::Pacman) end diff --git a/spec/unit/resource/perl_spec.rb b/spec/unit/resource/perl_spec.rb index f0313e6fb9..d25dc98563 100644 --- a/spec/unit/resource/perl_spec.rb +++ b/spec/unit/resource/perl_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -22,17 +22,17 @@ describe Chef::Resource::Perl do before(:each) do @resource = Chef::Resource::Perl.new("fakey_fakerton") - end + end it "should create a new Chef::Resource::Perl" do @resource.should be_a_kind_of(Chef::Resource) @resource.should be_a_kind_of(Chef::Resource::Perl) end - + it "should have a resource name of :perl" do @resource.resource_name.should eql(:perl) end - + it "should have an interpreter of perl" do @resource.interpreter.should eql("perl") end diff --git a/spec/unit/resource/portage_package_spec.rb b/spec/unit/resource/portage_package_spec.rb index da086d95ba..510f3b5864 100644 --- a/spec/unit/resource/portage_package_spec.rb +++ b/spec/unit/resource/portage_package_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,19 +19,19 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper")) describe Chef::Resource::PortagePackage, "initialize" do - + before(:each) do @resource = Chef::Resource::PortagePackage.new("foo") end - + it "should return a Chef::Resource::PortagePackage" do @resource.should be_a_kind_of(Chef::Resource::PortagePackage) end - + it "should set the resource_name to :portage_package" do @resource.resource_name.should eql(:portage_package) end - + it "should set the provider to Chef::Provider::Package::Portage" do @resource.provider.should eql(Chef::Provider::Package::Portage) end diff --git a/spec/unit/resource/powershell_spec.rb b/spec/unit/resource/powershell_spec.rb index 6ec37583e6..a35e37c696 100644 --- a/spec/unit/resource/powershell_spec.rb +++ b/spec/unit/resource/powershell_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -30,19 +30,19 @@ describe Chef::Resource::PowershellScript do @resource = Chef::Resource::PowershellScript.new("powershell_unit_test", run_context) - end + end it "should create a new Chef::Resource::PowershellScript" do @resource.should be_a_kind_of(Chef::Resource::PowershellScript) end - + context "windowsscript" do let(:resource_instance) { @resource } let(:resource_instance_name ) { @resource.command } let(:resource_name) { :powershell_script } let(:interpreter_file_name) { 'powershell.exe' } - it_should_behave_like "a Windows script resource" + it_should_behave_like "a Windows script resource" end end diff --git a/spec/unit/resource/python_spec.rb b/spec/unit/resource/python_spec.rb index ff9547db9a..3362b68c62 100644 --- a/spec/unit/resource/python_spec.rb +++ b/spec/unit/resource/python_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -22,17 +22,17 @@ describe Chef::Resource::Python do before(:each) do @resource = Chef::Resource::Python.new("fakey_fakerton") - end + end it "should create a new Chef::Resource::Python" do @resource.should be_a_kind_of(Chef::Resource) @resource.should be_a_kind_of(Chef::Resource::Python) end - + it "should have a resource name of :python" do @resource.resource_name.should eql(:python) end - + it "should have an interpreter of python" do @resource.interpreter.should eql("python") end diff --git a/spec/unit/resource/registry_key_spec.rb b/spec/unit/resource/registry_key_spec.rb index 9d7680de0c..3f227e26b6 100644 --- a/spec/unit/resource/registry_key_spec.rb +++ b/spec/unit/resource/registry_key_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/resource/remote_directory_spec.rb b/spec/unit/resource/remote_directory_spec.rb index e4fa8fc4e3..d3800062ae 100644 --- a/spec/unit/resource/remote_directory_spec.rb +++ b/spec/unit/resource/remote_directory_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -22,7 +22,7 @@ describe Chef::Resource::RemoteDirectory do before(:each) do @resource = Chef::Resource::RemoteDirectory.new("/etc/dunk") - end + end it "should create a new Chef::Resource::RemoteDirectory" do @resource.should be_a_kind_of(Chef::Resource) @@ -46,35 +46,35 @@ describe Chef::Resource::RemoteDirectory do @resource.files_backup 1 @resource.files_backup.should eql(1) end - + it "should accept false for the remote files backup" do @resource.files_backup false @resource.files_backup.should eql(false) end - + it "should accept 3 or 4 digets for the files_mode" do @resource.files_mode 100 @resource.files_mode.should eql(100) @resource.files_mode 1000 @resource.files_mode.should eql(1000) end - + it "should accept a string or number for the files group" do @resource.files_group "heart" @resource.files_group.should eql("heart") @resource.files_group 1000 @resource.files_group.should eql(1000) end - + it "should accept a string or number for the files owner" do @resource.files_owner "heart" @resource.files_owner.should eql("heart") @resource.files_owner 1000 @resource.files_owner.should eql(1000) end - + describe "when it has cookbook, files owner, files mode, and source" do - before do + before do @resource.path("/var/path/") @resource.cookbook("pokemon.rb") @resource.files_owner("root") diff --git a/spec/unit/resource/remote_file_spec.rb b/spec/unit/resource/remote_file_spec.rb index 93fb3c0c36..643bc8ba21 100644 --- a/spec/unit/resource/remote_file_spec.rb +++ b/spec/unit/resource/remote_file_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -123,7 +123,7 @@ describe Chef::Resource::RemoteFile do end describe "when it has group, mode, owner, source, and checksum" do - before do + before do if Chef::Platform.windows? @resource.path("C:/temp/origin/file.txt") @resource.rights(:read, "Everyone") @@ -144,7 +144,7 @@ describe Chef::Resource::RemoteFile do puts state state[:rights].should == [{:permissions => :read, :principals => "Everyone"}] state[:deny_rights].should == [{:permissions => :full_control, :principals => "Clumsy_Sam"}] - else + else state[:group].should == "pokemon" state[:mode].should == "0664" state[:owner].should == "root" diff --git a/spec/unit/resource/route_spec.rb b/spec/unit/resource/route_spec.rb index 966b3aed34..bca42f1101 100644 --- a/spec/unit/resource/route_spec.rb +++ b/spec/unit/resource/route_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -23,31 +23,31 @@ describe Chef::Resource::Route do before(:each) do @resource = Chef::Resource::Route.new("10.0.0.10") - end + end it "should create a new Chef::Resource::Route" do @resource.should be_a_kind_of(Chef::Resource) @resource.should be_a_kind_of(Chef::Resource::Route) end - + it "should have a name" do @resource.name.should eql("10.0.0.10") end - + it "should have a default action of 'add'" do @resource.action.should eql([:add]) end - + it "should accept add or delete for action" do lambda { @resource.action :add }.should_not raise_error(ArgumentError) lambda { @resource.action :delete }.should_not raise_error(ArgumentError) lambda { @resource.action :lolcat }.should raise_error(ArgumentError) end - + it "should use the object name as the target by default" do @resource.target.should eql("10.0.0.10") end - + it "should allow you to specify the netmask" do @resource.netmask "255.255.255.0" @resource.netmask.should eql("255.255.255.0") @@ -72,22 +72,22 @@ describe Chef::Resource::Route do @resource.route_type "host" @resource.route_type.should eql(:host) end - + it "should default to a host route type" do @resource.route_type.should eql(:host) end - + it "should accept a net route type" do @resource.route_type :net @resource.route_type.should eql(:net) end - + it "should reject any other route_type but :host and :net" do lambda { @resource.route_type "lolcat" }.should raise_error(ArgumentError) end - + describe "when it has netmask, gateway, and device" do - before do + before do @resource.target("charmander") @resource.netmask("lemask") @resource.gateway("111.111.111") diff --git a/spec/unit/resource/rpm_package_spec.rb b/spec/unit/resource/rpm_package_spec.rb index d59dc6b29c..25930a5484 100644 --- a/spec/unit/resource/rpm_package_spec.rb +++ b/spec/unit/resource/rpm_package_spec.rb @@ -6,9 +6,9 @@ # 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. diff --git a/spec/unit/resource/ruby_block_spec.rb b/spec/unit/resource/ruby_block_spec.rb index 637d4fe34d..82bbd1ffc7 100644 --- a/spec/unit/resource/ruby_block_spec.rb +++ b/spec/unit/resource/ruby_block_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -33,7 +33,7 @@ describe Chef::Resource::RubyBlock do it "should have a default action of 'create'" do @resource.action.should eql("run") end - + it "should have a resource name of :ruby_block" do @resource.resource_name.should eql(:ruby_block) end @@ -50,7 +50,7 @@ describe Chef::Resource::RubyBlock do end describe "when it has been initialized with block code" do - before do + before do @resource.block_name("puts 'harrrr'") end diff --git a/spec/unit/resource/ruby_spec.rb b/spec/unit/resource/ruby_spec.rb index 48dfd90898..9bf7316e6d 100644 --- a/spec/unit/resource/ruby_spec.rb +++ b/spec/unit/resource/ruby_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -22,17 +22,17 @@ describe Chef::Resource::Ruby do before(:each) do @resource = Chef::Resource::Ruby.new("fakey_fakerton") - end + end it "should create a new Chef::Resource::Ruby" do @resource.should be_a_kind_of(Chef::Resource) @resource.should be_a_kind_of(Chef::Resource::Ruby) end - + it "should have a resource name of :ruby" do @resource.resource_name.should eql(:ruby) end - + it "should have an interpreter of ruby" do @resource.interpreter.should eql("ruby") end diff --git a/spec/unit/resource/scm_spec.rb b/spec/unit/resource/scm_spec.rb index 488d335342..8f6593a931 100644 --- a/spec/unit/resource/scm_spec.rb +++ b/spec/unit/resource/scm_spec.rb @@ -137,8 +137,21 @@ describe Chef::Resource::Scm do @resource.ssh_wrapper.should be_nil end + describe "when it has a timeout attribute" do + let(:ten_seconds) { 10 } + before { @resource.timeout(ten_seconds) } + it "stores this timeout" do + @resource.timeout.should == ten_seconds + end + end + describe "when it has no timeout attribute" do + it "should have no default timeout" do + @resource.timeout.should be_nil + end + end + describe "when it has repository, revision, user, and group" do - before do + before do @resource.destination("hell") @resource.repository("apt") @resource.revision("1.2.3") diff --git a/spec/unit/resource/script_spec.rb b/spec/unit/resource/script_spec.rb index 53735daf01..f100b0dc85 100644 --- a/spec/unit/resource/script_spec.rb +++ b/spec/unit/resource/script_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -20,7 +20,7 @@ require 'spec_helper' describe Chef::Resource::Script do - let(:resource_instance_name) { "fakey_fakerton" } + let(:resource_instance_name) { "fakey_fakerton" } let(:script_resource) { Chef::Resource::Script.new(resource_instance_name) } let(:resource_name) { :script } @@ -30,7 +30,7 @@ describe Chef::Resource::Script do end describe "when it has interpreter and flags" do - before do + before do script_resource.command("grep") script_resource.interpreter("gcc") script_resource.flags("-al") @@ -40,7 +40,7 @@ describe Chef::Resource::Script do script_resource.identity.should == "grep" end end - + it_behaves_like "a script resource" end diff --git a/spec/unit/resource/service_spec.rb b/spec/unit/resource/service_spec.rb index c06eb9dd77..067fa7d0d3 100644 --- a/spec/unit/resource/service_spec.rb +++ b/spec/unit/resource/service_spec.rb @@ -7,9 +7,9 @@ # 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. @@ -23,7 +23,7 @@ describe Chef::Resource::Service do before(:each) do @resource = Chef::Resource::Service.new("chef") - end + end it "should create a new Chef::Resource::Service" do @resource.should be_a_kind_of(Chef::Resource) @@ -42,7 +42,7 @@ describe Chef::Resource::Service do @resource.service_name "something" @resource.service_name.should eql("something") end - + it "should accept a string for the service pattern" do @resource.pattern ".*" @resource.pattern.should eql(".*") @@ -53,7 +53,7 @@ describe Chef::Resource::Service do @resource.pattern /.*/ }.should raise_error(ArgumentError) end - + it "should accept a string for the service start command" do @resource.start_command "/etc/init.d/chef start" @resource.start_command.should eql("/etc/init.d/chef start") @@ -64,7 +64,7 @@ describe Chef::Resource::Service do @resource.start_command /.*/ }.should raise_error(ArgumentError) end - + it "should accept a string for the service stop command" do @resource.stop_command "/etc/init.d/chef stop" @resource.stop_command.should eql("/etc/init.d/chef stop") @@ -75,23 +75,23 @@ describe Chef::Resource::Service do @resource.stop_command /.*/ }.should raise_error(ArgumentError) end - + it "should accept a string for the service status command" do @resource.status_command "/etc/init.d/chef status" @resource.status_command.should eql("/etc/init.d/chef status") end - + it "should not accept a regexp for the service status command" do lambda { @resource.status_command /.*/ }.should raise_error(ArgumentError) end - + it "should accept a string for the service restart command" do @resource.restart_command "/etc/init.d/chef restart" @resource.restart_command.should eql("/etc/init.d/chef restart") end - + it "should not accept a regexp for the service restart command" do lambda { @resource.restart_command /.*/ @@ -102,13 +102,13 @@ describe Chef::Resource::Service do @resource.reload_command "/etc/init.d/chef reload" @resource.reload_command.should eql("/etc/init.d/chef reload") end - + it "should not accept a regexp for the service reload command" do lambda { @resource.reload_command /.*/ }.should raise_error(ArgumentError) end - + it "should accept a string for the service init command" do @resource.init_command "/etc/init.d/chef" @resource.init_command.should eql("/etc/init.d/chef") @@ -122,15 +122,15 @@ describe Chef::Resource::Service do %w{enabled running}.each do |attrib| it "should accept true for #{attrib}" do - @resource.send(attrib, true) + @resource.send(attrib, true) @resource.send(attrib).should eql(true) end - + it "should accept false for #{attrib}" do @resource.send(attrib, false) @resource.send(attrib).should eql(false) end - + it "should not accept a string for #{attrib}" do lambda { @resource.send(attrib, "poop") }.should raise_error(ArgumentError) end @@ -138,7 +138,7 @@ describe Chef::Resource::Service do it "should default all the feature support to false" do support_hash = { :status => false, :restart => false, :reload=> false } @resource.supports.should == support_hash - end + end it "should allow you to set what features this resource supports as a array" do support_array = [ :status, :restart ] @@ -155,7 +155,7 @@ describe Chef::Resource::Service do end describe "when it has pattern and supports" do - before do + before do @resource.service_name("superfriend") @resource.enabled(true) @resource.running(false) @@ -172,5 +172,5 @@ describe Chef::Resource::Service do end end - + end diff --git a/spec/unit/resource/smartos_package_spec.rb b/spec/unit/resource/smartos_package_spec.rb index ca815320ad..391713c8ff 100644 --- a/spec/unit/resource/smartos_package_spec.rb +++ b/spec/unit/resource/smartos_package_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -18,14 +18,14 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper")) -describe Chef::Resource::SmartOSPackage, "initialize" do +describe Chef::Resource::SmartosPackage, "initialize" do before(:each) do - @resource = Chef::Resource::SmartOSPackage.new("foo") + @resource = Chef::Resource::SmartosPackage.new("foo") end - it "should return a Chef::Resource::SmartOSPackage" do - @resource.should be_a_kind_of(Chef::Resource::SmartOSPackage) + it "should return a Chef::Resource::SmartosPackage" do + @resource.should be_a_kind_of(Chef::Resource::SmartosPackage) end it "should set the resource_name to :smartos_package" do diff --git a/spec/unit/resource/solaris_package_spec.rb b/spec/unit/resource/solaris_package_spec.rb new file mode 100644 index 0000000000..6d0260ab5a --- /dev/null +++ b/spec/unit/resource/solaris_package_spec.rb @@ -0,0 +1,57 @@ +# +# Author:: Prabhu Das (<prabhu.das@clogeny.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::SolarisPackage, "initialize" do + + before(:each) do + @resource = Chef::Resource::SolarisPackage.new("foo") + end + + it "should return a Chef::Resource::SolarisPackage object" do + @resource.should be_a_kind_of(Chef::Resource::SolarisPackage) + end + + it "should not raise any Error when valid number of arguments are provided" do + expect { Chef::Resource::SolarisPackage.new("foo") }.to_not raise_error + end + + it "should raise ArgumentError when incorrect number of arguments are provided" do + expect { Chef::Resource::SolarisPackage.new }.to raise_error(ArgumentError) + end + + it "should set the package_name to the name provided" do + @resource.package_name.should eql("foo") + end + + it "should set the resource_name to :solaris_package" do + @resource.resource_name.should eql(:solaris_package) + end + + it "should set the run_context to the run_context provided" do + @run_context = double() + @run_context.stub(:node) + resource = Chef::Resource::SolarisPackage.new("foo", @run_context) + resource.run_context.should eql(@run_context) + end + + it "should set the provider to Chef::Provider::Package::Solaris" do + @resource.provider.should eql(Chef::Provider::Package::Solaris) + end +end diff --git a/spec/unit/resource/subversion_spec.rb b/spec/unit/resource/subversion_spec.rb index 650eb010a6..67593c5a7c 100644 --- a/spec/unit/resource/subversion_spec.rb +++ b/spec/unit/resource/subversion_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,20 +19,20 @@ require 'spec_helper' describe Chef::Resource::Subversion do - + before do @svn = Chef::Resource::Subversion.new("ohai, svn project!") end - + it "is a subclass of Resource::Scm" do @svn.should be_an_instance_of(Chef::Resource::Subversion) @svn.should be_a_kind_of(Chef::Resource::Scm) end - + it "uses the subversion provider" do @svn.provider.should eql(Chef::Provider::Subversion) end - + it "allows the force_export action" do @svn.allowed_actions.should include(:force_export) end diff --git a/spec/unit/resource/timestamped_deploy_spec.rb b/spec/unit/resource/timestamped_deploy_spec.rb index 89b881830a..f380ffca87 100644 --- a/spec/unit/resource/timestamped_deploy_spec.rb +++ b/spec/unit/resource/timestamped_deploy_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,10 +19,10 @@ require 'spec_helper' describe Chef::Resource::TimestampedDeploy do - + it "defaults to the TimestampedDeploy provider" do @resource = Chef::Resource::TimestampedDeploy.new("stuff") @resource.provider.should == Chef::Provider::Deploy::Timestamped end - + end diff --git a/spec/unit/resource/user_spec.rb b/spec/unit/resource/user_spec.rb index 3454152367..caf12aa416 100644 --- a/spec/unit/resource/user_spec.rb +++ b/spec/unit/resource/user_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -21,7 +21,7 @@ require 'spec_helper' describe Chef::Resource::User, "initialize" do before(:each) do @resource = Chef::Resource::User.new("adam") - end + end it "should create a new Chef::Resource::User" do @resource.should be_a_kind_of(Chef::Resource) @@ -31,29 +31,29 @@ describe Chef::Resource::User, "initialize" do it "should set the resource_name to :user" do @resource.resource_name.should eql(:user) end - + it "should set the username equal to the argument to initialize" do @resource.username.should eql("adam") end - + %w{comment uid gid home shell password}.each do |attrib| it "should set #{attrib} to nil" do @resource.send(attrib).should eql(nil) end end - + it "should set action to :create" do @resource.action.should eql(:create) end - + it "should set supports[:manage_home] to false" do @resource.supports[:manage_home].should eql(false) end - + it "should set supports[:non_unique] to false" do @resource.supports[:non_unique].should eql(false) end - + %w{create remove modify manage lock unlock}.each do |action| it "should allow action #{action}" do @resource.allowed_actions.detect { |a| a == action.to_sym }.should eql(action.to_sym) @@ -72,7 +72,7 @@ end describe Chef::Resource::User, attrib do before(:each) do @resource = Chef::Resource::User.new("adam") - end + end it "should allow a string" do @resource.send(attrib, "adam") @@ -89,13 +89,13 @@ end describe Chef::Resource::User, attrib do before(:each) do @resource = Chef::Resource::User.new("adam") - end + end it "should allow a string" do @resource.send(attrib, "100") @resource.send(attrib).should eql("100") end - + it "should allow an integer" do @resource.send(attrib, 100) @resource.send(attrib).should eql(100) @@ -105,7 +105,7 @@ end lambda { @resource.send(attrib, { :woot => "i found it" }) }.should raise_error(ArgumentError) end end - + describe "when it has uid, gid, and home" do before do @resource = Chef::Resource::User.new("root") diff --git a/spec/unit/resource/yum_package_spec.rb b/spec/unit/resource/yum_package_spec.rb index a0f4aaee55..783a539eb2 100644 --- a/spec/unit/resource/yum_package_spec.rb +++ b/spec/unit/resource/yum_package_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,19 +19,19 @@ require 'spec_helper' describe Chef::Resource::YumPackage, "initialize" do - + before(:each) do @resource = Chef::Resource::YumPackage.new("foo") end - + it "should return a Chef::Resource::YumPackage" do @resource.should be_a_kind_of(Chef::Resource::YumPackage) end - + it "should set the resource_name to :yum_package" do @resource.resource_name.should eql(:yum_package) end - + it "should set the provider to Chef::Provider::Package::Yum" do @resource.provider.should eql(Chef::Provider::Package::Yum) end @@ -56,7 +56,7 @@ describe Chef::Resource::YumPackage, "flush_cache" do it "should default the flush timing to false" do flush_hash = { :before => false, :after => false } @resource.flush_cache.should == flush_hash - end + end it "should allow you to set the flush timing with an array" do flush_array = [ :before, :after ] diff --git a/spec/unit/resource_collection/stepable_iterator_spec.rb b/spec/unit/resource_collection/stepable_iterator_spec.rb index 1da9de20cc..b649f8be6e 100644 --- a/spec/unit/resource_collection/stepable_iterator_spec.rb +++ b/spec/unit/resource_collection/stepable_iterator_spec.rb @@ -5,9 +5,9 @@ # 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. @@ -19,17 +19,17 @@ require 'spec_helper' describe Chef::ResourceCollection::StepableIterator do CRSI = Chef::ResourceCollection::StepableIterator - + it "has an empty array for its collection by default" do CRSI.new.collection.should == [] end - + describe "doing basic iteration" do before do @simple_collection = [1,2,3,4] @iterator = CRSI.for_collection(@simple_collection) end - + it "re-initializes the instance with a collection" do @iterator.collection.should equal(@simple_collection) @iterator.size.should == 4 @@ -51,7 +51,7 @@ describe Chef::ResourceCollection::StepableIterator do collected_by_index.should == @simple_collection collected_by_index.should_not equal(@simple_collection) end - + it "iterates over the collection with index and element" do collected = {} @iterator.each_with_index do |element, index| @@ -59,32 +59,32 @@ describe Chef::ResourceCollection::StepableIterator do end collected.should == {0=>1, 1=>2, 2=>3, 3=>4} end - + end - + describe "pausing and resuming iteration" do - + before do @collection = [] @snitch_var = nil @collection << lambda { @snitch_var = 23 } @collection << lambda { @iterator.pause } @collection << lambda { @snitch_var = 42 } - + @iterator = CRSI.for_collection(@collection) @iterator.each { |proc| proc.call } end - + it "allows the iteration to be paused" do @snitch_var.should == 23 end - + it "allows the iteration to be resumed" do @snitch_var.should == 23 @iterator.resume @snitch_var.should == 42 end - + it "allows iteration to be rewound" do @iterator.skip_back(2) @iterator.resume @@ -92,13 +92,13 @@ describe Chef::ResourceCollection::StepableIterator do @iterator.resume @snitch_var.should == 42 end - + it "allows iteration to be fast forwarded" do @iterator.skip_forward @iterator.resume @snitch_var.should == 23 end - + it "allows iteration to be rewound" do @snitch_var = nil @iterator.rewind @@ -106,7 +106,7 @@ describe Chef::ResourceCollection::StepableIterator do @iterator.resume @snitch_var.should == 23 end - + it "allows iteration to be stepped" do @snitch_var = nil @iterator.rewind @@ -114,13 +114,13 @@ describe Chef::ResourceCollection::StepableIterator do @iterator.position.should == 1 @snitch_var.should == 23 end - + it "doesn't step if there are no more steps" do @iterator.step.should == 3 lambda {@iterator.step}.should_not raise_error @iterator.step.should be_nil end - + it "allows the iteration to start by being stepped" do @snitch_var = nil @iterator = CRSI.for_collection(@collection) @@ -129,7 +129,7 @@ describe Chef::ResourceCollection::StepableIterator do @iterator.position.should == 1 @snitch_var.should == 23 end - + it "should work correctly when elements are added to the collection during iteration" do @collection.insert(2, lambda { @snitch_var = 815}) @collection.insert(3, lambda { @iterator.pause }) @@ -138,7 +138,7 @@ describe Chef::ResourceCollection::StepableIterator do @iterator.resume @snitch_var.should == 42 end - + end - + end diff --git a/spec/unit/resource_definition_spec.rb b/spec/unit/resource_definition_spec.rb index a29c15a1e3..abac4c1163 100644 --- a/spec/unit/resource_definition_spec.rb +++ b/spec/unit/resource_definition_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -22,16 +22,16 @@ describe Chef::ResourceDefinition do before(:each) do @def = Chef::ResourceDefinition.new() end - + describe "initialize" do it "should be a Chef::ResourceDefinition" do @def.should be_a_kind_of(Chef::ResourceDefinition) end - + it "should not initialize a new node if one is not provided" do @def.node.should eql(nil) end - + it "should accept a node as an argument" do node = Chef::Node.new node.name("bobo") @@ -39,7 +39,7 @@ describe Chef::ResourceDefinition do @def.node.name.should == "bobo" end end - + describe "node" do it "should set the node with node=" do node = Chef::Node.new @@ -47,32 +47,32 @@ describe Chef::ResourceDefinition do @def.node = node @def.node.name.should == "bobo" end - + it "should return the node" do @def.node = Chef::Node.new @def.node.should be_a_kind_of(Chef::Node) end end - + it "should accept a new definition with a symbol for a name" do - lambda { - @def.define :smoke do + lambda { + @def.define :smoke do end }.should_not raise_error(ArgumentError) - lambda { + lambda { @def.define "george washington" do - end + end }.should raise_error(ArgumentError) @def.name.should eql(:smoke) end - + it "should accept a new definition with a hash" do - lambda { + lambda { @def.define :smoke, :cigar => "cuban", :cigarette => "marlboro" do end }.should_not raise_error(ArgumentError) end - + it "should expose the prototype hash params in the params hash" do @def.define :smoke, :cigar => "cuban", :cigarette => "marlboro" do; end @def.params[:cigar].should eql("cuban") @@ -86,34 +86,34 @@ describe Chef::ResourceDefinition do @def.recipe.should be_a_kind_of(Proc) @def.recipe.call.should eql("I am what I am") end - + it "should set paramaters based on method_missing" do @def.mind "to fly" @def.params[:mind].should eql("to fly") end - + it "should raise an exception if prototype_params is not a hash" do lambda { @def.define :monkey, Array.new do end }.should raise_error(ArgumentError) end - + it "should raise an exception if define is called without a block" do - lambda { + lambda { @def.define :monkey }.should raise_error(ArgumentError) end - + it "should load a description from a file" do @def.from_file(File.join(CHEF_SPEC_DATA, "definitions", "test.rb")) @def.name.should eql(:rico_suave) @def.params[:rich].should eql("smooth") - end - + end + it "should turn itself into a string based on the name with to_s" do @def.name = :woot @def.to_s.should eql("woot") end - + end diff --git a/spec/unit/resource_reporter_spec.rb b/spec/unit/resource_reporter_spec.rb index cb4f5bce94..e2ecde212f 100644 --- a/spec/unit/resource_reporter_spec.rb +++ b/spec/unit/resource_reporter_spec.rb @@ -464,6 +464,33 @@ describe Chef::ResourceReporter do end end + context "when including a resource that overrides Resource#state" do + before do + @current_state_resource = Chef::Resource::WithState.new("Stateful", @run_context) + @current_state_resource.state = nil + + @new_state_resource = Chef::Resource::WithState.new("Stateful", @run_context) + @new_state_resource.state = "Running" + @resource_reporter.resource_action_start(@new_state_resource, :create) + @resource_reporter.resource_current_state_loaded(@new_state_resource, :create, @current_state_resource) + @resource_reporter.resource_updated(@new_state_resource, :create) + @resource_reporter.resource_completed(@new_state_resource) + @run_status.stop_clock + @report = @resource_reporter.prepare_run_data + @first_update_report = @report["resources"].first + end + + it "sets before to {} instead of nil" do + @first_update_report.should have_key("before") + @first_update_report['before'].should eq({}) + end + + it "sets after to {} instead of 'Running'" do + @first_update_report.should have_key("after") + @first_update_report['after'].should eq({}) + end + end + end describe "when updating resource history on the server" do diff --git a/spec/unit/rest/auth_credentials_spec.rb b/spec/unit/rest/auth_credentials_spec.rb index de06b2cc55..7aa68deab4 100644 --- a/spec/unit/rest/auth_credentials_spec.rb +++ b/spec/unit/rest/auth_credentials_spec.rb @@ -199,100 +199,6 @@ describe Chef::REST::RESTRequest do new_request.http_client.read_timeout.should == 9001 end - describe "for SSL" do - before do - Chef::Config[:ssl_client_cert] = nil - Chef::Config[:ssl_client_key] = nil - Chef::Config[:ssl_ca_path] = nil - Chef::Config[:ssl_ca_file] = nil - end - - after do - Chef::Config[:ssl_client_cert] = nil - Chef::Config[:ssl_client_key] = nil - Chef::Config[:ssl_ca_path] = nil - Chef::Config[:ssl_verify_mode] = :verify_none - Chef::Config[:ssl_ca_file] = nil - end - - describe "when configured with :ssl_verify_mode set to :verify peer" do - before do - @url = URI.parse("https://chef.example.com:4443/") - Chef::Config[:ssl_verify_mode] = :verify_peer - @request = new_request - end - - it "configures the HTTP client to use SSL when given a URL with the https protocol" do - @request.http_client.use_ssl?.should be_true - end - - it "sets the OpenSSL verify mode to verify_peer" do - @request.http_client.verify_mode.should == OpenSSL::SSL::VERIFY_PEER - end - - it "raises a ConfigurationError if :ssl_ca_path is set to a path that doesn't exist" do - Chef::Config[:ssl_ca_path] = "/dev/null/nothing_here" - lambda {new_request}.should raise_error(Chef::Exceptions::ConfigurationError) - end - - it "should set the CA path if that is set in the configuration" do - Chef::Config[:ssl_ca_path] = File.join(CHEF_SPEC_DATA, "ssl") - new_request.http_client.ca_path.should == File.join(CHEF_SPEC_DATA, "ssl") - end - - it "raises a ConfigurationError if :ssl_ca_file is set to a file that does not exist" do - Chef::Config[:ssl_ca_file] = "/dev/null/nothing_here" - lambda {new_request}.should raise_error(Chef::Exceptions::ConfigurationError) - end - - it "should set the CA file if that is set in the configuration" do - Chef::Config[:ssl_ca_file] = CHEF_SPEC_DATA + '/ssl/5e707473.0' - new_request.http_client.ca_file.should == CHEF_SPEC_DATA + '/ssl/5e707473.0' - end - end - - describe "when configured with :ssl_verify_mode set to :verify peer" do - before do - @url = URI.parse("https://chef.example.com:4443/") - Chef::Config[:ssl_verify_mode] = :verify_none - end - - it "sets the OpenSSL verify mode to :verify_none" do - new_request.http_client.verify_mode.should == OpenSSL::SSL::VERIFY_NONE - end - end - - describe "when configured with a client certificate" do - before {@url = URI.parse("https://chef.example.com:4443/")} - - it "raises ConfigurationError if the certificate file doesn't exist" do - Chef::Config[:ssl_client_cert] = "/dev/null/nothing_here" - Chef::Config[:ssl_client_key] = CHEF_SPEC_DATA + '/ssl/chef-rspec.key' - lambda {new_request}.should raise_error(Chef::Exceptions::ConfigurationError) - end - - it "raises ConfigurationError if the certificate file doesn't exist" do - Chef::Config[:ssl_client_cert] = CHEF_SPEC_DATA + '/ssl/chef-rspec.cert' - Chef::Config[:ssl_client_key] = "/dev/null/nothing_here" - lambda {new_request}.should raise_error(Chef::Exceptions::ConfigurationError) - end - - it "raises a ConfigurationError if one of :ssl_client_cert and :ssl_client_key is set but not both" do - Chef::Config[:ssl_client_cert] = "/dev/null/nothing_here" - Chef::Config[:ssl_client_key] = nil - lambda {new_request}.should raise_error(Chef::Exceptions::ConfigurationError) - end - - it "configures the HTTP client's cert and private key" do - Chef::Config[:ssl_client_cert] = CHEF_SPEC_DATA + '/ssl/chef-rspec.cert' - Chef::Config[:ssl_client_key] = CHEF_SPEC_DATA + '/ssl/chef-rspec.key' - http_client = new_request.http_client - http_client.cert.to_s.should == OpenSSL::X509::Certificate.new(IO.read(CHEF_SPEC_DATA + '/ssl/chef-rspec.cert')).to_s - http_client.key.to_s.should == IO.read(CHEF_SPEC_DATA + '/ssl/chef-rspec.key') - end - end - end - describe "for proxy" do before do Chef::Config[:http_proxy] = "http://proxy.example.com:3128" diff --git a/spec/unit/rest_spec.rb b/spec/unit/rest_spec.rb index 5ade86110c..fddb3dc407 100644 --- a/spec/unit/rest_spec.rb +++ b/spec/unit/rest_spec.rb @@ -57,7 +57,7 @@ describe Chef::REST do @log_stringio = StringIO.new Chef::Log.init(@log_stringio) - Chef::REST::CookieJar.stub!(:instance).and_return({}) + Chef::REST::CookieJar.stub(:instance).and_return({}) @base_url = "http://chef.example.com:4000" @monkey_uri = URI.parse("http://chef.example.com:4000/monkey") @rest = Chef::REST.new(@base_url, nil, nil) @@ -76,27 +76,46 @@ describe Chef::REST do end it "makes a :GET request with the composed url object" do - @rest.should_receive(:api_request).with(:GET, @monkey_uri, {}) + @rest.should_receive(:send_http_request). + with(:GET, @monkey_uri, STANDARD_READ_HEADERS, false). + and_return([1,2,3]) + @rest.should_receive(:apply_response_middleware).with(1,2,3).and_return([1,2,3]) + @rest.should_receive('success_response?'.to_sym).with(1).and_return(true) @rest.get_rest("monkey") end it "makes a :GET reqest for a streaming download with the composed url" do - @rest.should_receive(:streaming_request).with(@monkey_uri, {}) + @rest.should_receive(:streaming_request).with('monkey', {}) @rest.get_rest("monkey", true) end - it "makes a :DELETE request with the composed url object" do - @rest.should_receive(:api_request).with(:DELETE, @monkey_uri, {}) + STANDARD_READ_HEADERS = {"Accept"=>"application/json", "Accept"=>"application/json", "Accept-Encoding"=>"gzip;q=1.0,deflate;q=0.6,identity;q=0.3"} + STANDARD_WRITE_HEADERS = {"Accept"=>"application/json", "Content-Type"=>"application/json", "Accept"=>"application/json", "Accept-Encoding"=>"gzip;q=1.0,deflate;q=0.6,identity;q=0.3"} + + it "makes a :DELETE request with the composed url object" do + @rest.should_receive(:send_http_request). + with(:DELETE, @monkey_uri, STANDARD_READ_HEADERS, false). + and_return([1,2,3]) + @rest.should_receive(:apply_response_middleware).with(1,2,3).and_return([1,2,3]) + @rest.should_receive('success_response?'.to_sym).with(1).and_return(true) @rest.delete_rest("monkey") end it "makes a :POST request with the composed url object and data" do - @rest.should_receive(:api_request).with(:POST, @monkey_uri, {}, "data") + @rest.should_receive(:send_http_request). + with(:POST, @monkey_uri, STANDARD_WRITE_HEADERS, "\"data\""). + and_return([1,2,3]) + @rest.should_receive(:apply_response_middleware).with(1,2,3).and_return([1,2,3]) + @rest.should_receive('success_response?'.to_sym).with(1).and_return(true) @rest.post_rest("monkey", "data") end it "makes a :PUT request with the composed url object and data" do - @rest.should_receive(:api_request).with(:PUT, @monkey_uri, {}, "data") + @rest.should_receive(:send_http_request). + with(:PUT, @monkey_uri, STANDARD_WRITE_HEADERS, "\"data\""). + and_return([1,2,3]) + @rest.should_receive(:apply_response_middleware).with(1,2,3).and_return([1,2,3]) + @rest.should_receive('success_response?'.to_sym).with(1).and_return(true) @rest.put_rest("monkey", "data") end end @@ -156,13 +175,13 @@ describe Chef::REST do @url = URI.parse("https://one:80/?foo=bar") @http_response = Net::HTTPSuccess.new("1.1", "200", "successful rest req") - @http_response.stub!(:read_body) - @http_response.stub!(:body).and_return("ninja") + @http_response.stub(:read_body) + @http_response.stub(:body).and_return("ninja") @http_response.add_field("Content-Length", "5") @http_client = Net::HTTP.new(@url.host, @url.port) - Net::HTTP.stub!(:new).and_return(@http_client) - @http_client.stub!(:request).and_yield(@http_response).and_return(@http_response) + Net::HTTP.stub(:new).and_return(@http_client) + @http_client.stub(:request).and_yield(@http_response).and_return(@http_response) @base_headers = { 'Accept' => 'application/json', 'X-Chef-Version' => Chef::VERSION, @@ -172,23 +191,18 @@ describe Chef::REST do describe "streaming downloads to a tempfile" do before do - @tempfile = Tempfile.open("chef-rspec-rest_spec-line-#{__LINE__}--") - Tempfile.stub!(:new).with("chef-rest").and_return(@tempfile) - Tempfile.stub!(:open).and_return(@tempfile) + @tempfile = StringIO.new + @tempfile.stub(:close!) + @tempfile.stub(:path).and_return("/a-temporary-file") + Tempfile.stub(:new).with("chef-rest").and_return(@tempfile) + Tempfile.stub(:open).and_return(@tempfile) @request_mock = {} - Net::HTTP::Get.stub!(:new).and_return(@request_mock) - - @http_response_mock = mock("Net::HTTP Response mock") - end - - after do - @tempfile.rspec_reset - @tempfile.close! + Net::HTTP::Get.stub(:new).and_return(@request_mock) end it "should build a new HTTP GET request without the application/json accept header" do - expected_headers = {'X-Chef-Version' => Chef::VERSION, 'Accept-Encoding' => Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE} + expected_headers = {'Accept' => "*/*", 'X-Chef-Version' => Chef::VERSION, 'Accept-Encoding' => Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE} Net::HTTP::Get.should_receive(:new).with("/?foo=bar", expected_headers).and_return(@request_mock) @rest.streaming_request(@url, {}) end @@ -203,9 +217,9 @@ describe Chef::REST do end it "should populate the tempfile with the value of the raw request" do - @http_response_mock.stub!(:read_body).and_yield("ninja") - @tempfile.should_receive(:write).with("ninja").once.and_return(true) + @http_response.should_receive(:read_body).and_yield("ninja") @rest.streaming_request(@url, {}) + #@tempfile.string.should include("ninja") end it "should close the tempfile if we're doing a raw request" do @@ -214,15 +228,15 @@ describe Chef::REST do end it "should not raise a divide by zero exception if the size is 0" do - @http_response_mock.stub!(:header).and_return({ 'Content-Length' => "5" }) - @http_response_mock.stub!(:read_body).and_yield('') - lambda { @rest.streaming_request(@url, {}) }.should_not raise_error(ZeroDivisionError) + @http_response.stub(:header).and_return({ 'Content-Length' => "5" }) + @http_response.stub(:read_body).and_yield('') + lambda { @rest.streaming_request(@url, {}) }.should_not raise_error end it "should not raise a divide by zero exception if the Content-Length is 0" do - @http_response_mock.stub!(:header).and_return({ 'Content-Length' => "0" }) - @http_response_mock.stub!(:read_body).and_yield("ninja") - lambda { @rest.streaming_request(@url, {}) }.should_not raise_error(ZeroDivisionError) + @http_response.stub(:header).and_return({ 'Content-Length' => "0" }) + @http_response.stub(:read_body).and_yield("ninja") + lambda { @rest.streaming_request(@url, {}) }.should_not raise_error end end @@ -230,7 +244,7 @@ describe Chef::REST do describe "as JSON API requests" do before do @request_mock = {} - Net::HTTP::Get.stub!(:new).and_return(@request_mock) + Net::HTTP::Get.stub(:new).and_return(@request_mock) @base_headers = {"Accept" => "application/json", "X-Chef-Version" => Chef::VERSION, @@ -240,14 +254,14 @@ describe Chef::REST do it "should always include the X-Chef-Version header" do Net::HTTP::Get.should_receive(:new).with("/?foo=bar", @base_headers).and_return(@request_mock) - @rest.api_request(:GET, @url, {}) + @rest.request(:GET, @url, {}) end it "sets the user agent to chef-client" do # must reset to default b/c knife changes the UA Chef::REST::RESTRequest.user_agent = Chef::REST::RESTRequest::DEFAULT_UA - @rest.api_request(:GET, @url, {}) - @request_mock['User-Agent'].should match /^Chef Client\/#{Chef::VERSION}/ + @rest.request(:GET, @url, {}) + @request_mock['User-Agent'].should match(/^Chef Client\/#{Chef::VERSION}/) end # CHEF-3140 @@ -265,7 +279,7 @@ describe Chef::REST do request = Net::HTTP::Get.new(@url.path) Net::HTTP::Get.should_receive(:new).and_return(request) # will raise a Zlib error if incorrect - @rest.api_request(:GET, @url, {}).should == "ninja" + @rest.request(:GET, @url, {}).should == "ninja" end end context "when configured with custom http headers" do @@ -285,19 +299,19 @@ describe Chef::REST do url_string = an_instance_of(String) header_hash = hash_including(@custom_headers) Net::HTTP::Get.should_receive(:new).with(url_string, header_hash) - @rest.api_request(:GET, @url, {}) + @rest.request(:GET, @url, {}) end end it "should set the cookie for this request if one exists for the given host:port" do Chef::REST::CookieJar.instance["#{@url.host}:#{@url.port}"] = "cookie monster" Net::HTTP::Get.should_receive(:new).with("/?foo=bar", @base_headers.merge('Cookie' => "cookie monster")).and_return(@request_mock) - @rest.api_request(:GET, @url, {}) + @rest.request(:GET, @url, {}) end it "should build a new HTTP GET request" do Net::HTTP::Get.should_receive(:new).with("/?foo=bar", @base_headers).and_return(@request_mock) - @rest.api_request(:GET, @url, {}) + @rest.request(:GET, @url, {}) end it "should build a new HTTP POST request" do @@ -305,7 +319,7 @@ describe Chef::REST do expected_headers = @base_headers.merge("Content-Type" => 'application/json', 'Content-Length' => '13') Net::HTTP::Post.should_receive(:new).with("/?foo=bar", expected_headers).and_return(request) - @rest.api_request(:POST, @url, {}, {:one=>:two}) + @rest.request(:POST, @url, {}, {:one=>:two}) request.body.should == '{"one":"two"}' end @@ -313,54 +327,54 @@ describe Chef::REST do request = Net::HTTP::Put.new(@url.path) expected_headers = @base_headers.merge("Content-Type" => 'application/json', 'Content-Length' => '13') Net::HTTP::Put.should_receive(:new).with("/?foo=bar",expected_headers).and_return(request) - @rest.api_request(:PUT, @url, {}, {:one=>:two}) + @rest.request(:PUT, @url, {}, {:one=>:two}) request.body.should == '{"one":"two"}' end it "should build a new HTTP DELETE request" do Net::HTTP::Delete.should_receive(:new).with("/?foo=bar", @base_headers).and_return(@request_mock) - @rest.api_request(:DELETE, @url) + @rest.request(:DELETE, @url) end it "should raise an error if the method is not GET/PUT/POST/DELETE" do - lambda { @rest.api_request(:MONKEY, @url) }.should raise_error(ArgumentError) + lambda { @rest.request(:MONKEY, @url) }.should raise_error(ArgumentError) end it "returns nil when the response is successful but content-type is not JSON" do - @rest.api_request(:GET, @url).should == "ninja" + @rest.request(:GET, @url).should == "ninja" end it "should inflate the body as to an object if JSON is returned" do @http_response.add_field('content-type', "application/json") - @http_response.stub!(:body).and_return('{"ohai2u":"json_api"}') - @rest.api_request(:GET, @url, {}).should == {"ohai2u"=>"json_api"} + @http_response.stub(:body).and_return('{"ohai2u":"json_api"}') + @rest.request(:GET, @url, {}).should == {"ohai2u"=>"json_api"} end %w[ HTTPFound HTTPMovedPermanently HTTPSeeOther HTTPUseProxy HTTPTemporaryRedirect HTTPMultipleChoice ].each do |resp_name| - it "should call api_request again on a #{resp_name} response" do + it "should call request again on a #{resp_name} response" do resp_cls = Net.const_get(resp_name) resp_code = Net::HTTPResponse::CODE_TO_OBJ.keys.detect { |k| Net::HTTPResponse::CODE_TO_OBJ[k] == resp_cls } http_response = Net::HTTPFound.new("1.1", resp_code, "bob is somewhere else again") http_response.add_field("location", @url.path) - http_response.stub!(:read_body) + http_response.stub(:read_body) - @http_client.stub!(:request).and_yield(http_response).and_return(http_response) + @http_client.stub(:request).and_yield(http_response).and_return(http_response) - lambda { @rest.api_request(:GET, @url) }.should raise_error(Chef::Exceptions::RedirectLimitExceeded) + lambda { @rest.request(:GET, @url) }.should raise_error(Chef::Exceptions::RedirectLimitExceeded) [:PUT, :POST, :DELETE].each do |method| - lambda { @rest.api_request(method, @url) }.should raise_error(Chef::Exceptions::InvalidRedirect) + lambda { @rest.request(method, @url) }.should raise_error(Chef::Exceptions::InvalidRedirect) end end end it "should return `false` when response is 304 NotModified" do http_response = Net::HTTPNotModified.new("1.1", "304", "it's the same as when you asked 5 minutes ago") - http_response.stub!(:read_body) + http_response.stub(:read_body) - @http_client.stub!(:request).and_yield(http_response).and_return(http_response) + @http_client.stub(:request).and_yield(http_response).and_return(http_response) - @rest.api_request(:GET, @url).should be_false + @rest.request(:GET, @url).should be_false end describe "when the request fails" do @@ -376,12 +390,12 @@ describe Chef::REST do it "should show the JSON error message on an unsuccessful request" do http_response = Net::HTTPServerError.new("1.1", "500", "drooling from inside of mouth") http_response.add_field("content-type", "application/json") - http_response.stub!(:body).and_return('{ "error":[ "Ears get sore!", "Not even four" ] }') - http_response.stub!(:read_body) - @rest.stub!(:sleep) - @http_client.stub!(:request).and_yield(http_response).and_return(http_response) + http_response.stub(:body).and_return('{ "error":[ "Ears get sore!", "Not even four" ] }') + http_response.stub(:read_body) + @rest.stub(:sleep) + @http_client.stub(:request).and_yield(http_response).and_return(http_response) - lambda {@rest.api_request(:GET, @url)}.should raise_error(Net::HTTPFatalError) + lambda {@rest.request(:GET, @url)}.should raise_error(Net::HTTPFatalError) @log_stringio.string.should match(Regexp.escape('INFO: HTTP Request Returned 500 drooling from inside of mouth: Ears get sore!, Not even four')) end @@ -393,23 +407,23 @@ describe Chef::REST do gzipped_body = Zlib::Deflate.deflate(unzipped_body) gzipped_body.force_encoding(Encoding::BINARY) if "strings".respond_to?(:force_encoding) - http_response.stub!(:body).and_return gzipped_body - http_response.stub!(:read_body) - @rest.stub!(:sleep) - @rest.stub!(:http_retry_count).and_return(0) - @http_client.stub!(:request).and_yield(http_response).and_return(http_response) + http_response.stub(:body).and_return gzipped_body + http_response.stub(:read_body) + @rest.stub(:sleep) + @rest.stub(:http_retry_count).and_return(0) + @http_client.stub(:request).and_yield(http_response).and_return(http_response) - lambda {@rest.api_request(:GET, @url)}.should raise_error(Net::HTTPFatalError) + lambda {@rest.request(:GET, @url)}.should raise_error(Net::HTTPFatalError) @log_stringio.string.should match(Regexp.escape('INFO: HTTP Request Returned 500 drooling from inside of mouth: Ears get sore!, Not even four')) end it "should raise an exception on an unsuccessful request" do http_response = Net::HTTPServerError.new("1.1", "500", "drooling from inside of mouth") - http_response.stub!(:body) - http_response.stub!(:read_body) - @rest.stub!(:sleep) - @http_client.stub!(:request).and_yield(http_response).and_return(http_response) - lambda {@rest.api_request(:GET, @url)}.should raise_error(Net::HTTPFatalError) + http_response.stub(:body) + http_response.stub(:read_body) + @rest.stub(:sleep) + @http_client.stub(:request).and_yield(http_response).and_return(http_response) + lambda {@rest.request(:GET, @url)}.should raise_error(Net::HTTPFatalError) end end @@ -419,22 +433,21 @@ describe Chef::REST do context "when streaming downloads to a tempfile" do before do @tempfile = Tempfile.open("chef-rspec-rest_spec-line-#{__LINE__}--") - Tempfile.stub!(:new).with("chef-rest").and_return(@tempfile) + Tempfile.stub(:new).with("chef-rest").and_return(@tempfile) @request_mock = {} - Net::HTTP::Get.stub!(:new).and_return(@request_mock) + Net::HTTP::Get.stub(:new).and_return(@request_mock) @http_response = Net::HTTPSuccess.new("1.1",200, "it-works") - @http_response.stub!(:read_body) - @http_client.stub!(:request).and_yield(@http_response).and_return(@http_response) + @http_response.stub(:read_body) + @http_client.stub(:request).and_yield(@http_response).and_return(@http_response) end after do - @tempfile.rspec_reset @tempfile.close! end it " build a new HTTP GET request without the application/json accept header" do - expected_headers = {'X-Chef-Version' => Chef::VERSION, 'Accept-Encoding' => Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE} + expected_headers = {'Accept' => "*/*", 'X-Chef-Version' => Chef::VERSION, 'Accept-Encoding' => Chef::REST::RESTRequest::ENCODING_GZIP_DEFLATE} Net::HTTP::Get.should_receive(:new).with("/?foo=bar", expected_headers).and_return(@request_mock) @rest.streaming_request(@url, {}) end @@ -444,7 +457,7 @@ describe Chef::REST do end it "writes the response body to a tempfile" do - @http_response.stub!(:read_body).and_yield("real").and_yield("ultimate").and_yield("power") + @http_response.stub(:read_body).and_yield("real").and_yield("ultimate").and_yield("power") @rest.streaming_request(@url, {}) IO.read(@tempfile.path).chomp.should == "realultimatepower" end @@ -455,7 +468,7 @@ describe Chef::REST do end it "yields the tempfile containing the streamed response body and then unlinks it when given a block" do - @http_response.stub!(:read_body).and_yield("real").and_yield("ultimate").and_yield("power") + @http_response.stub(:read_body).and_yield("real").and_yield("ultimate").and_yield("power") tempfile_path = nil @rest.streaming_request(@url, {}) do |tempfile| tempfile_path = tempfile.path @@ -467,18 +480,18 @@ describe Chef::REST do it "does not raise a divide by zero exception if the content's actual size is 0" do @http_response.add_field('Content-Length', "5") - @http_response.stub!(:read_body).and_yield('') - lambda { @rest.streaming_request(@url, {}) }.should_not raise_error(ZeroDivisionError) + @http_response.stub(:read_body).and_yield('') + lambda { @rest.streaming_request(@url, {}) }.should_not raise_error end it "does not raise a divide by zero exception when the Content-Length is 0" do @http_response.add_field('Content-Length', "0") - @http_response.stub!(:read_body).and_yield("ninja") - lambda { @rest.streaming_request(@url, {}) }.should_not raise_error(ZeroDivisionError) + @http_response.stub(:read_body).and_yield("ninja") + lambda { @rest.streaming_request(@url, {}) }.should_not raise_error end it "fetches a file and yields the tempfile it is streamed to" do - @http_response.stub!(:read_body).and_yield("real").and_yield("ultimate").and_yield("power") + @http_response.stub(:read_body).and_yield("real").and_yield("ultimate").and_yield("power") tempfile_path = nil @rest.fetch("cookbooks/a_cookbook") do |tempfile| tempfile_path = tempfile.path @@ -490,34 +503,32 @@ describe Chef::REST do it "closes and unlinks the tempfile if there is an error while streaming the content to the tempfile" do path = @tempfile.path path.should_not be_nil - @tempfile.stub!(:write).and_raise(IOError) + @tempfile.stub(:write).and_raise(IOError) @rest.fetch("cookbooks/a_cookbook") {|tmpfile| "shouldn't get here"} File.exists?(path).should be_false end it "closes and unlinks the tempfile when the response is a redirect" do - Tempfile.rspec_reset - tempfile = mock("die", :path => "/tmp/ragefist", :close => true, :binmode => true) - tempfile.should_receive(:close!).at_least(2).times - Tempfile.stub!(:new).with("chef-rest").and_return(tempfile) + tempfile = double("A tempfile", :path => "/tmp/ragefist", :close => true, :binmode => true) + tempfile.should_receive(:close!).at_least(1).times + Tempfile.stub(:new).with("chef-rest").and_return(tempfile) - http_response = Net::HTTPFound.new("1.1", "302", "bob is taking care of that one for me today") - http_response.add_field("location", @url.path) - http_response.stub!(:read_body) + redirect = Net::HTTPFound.new("1.1", "302", "bob is taking care of that one for me today") + redirect.add_field("location", @url.path) + redirect.stub(:read_body) - @http_client.stub!(:request).and_yield(http_response).and_yield(@http_response).and_return(http_response, @http_response) + @http_client.should_receive(:request).and_yield(redirect).and_return(redirect) + @http_client.should_receive(:request).and_yield(@http_response).and_return(@http_response) @rest.fetch("cookbooks/a_cookbook") {|tmpfile| "shouldn't get here"} end it "passes the original block to the redirected request" do - Tempfile.rspec_reset - http_response = Net::HTTPFound.new("1.1", "302", "bob is taking care of that one for me today") http_response.add_field("location","/that-thing-is-here-now") - http_response.stub!(:read_body) + http_response.stub(:read_body) block_called = false - @http_client.stub!(:request).and_yield(@http_response).and_return(http_response, @http_response) + @http_client.stub(:request).and_yield(@http_response).and_return(http_response, @http_response) @rest.fetch("cookbooks/a_cookbook") do |tmpfile| block_called = true end @@ -546,9 +557,9 @@ describe Chef::REST do redirected.call unless total_redirects >= 9 end end - lambda {redirected.call}.should_not raise_error(Chef::Exceptions::RedirectLimitExceeded) + lambda {redirected.call}.should_not raise_error total_redirects = 0 - lambda {redirected.call}.should_not raise_error(Chef::Exceptions::RedirectLimitExceeded) + lambda {redirected.call}.should_not raise_error end it "does not sign the redirected request when sign_on_redirect is false" do @@ -572,7 +583,7 @@ describe Chef::REST do redirected.call unless total_redirects >= 9 end end - lambda {redirected.call}.should_not raise_error(Chef::Exceptions::RedirectLimitExceeded) + lambda {redirected.call}.should_not raise_error total_redirects = 0 @rest.redirect_limit = 3 diff --git a/spec/unit/role_spec.rb b/spec/unit/role_spec.rb index 764d586903..f36b7f13bd 100644 --- a/spec/unit/role_spec.rb +++ b/spec/unit/role_spec.rb @@ -244,6 +244,11 @@ describe Chef::Role do end end + ROLE_DSL=<<-EOR +name "ceiling_cat" +description "like Aliens, but furry" +EOR + describe "when loading from disk" do it "should return a Chef::Role object from JSON" do File.should_receive(:exists?).with(File.join(Chef::Config[:role_path], 'lolcat.json')).exactly(1).times.and_return(true) @@ -256,10 +261,6 @@ describe Chef::Role do File.should_receive(:exists?).with(File.join(Chef::Config[:role_path], 'lolcat.json')).exactly(1).times.and_return(false) File.should_receive(:exists?).with(File.join(Chef::Config[:role_path], 'lolcat.rb')).exactly(2).times.and_return(true) File.should_receive(:readable?).with(File.join(Chef::Config[:role_path], 'lolcat.rb')).exactly(1).times.and_return(true) - ROLE_DSL=<<-EOR -name "ceiling_cat" -description "like Aliens, but furry" -EOR IO.should_receive(:read).with(File.join(Chef::Config[:role_path], 'lolcat.rb')).and_return(ROLE_DSL) @role.should be_a_kind_of(Chef::Role) @role.class.from_disk("lolcat") @@ -271,5 +272,57 @@ EOR lambda {@role.class.from_disk("lolcat")}.should raise_error(Chef::Exceptions::RoleNotFound) end end + + describe "when loading from disk and role_path is an array" do + + before(:each) do + Chef::Config[:role_path] = ['/path1', '/path/path2'] + end + + it "should return a Chef::Role object from JSON" do + File.should_receive(:exists?).with(File.join('/path1', 'lolcat.json')).exactly(1).times.and_return(true) + IO.should_receive(:read).with(File.join('/path1', 'lolcat.json')).and_return('{"name": "ceiling_cat", "json_class": "Chef::Role" }') + @role.should be_a_kind_of(Chef::Role) + @role.class.from_disk("lolcat") + end + + it "should return a Chef::Role object from JSON when role is in the second path" do + File.should_receive(:exists?).with(File.join('/path1', 'lolcat.json')).exactly(1).times.and_return(false) + File.should_receive(:exists?).with(File.join('/path1', 'lolcat.rb')).exactly(1).times.and_return(false) + File.should_receive(:exists?).with(File.join('/path/path2', 'lolcat.json')).exactly(1).times.and_return(true) + IO.should_receive(:read).with(File.join('/path/path2', 'lolcat.json')).and_return('{"name": "ceiling_cat", "json_class": "Chef::Role" }') + @role.should be_a_kind_of(Chef::Role) + @role.class.from_disk("lolcat") + end + + it "should return a Chef::Role object from a Ruby DSL" do + File.should_receive(:exists?).with(File.join('/path1', 'lolcat.json')).exactly(1).times.and_return(false) + File.should_receive(:exists?).with(File.join('/path1', 'lolcat.rb')).exactly(2).times.and_return(true) + File.should_receive(:readable?).with(File.join('/path1', 'lolcat.rb')).exactly(1).times.and_return(true) + IO.should_receive(:read).with(File.join('/path1', 'lolcat.rb')).and_return(ROLE_DSL) + @role.should be_a_kind_of(Chef::Role) + @role.class.from_disk("lolcat") + end + + it "should return a Chef::Role object from a Ruby DSL when role is in the second path" do + File.should_receive(:exists?).with(File.join('/path1', 'lolcat.json')).exactly(1).times.and_return(false) + File.should_receive(:exists?).with(File.join('/path1', 'lolcat.rb')).exactly(1).times.and_return(false) + File.should_receive(:exists?).with(File.join('/path/path2', 'lolcat.json')).exactly(1).times.and_return(false) + File.should_receive(:exists?).with(File.join('/path/path2', 'lolcat.rb')).exactly(2).times.and_return(true) + File.should_receive(:readable?).with(File.join('/path/path2', 'lolcat.rb')).exactly(1).times.and_return(true) + IO.should_receive(:read).with(File.join('/path/path2', 'lolcat.rb')).and_return(ROLE_DSL) + @role.should be_a_kind_of(Chef::Role) + @role.class.from_disk("lolcat") + end + + it "should raise an exception if the file does not exist" do + File.should_receive(:exists?).with(File.join('/path1', 'lolcat.json')).exactly(1).times.and_return(false) + File.should_receive(:exists?).with(File.join('/path1', 'lolcat.rb')).exactly(1).times.and_return(false) + File.should_receive(:exists?).with(File.join('/path/path2', 'lolcat.json')).exactly(1).times.and_return(false) + File.should_receive(:exists?).with(File.join('/path/path2', 'lolcat.rb')).exactly(1).times.and_return(false) + lambda {@role.class.from_disk("lolcat")}.should raise_error(Chef::Exceptions::RoleNotFound) + end + + end end diff --git a/spec/unit/run_context/cookbook_compiler_spec.rb b/spec/unit/run_context/cookbook_compiler_spec.rb index 0c5e568a13..52f4772206 100644 --- a/spec/unit/run_context/cookbook_compiler_spec.rb +++ b/spec/unit/run_context/cookbook_compiler_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -17,23 +17,7 @@ # require 'spec_helper' - -# Keeps track of what file got loaded in what order. -module LibraryLoadOrder - extend self - - def load_order - @load_order ||= [] - end - - def reset! - @load_order = nil - end - - def record(file) - load_order << file - end -end +require 'support/lib/library_load_order' # These tests rely on fixture data in spec/data/run_context/cookbooks. # @@ -178,7 +162,7 @@ describe Chef::RunContext::CookbookCompiler do # Tests for this behavior are in RunContext's tests end - describe "listing cookbook order" do + describe "listing cookbook order" do it "should return an array of cookbook names as symbols without duplicates" do node.run_list("test-with-circular-deps::default", "circular-dep1::default", "circular-dep2::default") diff --git a/spec/unit/run_context_spec.rb b/spec/unit/run_context_spec.rb index 51fa0e81f9..8063dffc77 100644 --- a/spec/unit/run_context_spec.rb +++ b/spec/unit/run_context_spec.rb @@ -8,9 +8,9 @@ # 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. @@ -19,6 +19,7 @@ # require 'spec_helper' +require 'support/lib/library_load_order' Chef::Log.level = :debug @@ -42,7 +43,7 @@ describe Chef::RunContext do @run_context.node.should == @node end - describe "after loading the cookbooks" do + describe "loading cookbooks for a run list" do before do @run_context.load(@node.run_list.expand('_default')) end @@ -73,6 +74,46 @@ describe Chef::RunContext do @node.should_not_receive(:from_file) @node.include_attribute("test::george") end + + + end + + describe "querying the contents of cookbooks" do + before do + @chef_repo_path = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) + cl = Chef::CookbookLoader.new(@chef_repo_path) + cl.load_cookbooks + @cookbook_collection = Chef::CookbookCollection.new(cl) + @node = Chef::Node.new + @node.set[:platform] = "ubuntu" + @node.set[:platform_version] = "13.04" + @node.name("testing") + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events) + end + + + it "queries whether a given cookbook has a specific template" do + @run_context.should have_template_in_cookbook("openldap", "test.erb") + @run_context.should_not have_template_in_cookbook("openldap", "missing.erb") + end + + it "errors when querying for a template in a not-available cookbook" do + expect do + @run_context.has_template_in_cookbook?("no-such-cookbook", "foo.erb") + end.to raise_error(Chef::Exceptions::CookbookNotFound) + end + + it "queries whether a given cookbook has a specific cookbook_file" do + @run_context.should have_cookbook_file_in_cookbook("java", "java.response") + @run_context.should_not have_cookbook_file_in_cookbook("java", "missing.txt") + end + + it "errors when querying for a cookbook_file in a not-available cookbook" do + expect do + @run_context.has_cookbook_file_in_cookbook?("no-such-cookbook", "foo.txt") + end.to raise_error(Chef::Exceptions::CookbookNotFound) + end end end diff --git a/spec/unit/run_list/run_list_item_spec.rb b/spec/unit/run_list/run_list_item_spec.rb index 62a17aa761..6b9de713da 100644 --- a/spec/unit/run_list/run_list_item_spec.rb +++ b/spec/unit/run_list/run_list_item_spec.rb @@ -101,7 +101,7 @@ describe Chef::RunList::RunListItem do item2 = Chef::RunList::RunListItem.new('recipe[lobsterragefist]') item1.should_not == item2 end - + it "is not equal to another run list item with the same name and type but different version" do item1 = Chef::RunList::RunListItem.new('recipe[lrf,0.1.0]') item2 = Chef::RunList::RunListItem.new('recipe[lrf,0.2.0]') diff --git a/spec/unit/run_lock_spec.rb b/spec/unit/run_lock_spec.rb index 4e62b110b9..de302dc533 100644 --- a/spec/unit/run_lock_spec.rb +++ b/spec/unit/run_lock_spec.rb @@ -20,14 +20,17 @@ require 'chef/client' describe Chef::RunLock do + default_pid_location = windows? ? 'C:\chef\cache\chef-client-running.pid' : '/var/chef/cache/chef-client-running.pid' + describe "when first created" do it "locates the lockfile in the file cache path by default" do - run_lock = Chef::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => nil) - run_lock.runlock_file.should == "/var/chef/cache/chef-client-running.pid" + run_lock = Chef::RunLock.new(Chef::Config.lockfile) + run_lock.runlock_file.should == default_pid_location end it "locates the lockfile in the user-configured path when set" do - run_lock = Chef::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => "/tmp/chef-client-running.pid") + Chef::Config.lockfile = "/tmp/chef-client-running.pid" + run_lock = Chef::RunLock.new(Chef::Config.lockfile) run_lock.runlock_file.should == "/tmp/chef-client-running.pid" end end diff --git a/spec/unit/scan_access_control_spec.rb b/spec/unit/scan_access_control_spec.rb index c83a552626..3cfecfaa35 100644 --- a/spec/unit/scan_access_control_spec.rb +++ b/spec/unit/scan_access_control_spec.rb @@ -69,7 +69,7 @@ describe Chef::ScanAccessControl do it "sets the group of the current resource to the current group as a String" do @current_resource.group.should == Etc.getgrgid(0).name end - + it "sets the owner of the current resource to the current owner as a String" do @current_resource.user.should == "root" end @@ -79,7 +79,7 @@ describe Chef::ScanAccessControl do it "sets the group of the current resource to the current group as a String" do @current_resource.group.should == 0 end - + it "sets the owner of the current resource to the current owner as a String" do @current_resource.user.should == 0 end diff --git a/spec/unit/search/query_spec.rb b/spec/unit/search/query_spec.rb index e32bed697c..3f41c142ee 100644 --- a/spec/unit/search/query_spec.rb +++ b/spec/unit/search/query_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -19,7 +19,7 @@ require 'spec_helper' require 'chef/search/query' -describe Chef::Search::Query do +describe Chef::Search::Query do before(:each) do @rest = mock("Chef::REST") Chef::REST.stub!(:new).and_return(@rest) diff --git a/spec/unit/util/backup_spec.rb b/spec/unit/util/backup_spec.rb index f0e182e181..c49694f924 100644 --- a/spec/unit/util/backup_spec.rb +++ b/spec/unit/util/backup_spec.rb @@ -21,13 +21,6 @@ require 'spec_helper' require 'tmpdir' describe Chef::Util::Backup do - before(:all) do - @original_config = Chef::Config.configuration - end - - after(:all) do - Chef::Config.configuration.replace(@original_config) - end let (:tempfile) do Tempfile.new("chef-util-backup-spec-test") @@ -114,15 +107,15 @@ describe Chef::Util::Backup do describe "backup_filename" do it "should return a timestamped path" do @backup.should_receive(:path).and_return('/a/b/c.txt') - @backup.send(:backup_filename).should =~ %r|^/a/b/c.txt.chef-\d{14}$| + @backup.send(:backup_filename).should =~ %r|^/a/b/c.txt.chef-\d{14}.\d{6}$| end it "should strip the drive letter off for windows" do @backup.should_receive(:path).and_return('c:\a\b\c.txt') - @backup.send(:backup_filename).should =~ %r|^\\a\\b\\c.txt.chef-\d{14}$| + @backup.send(:backup_filename).should =~ %r|^\\a\\b\\c.txt.chef-\d{14}.\d{6}$| end it "should strip the drive letter off for windows (with forwardslashes)" do @backup.should_receive(:path).and_return('c:/a/b/c.txt') - @backup.send(:backup_filename).should =~ %r|^/a/b/c.txt.chef-\d{14}$| + @backup.send(:backup_filename).should =~ %r|^/a/b/c.txt.chef-\d{14}.\d{6}$| end end @@ -130,19 +123,19 @@ describe Chef::Util::Backup do it "uses the file's directory when Chef::Config[:file_backup_path] is nil" do @backup.should_receive(:path).and_return('/a/b/c.txt') Chef::Config[:file_backup_path] = nil - @backup.send(:backup_path).should =~ %r|^/a/b/c.txt.chef-\d{14}$| + @backup.send(:backup_path).should =~ %r|^/a/b/c.txt.chef-\d{14}.\d{6}$| end it "uses the configured Chef::Config[:file_backup_path]" do @backup.should_receive(:path).and_return('/a/b/c.txt') Chef::Config[:file_backup_path] = '/backupdir' - @backup.send(:backup_path).should =~ %r|^/backupdir[\\/]+a/b/c.txt.chef-\d{14}$| + @backup.send(:backup_path).should =~ %r|^/backupdir[\\/]+a/b/c.txt.chef-\d{14}.\d{6}$| end it "uses the configured Chef::Config[:file_backup_path] and strips the drive on windows" do @backup.should_receive(:path).and_return('c:\\a\\b\\c.txt') Chef::Config[:file_backup_path] = 'c:\backupdir' - @backup.send(:backup_path).should =~ %r|^c:\\backupdir[\\/]+a\\b\\c.txt.chef-\d{14}$| + @backup.send(:backup_path).should =~ %r|^c:\\backupdir[\\/]+a\\b\\c.txt.chef-\d{14}.\d{6}$| end end diff --git a/spec/unit/util/diff_spec.rb b/spec/unit/util/diff_spec.rb index 2dadb5be56..0e3bc0a0d7 100644 --- a/spec/unit/util/diff_spec.rb +++ b/spec/unit/util/diff_spec.rb @@ -21,14 +21,6 @@ require 'spec_helper' require 'tmpdir' describe Chef::Util::Diff, :uses_diff => true do - before(:all) do - @original_config = Chef::Config.hash_dup - end - - after(:all) do - Chef::Config.configuration = @original_config if @original_config - end - let!(:old_tempfile) { Tempfile.new("chef-util-diff-spec") } let!(:new_tempfile) { Tempfile.new("chef-util-diff-spec") } let!(:old_file) { old_tempfile.path } @@ -393,37 +385,6 @@ describe Chef::Util::Diff, :uses_diff => true do end end - describe "when errors are thrown from shell_out" do - before do - differ.stub!(:shell_out).and_raise('boom') - differ.diff(old_file, new_file) - end - - it "calling for_output should return the error message" do - expect(differ.for_output).to eql(["Could not determine diff. Error: boom"]) - end - - it "calling for_reporting should be nil" do - expect(differ.for_reporting).to be_nil - end - end - - describe "when shell_out returns stderr output" do - before do - @result = mock('result', :stdout => "", :stderr => "boom") - differ.stub!(:shell_out).and_return(@result) - differ.diff(old_file, new_file) - end - - it "calling for_output should return the error message" do - expect(differ.for_output).to eql(["Could not determine diff. Error: boom"]) - end - - it "calling for_reporting should be nil" do - expect(differ.for_reporting).to be_nil - end - end - describe "when checking if files are binary or text" do it "should identify zero-length files as text" do diff --git a/spec/unit/version/platform_spec.rb b/spec/unit/version/platform_spec.rb index 6245800f9d..8b5b3503dc 100644 --- a/spec/unit/version/platform_spec.rb +++ b/spec/unit/version/platform_spec.rb @@ -5,9 +5,9 @@ # 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. @@ -28,7 +28,7 @@ describe Chef::Version::Platform do it "should transform 1 to 1.0.0" do Chef::Version::Platform.new("1").to_s.should == "1.0.0" end - + describe "when creating valid Versions" do good_versions = %w(1 1.2 1.2.3 1000.80.50000 0.300.25 001.02.00003) good_versions.each do |v| diff --git a/spec/unit/version_class_spec.rb b/spec/unit/version_class_spec.rb index 285588b031..b0fcfbb3fb 100644 --- a/spec/unit/version_class_spec.rb +++ b/spec/unit/version_class_spec.rb @@ -6,9 +6,9 @@ # 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. @@ -28,12 +28,12 @@ describe Chef::Version do @v0.to_s.should == "0.0.0" @v123.to_s.should == "1.2.3" end - + it "should make a round trip with its string representation" do a = Chef::Version.new(@v123.to_s) a.should == @v123 end - + it "should transform 1.2 to 1.2.0" do Chef::Version.new("1.2").to_s.should == "1.2.0" end @@ -118,7 +118,7 @@ describe Chef::Version do end describe "comparison examples" do - [ + [ [ "0.0.0", :>, "0.0.0", false ], [ "0.0.0", :>=, "0.0.0", true ], [ "0.0.0", :==, "0.0.0", true ], diff --git a/spec/unit/version_constraint/platform_spec.rb b/spec/unit/version_constraint/platform_spec.rb index a7749102f0..a3599aeb96 100644 --- a/spec/unit/version_constraint/platform_spec.rb +++ b/spec/unit/version_constraint/platform_spec.rb @@ -5,9 +5,9 @@ # 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. diff --git a/spec/unit/windows_service_spec.rb b/spec/unit/windows_service_spec.rb new file mode 100644 index 0000000000..ba3d2980df --- /dev/null +++ b/spec/unit/windows_service_spec.rb @@ -0,0 +1,54 @@ +# +# Author:: Mukta Aphale (<mukta.aphale@clogeny.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' +if Chef::Platform.windows? + require 'chef/application/windows_service' +end + +describe "Chef::Application::WindowsService", :windows_only do + let (:instance) {Chef::Application::WindowsService.new} + let (:shell_out_result) {Object.new} + let (:tempfile) {Tempfile.new "log_file"} + before do + instance.stub(:parse_options) + shell_out_result.stub(:stdout) + shell_out_result.stub(:stderr) + end + it "runs chef-client in new process" do + instance.should_receive(:configure_chef).twice + instance.service_init + instance.should_receive(:run_chef_client).and_call_original + instance.should_receive(:shell_out).and_return(shell_out_result) + instance.stub(:running?).and_return(true, false) + instance.instance_variable_get(:@service_signal).stub(:wait) + instance.stub(:state).and_return(4) + instance.service_main + end + it "passes config params to new process" do + Chef::Config.merge!({:log_location => tempfile.path, :config_file => "test_config_file", :log_level => :info}) + instance.should_receive(:configure_chef).twice + instance.service_init + instance.stub(:running?).and_return(true, false) + instance.instance_variable_get(:@service_signal).stub(:wait) + instance.stub(:state).and_return(4) + instance.should_receive(:run_chef_client).and_call_original + instance.should_receive(:shell_out).with("chef-client --no-fork -c test_config_file -L #{tempfile.path}").and_return(shell_out_result) + instance.service_main + tempfile.unlink + end +end |