summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaire McQuin <claire@getchef.com>2014-10-08 14:00:50 -0700
committerClaire McQuin <claire@getchef.com>2014-10-08 14:00:50 -0700
commit5c424b455b67c01e79d7e3b24a403d3f85f74677 (patch)
tree367e26aa789d786ceabe24c2a6fef45e72a48e6f
parent063e4a53b062ba3090ebf2187c6513030075a325 (diff)
parent7f236885e421954ba39e6daf0d9da30b16b04040 (diff)
downloadchef-5c424b455b67c01e79d7e3b24a403d3f85f74677.tar.gz
Merge branch 'master' into mcquin/Issue-1910-lwrp
-rw-r--r--CHANGELOG.md4
-rw-r--r--CONTRIBUTING.md9
-rw-r--r--DOC_CHANGES.md55
-rw-r--r--RELEASE_NOTES.md35
-rw-r--r--kitchen-tests/test/fixtures/serverspec_helper.rb79
-rw-r--r--kitchen-tests/test/integration/webapp/serverspec/localhost/default_spec.rb6
-rw-r--r--lib/chef/client.rb2
-rw-r--r--lib/chef/cookbook_version.rb10
-rw-r--r--lib/chef/http.rb31
-rw-r--r--lib/chef/mixin/homebrew_owner.rb58
-rw-r--r--lib/chef/mixin/homebrew_user.rb68
-rw-r--r--lib/chef/provider/dsc_script.rb34
-rw-r--r--lib/chef/provider/git.rb5
-rw-r--r--lib/chef/provider/package/freebsd/pkgng.rb2
-rw-r--r--lib/chef/provider/package/homebrew.rb12
-rw-r--r--lib/chef/resource/dsc_script.rb18
-rw-r--r--lib/chef/resource/homebrew_package.rb11
-rw-r--r--spec/functional/resource/group_spec.rb11
-rw-r--r--spec/unit/mixin/homebrew_owner_spec.rb65
-rw-r--r--spec/unit/mixin/homebrew_user_spec.rb100
-rw-r--r--spec/unit/provider/dsc_script_spec.rb239
-rw-r--r--spec/unit/provider/git_spec.rb15
-rw-r--r--spec/unit/provider/package/freebsd/pkgng_spec.rb2
-rw-r--r--spec/unit/provider/package/homebrew_spec.rb14
-rw-r--r--spec/unit/resource/dsc_script_spec.rb29
-rw-r--r--spec/unit/resource/homebrew_package_spec.rb21
-rw-r--r--spec/unit/rest_spec.rb5
27 files changed, 566 insertions, 374 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b7a2f352b..452b1d331b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,7 @@
## Unreleased: 12.0.0
+* [**Jesse Hu**](https://github.com/jessehu):
+ retry on HTTP 50X Error when calling Chef REST API
* [**Nolan Davidson**](https://github.com/nsdavidson):
The chef-apply command now prints usage information when called without arguments
* [**Kazuki Saito**](https://github.com/sakazuki):
@@ -72,6 +74,8 @@
Improve the regex for /etc/rc.conf for the FreeBSD service provider
* [**Stanislav Bogatyrev**](https://github.com/realloc):
Fetch recipe_url before loading json_attribs in chef-solo (CHEF-5075)
+* [**Mal Graty**](https://github.com/mal): Workaround for a breaking change in git's shallow-clone behavior. (Issue 1563)
+* [**Dave Eddy**](https://github.com/bahamas10): Fix version detection in FreeBSD pkgng provider. (PR 1980)
### Chef Contributions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e6e9a26cad..f8618ad381 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -159,6 +159,15 @@ In order to decrease the back and forth an issues and help us get to the bottom
[What actually happens after the reproduction steps?]
```
+### Useful Github Queries
+
+Contributions go through a review process to improve code quality and avoid regressions. Managing a large number of contributions requires a workflow to provide queues for work such as triage, code review, and merging. A semi-formal process has evolved over the life of the project. Chef maintains this process pending community development and acceptance of an [RFC](https://github.com/opscode/chef-rfc). These queries will help track contributions through this process:
+
+* [Issues that are not assigned to a team](https://github.com/opscode/chef/issues?q=is%3Aopen+-label%3AAIX+-label%3ABSD+-label%3Awindows+-label%3A%22Chef+Core%22++-label%3A%22Dev+Tools%22+-label%3AUbuntu+-label%3A%22Enterprise+Linux%22+-label%3A%22Ready+For+Merge%22+-label%3AMac+-label%3ASolaris+)
+* [Untriaged Issues](https://github.com/opscode/chef/issues?q=is%3Aopen+is%3Aissue+-label%3ABug+-label%3AEnhancement+-label%3A%22Tech+Cleanup%22+-label%3A%22Ready+For+Merge%22)
+* [PRs to be Reviewed](https://github.com/opscode/chef/labels/Pending%20Maintainer%20Review)
+* [Suitable for First Contribution](https://github.com/opscode/chef/labels/Easy)
+
## <a name="release"></a> Chef Release Cycles
Our primary shipping vehicle is operating system specific packages that includes
diff --git a/DOC_CHANGES.md b/DOC_CHANGES.md
index 1c16377ccd..ceccb77cd0 100644
--- a/DOC_CHANGES.md
+++ b/DOC_CHANGES.md
@@ -467,3 +467,58 @@ PathHelper = Chef::Util::PathHelper
Dir.glob(File.join(PathHelper.escape_glob(path), "*")) # ["#{path}\\apache2", "#{path}\\apt", ...]
Dir[PathHelper.escape_glob(path) + "/*"] # ["#{path}\\apache2", "#{path}\\apt", ...]
```
+
+## Mac OS X default package provider is now Homebrew
+
+Per [Chef RFC 016](https://github.com/opscode/chef-rfc/blob/master/rfc016-homebrew-osx-package-provider.md), the default provider for the `package` resource on Mac OS X is now [Homebrew](http://brew.sh). The [homebrew cookbook's](https://supermarket.getchef.com/cookbooks/homebrew) default recipe, or some other method is still required for getting homebrew installed on the system. The cookbook won't be strictly required just to install packages from homebrew on OS X, though. To use this, simply use the `package` resource, or the `homebrew_package` shortcut resource:
+
+```ruby
+package 'emacs'
+```
+
+Or,
+
+```ruby
+homebrew_package 'emacs'
+```
+
+The macports provider will still be available, and can be used with the shortcut resource, or by using the `provider` attribute:
+
+```ruby
+macports_package 'emacs'
+```
+
+Or,
+
+```ruby
+package 'emacs' do
+ provider Chef::Provider::Package::Macports
+end
+```
+
+### Providing `homebrew_user`
+
+Homebrew recommends being ran as a non-root user, whereas Chef recommends being ran with root privileges. The
+`homebrew_package` provider has logic to try and determine which user to install Homebrew packages as.
+
+By default, the `homebrew_package` provider will try to execute the homebrew command as the owner of the `/usr/local/bin/brew`
+executable. If that executable does not exist, Chef will try to find it by executing `which brew`. If that cannot be
+found, Chef then errors. The Homebrew recommendation is the default install, which will place the executable at
+`/usr/local/bin/brew` owned by a non-root user.
+
+You can circumvent this by providing the `homebrew_package` a `homebrew_user` attribute, like:
+
+```ruby
+# provided as a uid
+homebrew_package 'emacs' do
+ homebrew_user 1001
+end
+
+# provided as a string
+homebrew_package 'vim' do
+ homebrew_user 'user1'
+end
+```
+
+Chef will then execute the Homebrew command as that user. The `homebrew_user` attribute can only be provided to the
+`homebrew_package` resource, not the `package` resource. \ No newline at end of file
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 4909414b95..a6d1a65f51 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -94,6 +94,41 @@ package 'emacs' do
end
```
+### Providing `homebrew_user`
+
+Homebrew recommends being ran as a non-root user, whereas Chef recommends being ran with root privileges. The
+`homebrew_package` provider has logic to try and determine which user to install Homebrew packages as.
+
+By default, the `homebrew_package` provider will try to execute the homebrew command as the owner of the `/usr/local/bin/brew`
+executable. If that executable does not exist, Chef will try to find it by executing `which brew`. If that cannot be
+found, Chef then errors. The Homebrew recommendation is the default install, which will place the executable at
+`/usr/local/bin/brew` owned by a non-root user.
+
+You can circumvent this by providing the `homebrew_package` a `homebrew_user` attribute, like:
+
+```ruby
+# provided as a uid
+homebrew_package 'emacs' do
+ homebrew_user 1001
+end
+
+# provided as a string
+homebrew_package 'vim' do
+ homebrew_user 'user1'
+end
+```
+
+Chef will then execute the Homebrew command as that user. The `homebrew_user` attribute can only be provided to the
+`homebrew_package` resource, not the `package` resource.
+
+## DSCL user provider now supports Mac OS X 10.7 and above.
+
+DSCL user provider in Chef has supported setting passwords only on Mac OS X 10.6. In this release, Mac OS X versions 10.7 and above are now supported. Support for Mac OS X 10.6 is dropped from the dscl provider since this version is EOLed by Apple.
+
+In order to support configuring passwords for the users using shadow hashes two new attributes `salt` & `iterations` are added to the user resource. These attributes are required to make the new [SALTED-SHA512-PBKDF2](http://en.wikipedia.org/wiki/PBKDF2) style shadow hashes used in Mac OS X versions 10.8 and above.
+
+User resource on Mac supports setting password both using plain-text password or using the shadow hash. You can simply set the `password` attribute to the plain text password to configure the password for the user. However this is not ideal since including plain text passwords in cookbooks (even if they are private) is not a good idea. In order to set passwords using shadow hash you can follow the instructions below based on your Mac OS X version.
+
### Mac OS X 10.7
10.7 calculates the password hash using **SALTED-SHA512**. Stored shadow hash length is 68 bytes; first 4 bytes being salt and the next 64 bytes being the shadow hash itself. You can use below code in order to calculate password hashes to be used in `password` attribute on Mac OS X 10.7:
diff --git a/kitchen-tests/test/fixtures/serverspec_helper.rb b/kitchen-tests/test/fixtures/serverspec_helper.rb
index 3a2c05f9cf..6e6d71e79b 100644
--- a/kitchen-tests/test/fixtures/serverspec_helper.rb
+++ b/kitchen-tests/test/fixtures/serverspec_helper.rb
@@ -5,70 +5,27 @@
require 'serverspec'
require 'json'
-include SpecInfra::Helper::Exec
-include SpecInfra::Helper::DetectOS
-include SpecInfra::Helper::Properties
+set :backend, :exec
-# http://serverspec.org/advanced_tips.html
-# os[:family] # RedHat, Ubuntu, Debian and so on
-# os[:release] # OS release version (cleaned up in v2)
-# os[:arch]
-osmapping = {
-# 'RedHat' => {
-# :platform_family => 'rhel',
-# :platform => 'centos',
-# :platform_version => '6.5'
-# },
-# 'RedHat7' => {
-# :platform_family => 'rhel',
-# :platform => 'centos',
-# :platform_version => '7.0'
-# },
-# 'Fedora' => {
-# :platform_family => 'rhel',
-# :platform => 'fedora',
-# :platform_version => '20'
-# },
- 'Ubuntu' => {
- :platform_family => 'debian',
- :platform => 'ubuntu',
- :platform_version => '12.04'
- }
-# 'Debian' => {
-# :platform_family => 'debian',
-# :platform => 'debian',
-# :platform_version => '7.4'
-# },
-# 'FreeBSD' => {
-# :platform_family => 'freebsd',
-# :platform => 'freebsd',
-# :platform_version => '9.2'
-# }
-}
+include Specinfra::Helper::Properties
-def ohai_platform(os, osmapping)
- puts "serverspec os detected as: #{os[:family]} #{os[:release]} [#{os[:arch]}]"
- ohaistub = {}
- ohaistub[:platform_family] = osmapping[os[:family]][:platform_family]
- ohaistub[:platform] = osmapping[os[:family]][:platform]
- if os[:release]
- ohaistub[:platform_version] = os[:release]
- else
- ohaistub[:platform_version] = osmapping[os[:family]][:platform_version]
+require 'pp'
+pp os
+
+def load_nodestub
+ case os[:family]
+ when 'ubuntu', 'debian'
+ platform = os[:family]
+ platform_version = os[:release]
+ when 'redhat'
+ platform = 'centos'
+ platform_version = os[:release].to_i
end
- ohaistub
+ JSON.parse(IO.read("#{ENV['BUSSER_ROOT']}/../kitchen/data/platforms/#{platform}/#{platform_version}.json"), :symbolize_names => true)
end
-def load_nodestub(ohai)
- puts "loading #{ohai[:platform]}/#{ohai[:platform_version]}"
- JSON.parse(IO.read("#{ENV['BUSSER_ROOT']}/../kitchen/data/platforms/#{ohai[:platform]}/#{ohai[:platform_version]}.json"), :symbolize_names => true)
-end
+# centos-59 doesn't have /sbin in the default path,
+# so we must ensure it's on serverspec's path
+set :path, '$PATH:/sbin'
-RSpec.configure do |config|
- set_property load_nodestub(ohai_platform(backend.check_os, osmapping))
- config.before(:all) do
- # centos-59 doesn't have /sbin in the default path,
- # so we must ensure it's on serverspec's path
- config.path = '/sbin'
- end
-end
+set_property load_nodestub
diff --git a/kitchen-tests/test/integration/webapp/serverspec/localhost/default_spec.rb b/kitchen-tests/test/integration/webapp/serverspec/localhost/default_spec.rb
index f8e83829a4..05da3ff337 100644
--- a/kitchen-tests/test/integration/webapp/serverspec/localhost/default_spec.rb
+++ b/kitchen-tests/test/integration/webapp/serverspec/localhost/default_spec.rb
@@ -67,13 +67,13 @@ describe "webapp::default", :end_to_end => true do
let(:db_query) { "mysql -u root -pilikerandompasswordstoo -e \"#{statement}\"" }
let(:statement) { "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='webapp'" }
it "creates a database called 'webapp'" do
- expect(command(db_query)).to return_stdout(/webapp/)
+ expect(command(db_query).stdout).to match /webapp/
end
describe "mysql database user 'webapp'" do
let(:statement) { "SELECT Host, Db FROM mysql.db WHERE User='webapp'\\G" }
it "adds user 'webapp' to database 'webapp@localhost'" do
- expect(command(db_query)).to return_stdout(/Host: localhost\n Db: webapp/)
+ expect(command(db_query).stdout).to match /Host: localhost\n Db: webapp/
end
describe "grants" do
@@ -86,7 +86,7 @@ describe "webapp::default", :end_to_end => true do
let(:priv_query) { "#{priv.capitalize}_priv" }
it "has privilege #{priv} on 'webapp@localhost'" do
- expect(command(db_query)).to return_stdout(/#{priv_query}: Y/)
+ expect(command(db_query).stdout).to match /#{priv_query}: Y/
end
end
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index cc712a3f3e..e531da5768 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -378,7 +378,7 @@ class Chef
run_context = setup_run_context
- catch (:end_client_run_early) do
+ catch(:end_client_run_early) do
converge(run_context)
end
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 1503add33a..40aaaf1191 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -552,6 +552,11 @@ class Chef
chef_server_rest.get_rest('cookbooks')
end
+ # Alias latest_cookbooks as list
+ class << self
+ alias :latest_cookbooks :list
+ end
+
def self.list_all_versions
chef_server_rest.get_rest('cookbooks?num_versions=all')
end
@@ -575,11 +580,6 @@ class Chef
end
end
- # Get the newest version of all cookbooks
- def self.latest_cookbooks
- chef_server_rest.get_rest('cookbooks/_latest')
- end
-
def <=>(o)
raise Chef::Exceptions::CookbookVersionNameMismatch if self.name != o.name
# FIXME: can we change the interface to the Metadata class such
diff --git a/lib/chef/http.rb b/lib/chef/http.rb
index abc47f636e..7f2d00157b 100644
--- a/lib/chef/http.rb
+++ b/lib/chef/http.rb
@@ -289,11 +289,26 @@ class Chef
def retrying_http_errors(url)
http_attempts = 0
begin
- http_attempts += 1
-
- yield
-
+ loop do
+ http_attempts += 1
+ response, request, return_value = yield
+ # handle HTTP 50X Error
+ if response.kind_of?(Net::HTTPServerError)
+ if http_retry_count - http_attempts + 1 > 0
+ sleep_time = 1 + (2 ** http_attempts) + rand(2 ** http_attempts)
+ Chef::Log.error("Server returned error #{response.code} for #{url}, retrying #{http_attempts}/#{http_retry_count} in #{sleep_time}s")
+ sleep(sleep_time)
+ redo
+ end
+ end
+ return [response, request, return_value]
+ end
rescue SocketError, Errno::ETIMEDOUT => e
+ if http_retry_count - http_attempts + 1 > 0
+ Chef::Log.error("Error connecting to #{url}, retry #{http_attempts}/#{http_retry_count}")
+ sleep(http_retry_delay)
+ retry
+ end
e.message.replace "Error connecting to #{url} - #{e.message}"
raise e
rescue Errno::ECONNREFUSED
@@ -310,14 +325,6 @@ class Chef
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
diff --git a/lib/chef/mixin/homebrew_owner.rb b/lib/chef/mixin/homebrew_owner.rb
deleted file mode 100644
index 73bb22ddf5..0000000000
--- a/lib/chef/mixin/homebrew_owner.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# Author:: Joshua Timberman (<joshua@getchef.com>)
-# Author:: Graeme Mathieson (<mathie@woss.name>)
-#
-# Copyright 2011-2013, Opscode, Inc.
-# Copyright 2014, Chef Software, Inc <legal@getchef.com>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in 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.
-#
-# Ported from the homebrew cookbook's Homebrew::Mixin owner helpers
-#
-# This lives here in Chef::Mixin because Chef's namespacing makes it
-# awkward to use modules elsewhere (e.g., chef/provider/package/homebrew/owner)
-
-class Chef
- module Mixin
- module HomebrewOwner
- def homebrew_owner(node)
- @homebrew_owner ||= calculate_owner(node)
- end
-
- private
-
- def calculate_owner(node)
- owner = homebrew_owner_attr(node) || sudo_user || current_user
- if owner == 'root'
- raise Chef::Exceptions::CannotDetermineHomebrewOwner,
- 'The homebrew owner is not specified and the current user is \"root\"' +
- 'Homebrew does not support root installs, please specify the homebrew' +
- 'owner by setting the attribute `node[\'homebrew\'][\'owner\']`.'
- end
- owner
- end
-
- def homebrew_owner_attr(node)
- node['homebrew']['owner'] if node.attribute?('homebrew') && node['homebrew'].attribute?('owner')
- end
-
- def sudo_user
- ENV['SUDO_USER']
- end
-
- def current_user
- ENV['USER']
- end
- end
- end
-end
diff --git a/lib/chef/mixin/homebrew_user.rb b/lib/chef/mixin/homebrew_user.rb
new file mode 100644
index 0000000000..854a954a90
--- /dev/null
+++ b/lib/chef/mixin/homebrew_user.rb
@@ -0,0 +1,68 @@
+#
+# Author:: Joshua Timberman (<joshua@getchef.com>)
+# Author:: Graeme Mathieson (<mathie@woss.name>)
+#
+# Copyright 2011-2013, Opscode, Inc.
+# Copyright 2014, Chef Software, Inc <legal@getchef.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in 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.
+#
+# Ported from the homebrew cookbook's Homebrew::Mixin owner helpers
+#
+# This lives here in Chef::Mixin because Chef's namespacing makes it
+# awkward to use modules elsewhere (e.g., chef/provider/package/homebrew/owner)
+
+require 'chef/mixin/shell_out'
+require 'etc'
+
+class Chef
+ module Mixin
+ module HomebrewUser
+ include Chef::Mixin::ShellOut
+
+ ##
+ # This tries to find the user to execute brew as. If a user is provided, that overrides the brew
+ # executable user. It is an error condition if the brew executable owner is root or we cannot find
+ # the brew executable.
+ def find_homebrew_uid(provided_user = nil)
+ # They could provide us a user name or a UID
+ unless provided_user.nil?
+ return provided_user if provided_user.is_a? Integer
+ return Etc.getpwnam(provided_user).uid
+ end
+
+ @homebrew_owner ||= calculate_owner
+ @homebrew_owner
+ end
+
+ private
+
+ def calculate_owner
+ default_brew_path = '/usr/local/bin/brew'
+ if ::File.exist?(default_brew_path)
+ # By default, this follows symlinks which is what we want
+ owner = ::File.stat(default_brew_path).uid
+ elsif (brew_path = shell_out("which brew").stdout.strip) && !brew_path.empty?
+ owner = ::File.stat(brew_path).uid
+ else
+ raise Chef::Exceptions::CannotDetermineHomebrewOwner,
+ 'Could not find the "brew" executable in /usr/local/bin or anywhere on the path.'
+ end
+
+ Chef::Log.debug "Found Homebrew owner #{Etc.getpwuid(owner).name}; executing `brew` commands as them"
+ owner
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/provider/dsc_script.rb b/lib/chef/provider/dsc_script.rb
index c979800cba..b8ca54f1b8 100644
--- a/lib/chef/provider/dsc_script.rb
+++ b/lib/chef/provider/dsc_script.rb
@@ -47,9 +47,11 @@ class Chef
end
def load_current_resource
- @dsc_resources_info = run_configuration(:test)
- @resource_converged = @dsc_resources_info.all? do |resource|
- !resource.changes_state?
+ if supports_dsc?
+ @dsc_resources_info = run_configuration(:test)
+ @resource_converged = @dsc_resources_info.all? do |resource|
+ !resource.changes_state?
+ end
end
end
@@ -57,8 +59,26 @@ class Chef
true
end
+ def define_resource_requirements
+ requirements.assert(:run) do |a|
+ err = [
+ 'Could not find Dsc on the system',
+ powershell_info_str,
+ "Powershell 4.0 or higher was not detected on your system and is required to use the dsc_script resource.",
+ ]
+ a.assertion { supports_dsc? }
+ a.failure_message Chef::Exceptions::NoProviderAvailable, err.join(' ')
+ a.whyrun err + ["Assuming a previous resource installs Powershell 4.0 or higher."]
+ a.block_action!
+ end
+ end
+
protected
+ def supports_dsc?
+ run_context && Chef::Platform.supports_dsc?(node)
+ end
+
def run_configuration(operation)
config_directory = ::Dir.mktmpdir("chef-dsc-script")
configuration_data_path = get_configuration_data_path(config_directory)
@@ -144,6 +164,14 @@ class Chef
end
end
end
+
+ def powershell_info_str
+ if run_context && run_context.node[:languages] && run_context.node[:languages][:powershell]
+ install_info = "Powershell #{run_context.node[:languages][:powershell][:version]} was found on the system."
+ else
+ install_info = 'Powershell was not found.'
+ end
+ end
end
end
end
diff --git a/lib/chef/provider/git.rb b/lib/chef/provider/git.rb
index 5b785c31fc..c8e615c1f9 100644
--- a/lib/chef/provider/git.rb
+++ b/lib/chef/provider/git.rb
@@ -102,6 +102,10 @@ class Chef
end
end
+ def git_minor_version
+ @git_minor_version ||= Gem::Version.new(shell_out!('git --version', run_options).stdout.split.last)
+ end
+
def existing_git_clone?
::File.exist?(::File.join(@new_resource.destination, ".git"))
end
@@ -137,6 +141,7 @@ class Chef
args = []
args << "-o #{remote}" unless remote == 'origin'
args << "--depth #{@new_resource.depth}" if @new_resource.depth
+ args << "--no-single-branch" if @new_resource.depth and git_minor_version >= Gem::Version.new('1.7.10')
Chef::Log.info "#{@new_resource} cloning repo #{@new_resource.repository} to #{@new_resource.destination}"
diff --git a/lib/chef/provider/package/freebsd/pkgng.rb b/lib/chef/provider/package/freebsd/pkgng.rb
index 0741a4d95f..bfe6dca617 100644
--- a/lib/chef/provider/package/freebsd/pkgng.rb
+++ b/lib/chef/provider/package/freebsd/pkgng.rb
@@ -45,7 +45,7 @@ class Chef
def current_installed_version
pkg_info = shell_out!("pkg info \"#{@new_resource.package_name}\"", :env => nil, :returns => [0,70])
- pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+)/, 1]
+ pkg_info.stdout[/^Version +: (.+)$/, 1]
end
def candidate_version
diff --git a/lib/chef/provider/package/homebrew.rb b/lib/chef/provider/package/homebrew.rb
index d964703c87..202e4d2533 100644
--- a/lib/chef/provider/package/homebrew.rb
+++ b/lib/chef/provider/package/homebrew.rb
@@ -19,13 +19,13 @@
#
require 'etc'
-require 'chef/mixin/homebrew_owner'
+require 'chef/mixin/homebrew_user'
class Chef
class Provider
class Package
class Homebrew < Chef::Provider::Package
- include Chef::Mixin::HomebrewOwner
+ include Chef::Mixin::HomebrewUser
def load_current_resource
self.current_resource = Chef::Resource::Package.new(new_resource.name)
current_resource.package_name(new_resource.package_name)
@@ -109,12 +109,14 @@ class Chef
private
def get_response_from_command(command)
- home_dir = Etc.getpwnam(homebrew_owner(node)).dir
+ homebrew_uid = find_homebrew_uid(new_resource.homebrew_user)
+ homebrew_user = Etc.getpwuid(homebrew_uid)
- Chef::Log.debug "Executing '#{command}' as user '#{homebrew_owner(node)}'"
- output = shell_out!(command, :timeout => 1800, :user => homebrew_owner(node), :environment => { 'HOME' => home_dir, 'RUBYOPT' => nil })
+ Chef::Log.debug "Executing '#{command}' as user '#{homebrew_user.name}'"
+ output = shell_out!(command, :timeout => 1800, :user => homebrew_uid, :environment => { 'HOME' => homebrew_user.dir, 'RUBYOPT' => nil })
output.stdout.chomp
end
+
end
end
end
diff --git a/lib/chef/resource/dsc_script.rb b/lib/chef/resource/dsc_script.rb
index 2972ace1aa..76ac6659d6 100644
--- a/lib/chef/resource/dsc_script.rb
+++ b/lib/chef/resource/dsc_script.rb
@@ -28,12 +28,8 @@ class Chef
super
@allowed_actions.push(:run)
@action = :run
- if(run_context && Chef::Platform.supports_dsc?(run_context.node))
- @provider = Chef::Provider::DscScript
- else
- raise Chef::Exceptions::NoProviderAvailable,
- "#{powershell_info_str(run_context)}\nPowershell 4.0 or higher was not detected on your system and is required to use the dsc_script resource."
- end
+ @provider = Chef::Provider::DscScript
+ @resource_name = :dsc_script
end
def code(arg=nil)
@@ -125,16 +121,6 @@ class Chef
:kind_of => [ Integer ]
)
end
-
- private
-
- def powershell_info_str(run_context)
- if run_context && run_context.node[:languages] && run_context.node[:languages][:powershell]
- install_info = "Powershell #{run_context.node[:languages][:powershell][:version]} was found on the system."
- else
- install_info = 'Powershell was not found.'
- end
- end
end
end
end
diff --git a/lib/chef/resource/homebrew_package.rb b/lib/chef/resource/homebrew_package.rb
index c3fa9ddffc..e1d50c1739 100644
--- a/lib/chef/resource/homebrew_package.rb
+++ b/lib/chef/resource/homebrew_package.rb
@@ -24,11 +24,22 @@ require 'chef/resource/package'
class Chef
class Resource
class HomebrewPackage < Chef::Resource::Package
+
def initialize(name, run_context=nil)
super
@resource_name = :homebrew_package
@provider = Chef::Provider::Package::Homebrew
+ @homebrew_user = nil
+ end
+
+ def homebrew_user(arg=nil)
+ set_or_return(
+ :homebrew_user,
+ arg,
+ :kind_of => [ String, Integer ]
+ )
end
+
end
end
end
diff --git a/spec/functional/resource/group_spec.rb b/spec/functional/resource/group_spec.rb
index 3c97291294..9c14232071 100644
--- a/spec/functional/resource/group_spec.rb
+++ b/spec/functional/resource/group_spec.rb
@@ -28,10 +28,10 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte
def group_should_exist(group)
case ohai[:platform_family]
when "debian", "fedora", "rhel", "suse", "gentoo", "slackware", "arch"
- expect { Etc::getgrnam(group) }.to_not raise_error(ArgumentError, "can't find group for #{group}")
+ expect { Etc::getgrnam(group) }.not_to raise_error
expect(group).to eq(Etc::getgrnam(group).name)
when "windows"
- expect { Chef::Util::Windows::NetGroup.new(group).local_get_members }.to_not raise_error(ArgumentError, "The group name could not be found.")
+ expect { Chef::Util::Windows::NetGroup.new(group).local_get_members }.not_to raise_error
end
end
@@ -369,9 +369,12 @@ downthestreetalwayshadagoodsmileonhisfacetheoldmanwalkingdownthestreeQQQQQQ" }
let(:tested_action) { :manage }
describe "when there is no group" do
- it "should raise an error" do
+ it "raises an error on modify" do
+ lambda { group_resource.run_action(:modify) }.should raise_error
+ end
+
+ it "does not raise an error on manage" do
lambda { group_resource.run_action(:manage) }.should_not raise_error
- group_should_not_exist(group_name)
end
end
diff --git a/spec/unit/mixin/homebrew_owner_spec.rb b/spec/unit/mixin/homebrew_owner_spec.rb
deleted file mode 100644
index 428cd827d9..0000000000
--- a/spec/unit/mixin/homebrew_owner_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-#
-# Author:: Joshua Timberman (<joshua@getchef.com>)
-#
-# Copyright 2014, Chef Software, Inc <legal@getchef.com>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'spec_helper'
-require 'chef/mixin/homebrew_owner'
-
-class ExampleHomebrewOwner
- include Chef::Mixin::HomebrewOwner
-end
-
-describe Chef::Mixin::HomebrewOwner do
- before(:each) do
- node.default['homebrew']['owner'] = nil
- end
-
- let(:homebrew_owner) { ExampleHomebrewOwner.new }
- let(:node) { Chef::Node.new }
-
- describe 'when the homebrew owner node attribute is set' do
- it 'raises an exception if the owner is root' do
- node.default['homebrew']['owner'] = 'root'
- expect { homebrew_owner.homebrew_owner(node) }.to raise_exception(Chef::Exceptions::CannotDetermineHomebrewOwner)
- end
-
- it 'returns the owner set by attribute' do
- node.default['homebrew']['owner'] = 'siouxsie'
- expect(homebrew_owner.homebrew_owner(node)).to eql('siouxsie')
- end
- end
-
- describe 'when the owner attribute is not set and we use sudo' do
- before(:each) do
- ENV.stub(:[]).with('SUDO_USER').and_return('john_lydon')
- end
-
- it 'uses the SUDO_USER environment variable' do
- expect(homebrew_owner.homebrew_owner(node)).to eql('john_lydon')
- end
- end
-
- describe 'when the owner attribute is not set and we arent using sudo' do
- before(:each) do
- ENV.stub(:[]).with('USER').and_return('sid_vicious')
- ENV.stub(:[]).with('SUDO_USER').and_return(nil)
- end
-
- it 'uses the current user' do
- expect(homebrew_owner.homebrew_owner(node)).to eql('sid_vicious')
- end
- end
-end
diff --git a/spec/unit/mixin/homebrew_user_spec.rb b/spec/unit/mixin/homebrew_user_spec.rb
new file mode 100644
index 0000000000..4e30455765
--- /dev/null
+++ b/spec/unit/mixin/homebrew_user_spec.rb
@@ -0,0 +1,100 @@
+#
+# Author:: Joshua Timberman (<joshua@getchef.com>)
+#
+# Copyright 2014, Chef Software, Inc <legal@getchef.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'spec_helper'
+require 'chef/mixin/homebrew_user'
+
+class ExampleHomebrewUser
+ include Chef::Mixin::HomebrewUser
+end
+
+describe Chef::Mixin::HomebrewUser do
+ before(:each) do
+ node.default['homebrew']['owner'] = nil
+ end
+
+ let(:homebrew_user) { ExampleHomebrewUser.new }
+ let(:node) { Chef::Node.new }
+
+ describe 'when the homebrew user is provided' do
+ let(:uid) { 1001 }
+ let(:user) { "foo" }
+
+ it 'returns the homebrew user without looking at the file when uid is provided' do
+ expect(File).to receive(:exist?).exactly(0).times
+ expect(homebrew_user.find_homebrew_uid(uid)).to eq(uid)
+ end
+
+ it 'returns the homebrew user without looking at the file when name is provided' do
+ expect(File).to receive(:exist?).exactly(0).times
+ Etc.stub_chain(:getpwnam, :uid).and_return(uid)
+ expect(homebrew_user.find_homebrew_uid(user)).to eq(uid)
+ end
+
+ end
+
+ shared_examples "successfully find executable" do
+ let(:user) { nil }
+ let(:brew_owner) { 2001 }
+ let(:default_brew_path) { '/usr/local/bin/brew' }
+ let(:stat_double) {
+ d = double()
+ expect(d).to receive(:uid).and_return(brew_owner)
+ d
+ }
+
+ context "debug statement prints owner name" do
+
+ before do
+ expect(Etc).to receive(:getpwuid).with(brew_owner).and_return(OpenStruct.new(:name => "name"))
+ end
+
+ it 'returns the owner of the brew executable when it is at a default location' do
+ expect(File).to receive(:exist?).with(default_brew_path).and_return(true)
+ expect(File).to receive(:stat).with(default_brew_path).and_return(stat_double)
+ expect(homebrew_user.find_homebrew_uid(user)).to eq(brew_owner)
+ end
+
+ it 'returns the owner of the brew executable when it is not at a default location' do
+ expect(File).to receive(:exist?).with(default_brew_path).and_return(false)
+ homebrew_user.stub_chain(:shell_out, :stdout, :strip).and_return("/foo")
+ expect(File).to receive(:stat).with("/foo").and_return(stat_double)
+ expect(homebrew_user.find_homebrew_uid(user)).to eq(brew_owner)
+ end
+
+ end
+ end
+
+ describe 'when the homebrew user is not provided' do
+
+ it 'raises an error if no executable is found' do
+ expect(File).to receive(:exist?).with(default_brew_path).and_return(false)
+ homebrew_user.stub_chain(:shell_out, :stdout, :strip).and_return("")
+ expect { homebrew_user.find_homebrew_uid(user) }.to raise_error(Chef::Exceptions::CannotDetermineHomebrewOwner)
+ end
+
+ include_examples "successfully find executable"
+
+ context "the executable is owned by root" do
+ include_examples "successfully find executable" do
+ let(:brew_owner) { 0 }
+ end
+ end
+
+ end
+
+end
diff --git a/spec/unit/provider/dsc_script_spec.rb b/spec/unit/provider/dsc_script_spec.rb
index 8a7a7b5c6a..d8fbee3ff9 100644
--- a/spec/unit/provider/dsc_script_spec.rb
+++ b/spec/unit/provider/dsc_script_spec.rb
@@ -22,123 +22,152 @@ require 'chef/util/dsc/resource_info'
require 'spec_helper'
describe Chef::Provider::DscScript do
- let (:node) {
- node = Chef::Node.new
- node.automatic[:languages][:powershell][:version] = '4.0'
- node
- }
- let (:events) { Chef::EventDispatch::Dispatcher.new }
- let (:run_context) { Chef::RunContext.new(node, {}, events) }
- let (:resource) { Chef::Resource::DscScript.new("script", run_context) }
- let (:provider) do
- Chef::Provider::DscScript.new(resource, run_context)
- end
-
- describe '#load_current_resource' do
- it "describes the resource as converged if there were 0 DSC resources" do
- allow(provider).to receive(:run_configuration).with(:test).and_return([])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_true
+ context 'when DSC is available' do
+ let (:node) {
+ node = Chef::Node.new
+ node.automatic[:languages][:powershell][:version] = '4.0'
+ node
+ }
+ let (:events) { Chef::EventDispatch::Dispatcher.new }
+ let (:run_context) { Chef::RunContext.new(node, {}, events) }
+ let (:resource) { Chef::Resource::DscScript.new("script", run_context) }
+ let (:provider) do
+ Chef::Provider::DscScript.new(resource, run_context)
end
- it "describes the resource as not converged if there is 1 DSC resources that is converged" do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_true
+ describe '#load_current_resource' do
+ it "describes the resource as converged if there were 0 DSC resources" do
+ allow(provider).to receive(:run_configuration).with(:test).and_return([])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_true
+ end
+
+ it "describes the resource as not converged if there is 1 DSC resources that is converged" do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_true
+ end
+
+ it "describes the resource as not converged if there is 1 DSC resources that is not converged" do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_false
+ end
+
+ it "describes the resource as not converged if there are any DSC resources that are not converged" do
+ dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
+ dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
+
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_false
+ end
+
+ it "describes the resource as converged if all DSC resources that are converged" do
+ dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
+ dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
+
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_true
+ end
end
- it "describes the resource as not converged if there is 1 DSC resources that is not converged" do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_false
+ describe '#generate_configuration_document' do
+ # I think integration tests should cover these cases
+
+ it 'uses configuration_document_from_script_path when a dsc script file is given' do
+ allow(provider).to receive(:load_current_resource)
+ resource.command("path_to_script")
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
+ generator.should_receive(:configuration_document_from_script_path)
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
+ provider.send(:generate_configuration_document, 'tmp', nil)
+ end
+
+ it 'uses configuration_document_from_script_code when a the dsc resource is given' do
+ allow(provider).to receive(:load_current_resource)
+ resource.code("ImADSCResource{}")
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
+ generator.should_receive(:configuration_document_from_script_code)
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
+ provider.send(:generate_configuration_document, 'tmp', nil)
+ end
+
+ it 'should noop if neither code or command are provided' do
+ allow(provider).to receive(:load_current_resource)
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
+ generator.should_receive(:configuration_document_from_script_code).with('', anything(), anything())
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
+ provider.send(:generate_configuration_document, 'tmp', nil)
+ end
end
- it "describes the resource as not converged if there are any DSC resources that are not converged" do
- dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
- dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
-
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_false
+ describe 'action_run' do
+ it 'should converge the script if it is not converged' do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
+ allow(provider).to receive(:run_configuration).with(:set)
+
+ provider.run_action(:run)
+ resource.should be_updated
+ end
+
+ it 'should not converge if the script is already converged' do
+ allow(provider).to receive(:run_configuration).with(:test).and_return([])
+
+ provider.run_action(:run)
+ resource.should_not be_updated
+ end
end
- it "describes the resource as converged if all DSC resources that are converged" do
- dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
- dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
-
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_true
+ describe '#generate_description' do
+ it 'removes the resource name from the beginning of any log line from the LCM' do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
+ provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing something/)
+ end
+
+ it 'ignores the last line' do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
+ provider.send(:generate_description)[1].should_not match(/lastline/)
+ end
+
+ it 'reports a dsc resource has not been changed if the LCM reported no change was required' do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', false, ['resourcename does nothing', 'lastline'])
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
+ provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing nothing/)
+ end
end
end
- describe '#generate_configuration_document' do
- # I think integration tests should cover these cases
-
- it 'uses configuration_document_from_script_path when a dsc script file is given' do
- allow(provider).to receive(:load_current_resource)
- resource.command("path_to_script")
- generator = double('Chef::Util::DSC::ConfigurationGenerator')
- generator.should_receive(:configuration_document_from_script_path)
- allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
- provider.send(:generate_configuration_document, 'tmp', nil)
- end
-
- it 'uses configuration_document_from_script_code when a the dsc resource is given' do
- allow(provider).to receive(:load_current_resource)
- resource.code("ImADSCResource{}")
- generator = double('Chef::Util::DSC::ConfigurationGenerator')
- generator.should_receive(:configuration_document_from_script_code)
- allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
- provider.send(:generate_configuration_document, 'tmp', nil)
- end
-
- it 'should noop if neither code or command are provided' do
- allow(provider).to receive(:load_current_resource)
- generator = double('Chef::Util::DSC::ConfigurationGenerator')
- generator.should_receive(:configuration_document_from_script_code).with('', anything(), anything())
- allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
- provider.send(:generate_configuration_document, 'tmp', nil)
- end
- end
-
- describe 'action_run' do
- it 'should converge the script if it is not converged' do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
- allow(provider).to receive(:run_configuration).with(:set)
-
- provider.run_action(:run)
- resource.should be_updated
- end
-
- it 'should not converge if the script is already converged' do
- allow(provider).to receive(:run_configuration).with(:test).and_return([])
-
- provider.run_action(:run)
- resource.should_not be_updated
- end
- end
-
- describe '#generate_description' do
- it 'removes the resource name from the beginning of any log line from the LCM' do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
- provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
- provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing something/)
- end
-
- it 'ignores the last line' do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
- provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
- provider.send(:generate_description)[1].should_not match(/lastline/)
- end
+ context 'when Dsc is not available' do
+ let (:node) { Chef::Node.new }
+ let (:events) { Chef::EventDispatch::Dispatcher.new }
+ let (:run_context) { Chef::RunContext.new(node, {}, events) }
+ let (:resource) { Chef::Resource::DscScript.new('script', run_context) }
+ let (:provider) { Chef::Provider::DscScript.new(resource, run_context) }
+
+ describe 'action_run' do
+ ['1.0', '2.0', '3.0'].each do |version|
+ it "raises an exception for powershell version '#{version}'" do
+ node.automatic[:languages][:powershell][:version] = version
+
+ expect {
+ provider.run_action(:run)
+ }.to raise_error(Chef::Exceptions::NoProviderAvailable)
+ end
+ end
+
+ it 'raises an exception if Powershell is not present' do
+ expect {
+ provider.run_action(:run)
+ }.to raise_error(Chef::Exceptions::NoProviderAvailable)
+ end
- it 'reports a dsc resource has not been changed if the LCM reported no change was required' do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', false, ['resourcename does nothing', 'lastline'])
- provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
- provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing nothing/)
end
end
end
diff --git a/spec/unit/provider/git_spec.rb b/spec/unit/provider/git_spec.rb
index 20b13c4cb0..ff1c0b0398 100644
--- a/spec/unit/provider/git_spec.rb
+++ b/spec/unit/provider/git_spec.rb
@@ -233,6 +233,21 @@ SHAS
it "compiles a clone command using --depth for shallow cloning" do
@resource.depth 5
expected_cmd = "git clone --depth 5 \"git://github.com/opscode/chef.git\" \"/my/deploy/dir\""
+ version_response = double('shell_out')
+ version_response.stub(:stdout) { 'git version 1.7.9' }
+ @provider.should_receive(:shell_out!).with("git --version",
+ :log_tag => "git[web2.0 app]").and_return(version_response)
+ @provider.should_receive(:shell_out!).with(expected_cmd, :log_tag => "git[web2.0 app]")
+ @provider.clone
+ end
+
+ it "compiles a clone command using --no-single-branch for shallow cloning when git >= 1.7.10" do
+ @resource.depth 5
+ expected_cmd = "git clone --depth 5 --no-single-branch \"git://github.com/opscode/chef.git\" \"/my/deploy/dir\""
+ version_response = double('shell_out')
+ version_response.stub(:stdout) { 'git version 1.7.10' }
+ @provider.should_receive(:shell_out!).with("git --version",
+ :log_tag => "git[web2.0 app]").and_return(version_response)
@provider.should_receive(:shell_out!).with(expected_cmd, :log_tag => "git[web2.0 app]")
@provider.clone
end
diff --git a/spec/unit/provider/package/freebsd/pkgng_spec.rb b/spec/unit/provider/package/freebsd/pkgng_spec.rb
index 001c9e23ba..c3837a251b 100644
--- a/spec/unit/provider/package/freebsd/pkgng_spec.rb
+++ b/spec/unit/provider/package/freebsd/pkgng_spec.rb
@@ -67,7 +67,7 @@ describe Chef::Provider::Package::Freebsd::Port do
describe "determining current installed version" do
before(:each) do
@provider.stub(:supports_pkgng?)
- @pkg_info = OpenStruct.new(:stdout => "zsh-3.1.7\n")
+ @pkg_info = OpenStruct.new(:stdout => "zsh-3.1.7\nVersion : 3.1.7\n")
end
it "should query pkg database" do
diff --git a/spec/unit/provider/package/homebrew_spec.rb b/spec/unit/provider/package/homebrew_spec.rb
index 9f105c13b8..d38458546d 100644
--- a/spec/unit/provider/package/homebrew_spec.rb
+++ b/spec/unit/provider/package/homebrew_spec.rb
@@ -28,6 +28,8 @@ describe Chef::Provider::Package::Homebrew do
Chef::Provider::Package::Homebrew.new(new_resource, run_context)
end
+ let(:homebrew_uid) { 1001 }
+
let(:uninstalled_brew_info) do
{
'name' => 'emacs',
@@ -92,8 +94,7 @@ describe Chef::Provider::Package::Homebrew do
end
before(:each) do
- node.default['homebrew']['owner'] = 'sid_vicious'
- allow(Etc).to receive(:getpwnam).with('sid_vicious').and_return('/Users/sid_vicious')
+
end
describe 'load_current_resource' do
@@ -143,13 +144,18 @@ describe Chef::Provider::Package::Homebrew do
end
describe 'brew' do
+ before do
+ expect(provider).to receive(:find_homebrew_uid).and_return(homebrew_uid)
+ expect(Etc).to receive(:getpwuid).with(homebrew_uid).and_return(OpenStruct.new(:name => "name", :dir => "/"))
+ end
+
it 'passes a single to the brew command and return stdout' do
- allow(provider).to receive(:get_response_from_command).and_return('zombo')
+ allow(provider).to receive(:shell_out!).and_return(OpenStruct.new(:stdout => 'zombo'))
expect(provider.brew).to eql('zombo')
end
it 'takes multiple arguments as an array' do
- allow(provider).to receive(:get_response_from_command).and_return('homestarrunner')
+ allow(provider).to receive(:shell_out!).and_return(OpenStruct.new(:stdout => 'homestarrunner'))
expect(provider.brew('info', 'opts', 'bananas')).to eql('homestarrunner')
end
end
diff --git a/spec/unit/resource/dsc_script_spec.rb b/spec/unit/resource/dsc_script_spec.rb
index cbd502a61c..eb9d19e553 100644
--- a/spec/unit/resource/dsc_script_spec.rb
+++ b/spec/unit/resource/dsc_script_spec.rb
@@ -95,33 +95,4 @@ describe Chef::Resource::DscScript do
expect { dsc_test_resource.configuration_data_script(configuration_data_script) }.to raise_error(ArgumentError)
end
end
-
- context 'when Powershell does not supported Dsc' do
- ['1.0', '2.0', '3.0'].each do |version|
- it "raises an exception for powershell version '#{version}'" do
- node = Chef::Node.new
- node.automatic[:languages][:powershell][:version] = version
- empty_events = Chef::EventDispatch::Dispatcher.new
- dsc_test_run_context = Chef::RunContext.new(node, {}, empty_events)
-
- expect {
- Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context)
- }.to raise_error(Chef::Exceptions::NoProviderAvailable)
- end
- end
- end
-
- context 'when Powershell is not present' do
- let (:dsc_test_run_context) {
- node = Chef::Node.new
- empty_events = Chef::EventDispatch::Dispatcher.new
- dsc_test_run_context = Chef::RunContext.new(node, {}, empty_events)
- }
-
- it 'raises an exception if powershell is not present' do
- expect {
- Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context)
- }.to raise_error(Chef::Exceptions::NoProviderAvailable)
- end
- end
end
diff --git a/spec/unit/resource/homebrew_package_spec.rb b/spec/unit/resource/homebrew_package_spec.rb
index 4b4f9afe5e..bb657607b7 100644
--- a/spec/unit/resource/homebrew_package_spec.rb
+++ b/spec/unit/resource/homebrew_package_spec.rb
@@ -33,4 +33,25 @@ describe Chef::Resource::HomebrewPackage, 'initialize' do
expect(resource.provider).to eql(Chef::Provider::Package::Homebrew)
end
+ it 'sets the homebrew_user to nil' do
+ expect(resource.homebrew_user).to eql(nil)
+ end
+
+ shared_examples 'home_brew user set and returned' do
+ it 'returns the configured homebrew_user' do
+ resource.homebrew_user user
+ expect(resource.homebrew_user).to eql(user)
+ end
+ end
+
+ context 'homebrew_user is set' do
+ let(:user) { 'Captain Picard' }
+ include_examples 'home_brew user set and returned'
+
+ context 'as an integer' do
+ let(:user) { 1001 }
+ include_examples 'home_brew user set and returned'
+ end
+ end
+
end
diff --git a/spec/unit/rest_spec.rb b/spec/unit/rest_spec.rb
index 3ad822193b..424fd12ee9 100644
--- a/spec/unit/rest_spec.rb
+++ b/spec/unit/rest_spec.rb
@@ -526,9 +526,12 @@ describe Chef::REST do
http_response.stub(:read_body)
http_response
end
- it "throws an exception" do
+
+ it "retries then throws an exception" do
rest.stub(:sleep)
expect {rest.request(:GET, url)}.to raise_error(Net::HTTPFatalError)
+ count = Chef::Config[:http_retry_count]
+ expect(log_stringio.string).to match(Regexp.escape("ERROR: Server returned error 500 for #{url}, retrying #{count}/#{count}"))
end
end
end