summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml36
-rw-r--r--CHANGELOG.md1
-rw-r--r--CONTRIBUTING.md10
-rw-r--r--Gemfile16
-rw-r--r--RELEASE_NOTES.md7
-rw-r--r--VERSION2
-rw-r--r--chef-config/VERSION2
-rw-r--r--chef-config/lib/chef-config/version.rb2
-rw-r--r--chef.gemspec2
-rw-r--r--distro/common/html/knife_cookbook_site.html36
-rw-r--r--distro/common/man/man1/knife-cookbook-site.122
-rw-r--r--external_tests/chef-rewind.gemfile5
-rw-r--r--external_tests/chef-sugar.gemfile6
-rw-r--r--external_tests/chefspec.gemfile7
-rw-r--r--external_tests/foodcritic.gemfile9
-rw-r--r--external_tests/halite.gemfile8
-rw-r--r--external_tests/poise.gemfile7
-rw-r--r--lib/chef/chef_class.rb5
-rw-r--r--lib/chef/cookbook_site_streaming_uploader.rb2
-rw-r--r--lib/chef/knife/bootstrap/templates/README.md7
-rw-r--r--lib/chef/knife/cookbook_create.rb2
-rw-r--r--lib/chef/knife/cookbook_site_download.rb2
-rw-r--r--lib/chef/knife/cookbook_site_install.rb2
-rw-r--r--lib/chef/knife/cookbook_site_share.rb12
-rw-r--r--lib/chef/knife/search.rb4
-rw-r--r--lib/chef/knife/ssh.rb2
-rw-r--r--lib/chef/mixin/which.rb2
-rw-r--r--lib/chef/platform/service_helpers.rb62
-rw-r--r--lib/chef/policy_builder/expand_node_object.rb30
-rw-r--r--lib/chef/property.rb11
-rw-r--r--lib/chef/provider/package/rpm.rb4
-rw-r--r--lib/chef/provider/remote_directory.rb2
-rw-r--r--lib/chef/run_context.rb8
-rw-r--r--lib/chef/run_lock.rb51
-rw-r--r--lib/chef/version.rb2
-rw-r--r--spec/functional/run_lock_spec.rb275
-rw-r--r--spec/integration/recipes/remote_directory.rb74
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/support/shared/unit/mock_shellout.rb46
-rw-r--r--spec/unit/knife/cookbook_site_share_spec.rb6
-rw-r--r--spec/unit/policy_builder/expand_node_object_spec.rb29
-rw-r--r--spec/unit/property_spec.rb60
-rw-r--r--spec/unit/provider/package/rpm_spec.rb19
-rw-r--r--spec/unit/provider_resolver_spec.rb1357
-rw-r--r--tasks/external_tests.rb70
45 files changed, 1350 insertions, 976 deletions
diff --git a/.travis.yml b/.travis.yml
index d7ad317e28..9f253df6c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -26,11 +26,41 @@ matrix:
include:
- rvm: 2.1
- rvm: 2.2
- - rvm: 2.1
+ - rvm: 2.2
gemfile: pedant.gemfile
script: bundle exec rake pedant
- ### START TEST KITCHEN ONLY ###
- - rvm: 2.1
+ - rvm: 2.2
+ env: "GEMFILE_MOD=\"gem 'cheffish', github: 'chef/cheffish'\""
+ script: bundle exec rake cheffish_spec
+ - rvm: 2.2
+ env: "GEMFILE_MOD=\"gem 'chef-provisioning', github: 'chef/chef-provisioning'\""
+ script: bundle exec rake chef_provisioning_spec
+ - rvm: 2.2
+ env: "GEMFILE_MOD=\"gem 'chef-provisioning-aws', github: 'chef/chef-provisioning-aws'\""
+ script: bundle exec rake chef_provisioning_aws_spec
+ - rvm: 2.2
+ env: "GEMFILE_MOD=\"gem 'chefspec'\""
+ script: bundle exec rake chefspec_spec
+ - rvm: 2.2
+ env: "GEMFILE_MOD=\"gem 'chef-sugar'\""
+ script: bundle exec rake chef_sugar_spec
+ - rvm: 2.2
+ env: "GEMFILE_MOD=\"gem 'chef-rewind'\""
+ script: bundle exec rake chef_rewind_spec
+ - rvm: 2.2
+ env: "GEMFILE_MOD=\"gem 'foodcritic', github: 'acrmp/foodcritic', branch: 'v5.0.0'\""
+ script: bundle exec rake foodcritic_spec
+ - rvm: 2.2
+ env: "GEMFILE_MOD=\"gem 'halite', github: 'poise/halite'\""
+ script: bundle exec rake halite_spec
+ - rvm: 2.2
+ env: "GEMFILE_MOD=\"gem 'poise', github: 'poise/poise'\""
+ script: bundle exec rake poise_spec
+ # Not working yet: halite
+ # - rvm: 2.2
+ # script: bundle exec rake poise_spec
+ ### START TEST KITCHEN ONLY ###
+ - rvm: 2.2
gemfile: kitchen-tests/Gemfile
before_install:
- echo -n $DO_KEY_CHUNK_{0..30} >> ~/.ssh/id_aws.base64
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7c83dbed88..251b68e50e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,7 @@ of partial templates.
* [**Joel Handwell**](https://github.com/joelhandwell):
[pr#3821](https://github.com/chef/chef/pull/3821) Human friendly elapsed time in log
+* [pr#3985](https://github.com/chef/chef/pull/3985) Simplify the regex which determines the rpm version to resolve issue #3671
* [pr#3928](https://github.com/chef/chef/pull/3928) Add named run list support when using policyfiles
* [pr#3913](https://github.com/chef/chef/pull/3913) Add `policy_name`and `policy_group` fields to the node object
* [pr#3875](https://github.com/chef/chef/pull/3875) Patch Win32::Registry#delete_key, #delete_value to use wide (W) APIs
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index cc416537ab..e7f2e05f06 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -70,7 +70,7 @@ Chef uses [the Apache 2.0 license](https://github.com/opscode/chef/blob/master/L
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.
+ such as when the contributor is doing work for a company.
To make a good faith effort to ensure these criteria are met, Chef requires an Individual CLA
or a Corporate CLA for contributions. This agreement helps ensure you are aware of the
@@ -134,8 +134,8 @@ There is also a listing of the various Chef products and where to file issues th
Otherwise you can file your issue in the [Chef project](https://github.com/opscode/chef/issues)
and we will make sure it gets filed against the appropriate project.
-In order to decrease the back and forth an issues and help us get to the bottom of them quickly
- we use below issue template. You can copy paste this code into the issue you are opening and
+In order to decrease the back and forth in issues, and to help us get to the bottom of them quickly
+ we use the below issue template. You can copy/paste this template into the issue you are opening and
edit it accordingly.
<a name="issuetemplate"></a>
@@ -148,16 +148,12 @@ In order to decrease the back and forth an issues and help us get to the bottom
### Scenario:
[What you are trying to achieve and you can't?]
-
-
### Steps to Reproduce:
[If you are filing an issue what are the things we need to do in order to repro your problem?]
-
### Expected Result:
[What are you expecting to happen as the consequence of above reproduction steps?]
-
### Actual Result:
[What actually happens after the reproduction steps?]
```
diff --git a/Gemfile b/Gemfile
index 2b135fb8e8..9d5cf0fea1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -22,11 +22,25 @@ group(:development, :test) do
gem "simplecov"
gem 'rack', "~> 1.5.1"
- gem 'cheffish', "~> 1.3", "!= 1.3.1"
gem 'ruby-shadow', :platforms => :ruby unless RUBY_PLATFORM.downcase.match(/(aix|cygwin)/)
+
+ # For external tests
+# gem 'chef-zero', github: 'chef/chef-zero'
+# gem 'cheffish', github: 'chef/cheffish'
+# gem 'chef-provisioning'#, github: 'chef/chef-provisioning'
+# gem 'chef-provisioning-aws', github: 'chef/chef-provisioning-aws'
+# gem 'test-kitchen'
+# gem 'chefspec'
+# gem 'chef-sugar'
+# gem 'poise', github: 'poise/poise', branch: 'deeecb890a6a0bc2037dfb09ce0fd0a8931519aa'
+# gem 'halite', github: 'poise/halite'
+# gem 'foodcritic', github: 'acrmp/foodcritic', branch: 'v5.0.0'
+# gem 'chef-rewind'
end
+instance_eval(ENV['GEMFILE_MOD']) if ENV['GEMFILE_MOD']
+
# 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')
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index cba5b9f415..d95c416a41 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,9 @@
# Chef Client Release Notes 12.5.0:
* OSX 10.11 support (support for SIP and service changes)
+* Windows cookbook <= 1.38.1 contains a library file which does not compile with
+chef-client 12.5.0. This is resolved in version 1.38.2 of the Windows cookbook.
+Cookbooks depending on the Windows cookbook should update the dependency version
+to at least 1.38.2 to be compatible with chef-client 12.5.0.
## PSCredential support for the `dsc_script` resource
@@ -59,7 +63,7 @@ In Fedora 22 yum has been deprecated in favor of DNF. Unfortunately, while DNF
compatible with yum, the yum provider in Chef is not compatible with DNF. Until a proper `dnf_package`
resource and associated provider is written and merged into core, 12.5.0 has been patched so that the
`yum_package` resource takes a property named `yum_binary` which can be set to point at the yum binary
-to run for all its commands. The `yum_binary` will also default to `yum-deprecated` if the
+to run for all its commands. The `yum_binary` will also default to `yum-deprecated` if the
`/usr/bin/yum-deprecated` command is found on the system. This means that Fedora 22 users can run
something like this early in their chef-client run:
@@ -73,4 +77,3 @@ end
After which the yum-deprecated binary will exist, and the yum provider will find it and should operate
normally and successfully.
-
diff --git a/VERSION b/VERSION
index 9a03cd310d..b7d7205d7e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-12.5.0.current.0
+12.5.0
diff --git a/chef-config/VERSION b/chef-config/VERSION
index 9a03cd310d..b7d7205d7e 100644
--- a/chef-config/VERSION
+++ b/chef-config/VERSION
@@ -1 +1 @@
-12.5.0.current.0
+12.5.0
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index 9579f0638d..ca9e132f7c 100644
--- a/chef-config/lib/chef-config/version.rb
+++ b/chef-config/lib/chef-config/version.rb
@@ -21,7 +21,7 @@
module ChefConfig
CHEFCONFIG_ROOT = File.dirname(File.expand_path(File.dirname(__FILE__)))
- VERSION = '12.5.0.current.0'
+ VERSION = '12.5.0'
end
#
diff --git a/chef.gemspec b/chef.gemspec
index f28cde21e7..b1abe7670a 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -52,5 +52,5 @@ Gem::Specification.new do |s|
s.executables = %w( chef-client chef-solo knife chef-shell chef-apply )
s.require_path = 'lib'
- s.files = %w(Rakefile LICENSE README.md CONTRIBUTING.md) + Dir.glob("{distro,lib,tasks,spec}/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
+ s.files = %w(Gemfile Rakefile LICENSE README.md CONTRIBUTING.md) + Dir.glob("{distro,lib,tasks,spec}/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
end
diff --git a/distro/common/html/knife_cookbook_site.html b/distro/common/html/knife_cookbook_site.html
index 8815961629..60efafa7e1 100644
--- a/distro/common/html/knife_cookbook_site.html
+++ b/distro/common/html/knife_cookbook_site.html
@@ -5,12 +5,12 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-
+
<title>knife cookbook site &mdash; chef-client Man Pages</title>
-
+
<link rel="stylesheet" href="_static/guide.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
-
+
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
@@ -32,13 +32,13 @@
</div>
-
+
<div class="document">
<div class="documentwrapper">
<div class="body">
-
+
<div class="section" id="knife-cookbook-site">
<h1>knife cookbook site<a class="headerlink" href="#knife-cookbook-site" title="Permalink to this headline">¶</a></h1>
<p>The Cookbooks Site API is used to provide access to the cookbooks community hosted at <a class="reference external" href="https://supermarket.getchef.com/cookbooks">https://supermarket.getchef.com/cookbooks</a>. All of the cookbooks in the community are accessible through a RESTful API located at <a class="reference external" href="https://supermarket.getchef.com/api/v1/cookbooks">https://supermarket.getchef.com/api/v1/cookbooks</a> by using any of the supported endpoints. In most cases, using knife and the <strong>knife cookbook site</strong> sub-command (and any of its arguments) is the recommended method of interacting with these cookbooks, but in some cases, using the Cookbooks Site API directly may make sense.</p>
@@ -228,17 +228,17 @@ ant iis redmine
</div>
<p>to return something like:</p>
<div class="highlight-bash"><div class="highlight"><pre>apache2:
- cookbook: http://cookbooks.opscode.com/api/v1/cookbooks/apache2
+ cookbook: https://supermarket.chef.io/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: https://supermarket.chef.io/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: https://supermarket.chef.io/api/v1/cookbooks/kickstart
cookbook_description: Creates apache2 vhost and serves a kickstart file.
cookbook_maintainer: opscode
cookbook_name: kickstart
@@ -311,18 +311,18 @@ 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
+latest_version: https://supermarket.chef.io/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
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/1_0_3
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/1_0_2
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/1_0_1
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/1_0_0
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/0_8_1
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/0_8_0
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/0_7_0
</pre></div>
</div>
<p><strong>Show cookbook data as JSON</strong></p>
@@ -364,7 +364,7 @@ versions:
</div>
-
+
<div class="clearer"></div>
</div>
@@ -372,4 +372,4 @@ versions:
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/distro/common/man/man1/knife-cookbook-site.1 b/distro/common/man/man1/knife-cookbook-site.1
index a90a5305f0..acfcf6b882 100644
--- a/distro/common/man/man1/knife-cookbook-site.1
+++ b/distro/common/man/man1/knife-cookbook-site.1
@@ -364,17 +364,17 @@ to return something like:
.nf
.ft C
apache2:
- cookbook: http://cookbooks.opscode.com/api/v1/cookbooks/apache2
+ cookbook: https://supermarket.chef.io/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: https://supermarket.chef.io/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: https://supermarket.chef.io/api/v1/cookbooks/kickstart
cookbook_description: Creates apache2 vhost and serves a kickstart file.
cookbook_maintainer: opscode
cookbook_name: kickstart
@@ -481,18 +481,18 @@ 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
+latest_version: https://supermarket.chef.io/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
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/1_0_3
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/1_0_2
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/1_0_1
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/1_0_0
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/0_8_1
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/0_8_0
+ https://supermarket.chef.io/api/v1/cookbooks/haproxy/versions/0_7_0
.ft P
.fi
.UNINDENT
diff --git a/external_tests/chef-rewind.gemfile b/external_tests/chef-rewind.gemfile
deleted file mode 100644
index 39f7d6e0e8..0000000000
--- a/external_tests/chef-rewind.gemfile
+++ /dev/null
@@ -1,5 +0,0 @@
-source 'https://rubygems.org'
-
-gemspec(name: 'chef', path: "../")
-
-gem 'chef-rewind', github: 'thommay/chef-rewind'
diff --git a/external_tests/chef-sugar.gemfile b/external_tests/chef-sugar.gemfile
deleted file mode 100644
index 31ef3bb5b8..0000000000
--- a/external_tests/chef-sugar.gemfile
+++ /dev/null
@@ -1,6 +0,0 @@
-source 'https://rubygems.org'
-
-gemspec(name: 'chef', path: "../")
-
-gem 'chef-sugar', github: 'sethvargo/chef-sugar'
-gem 'chefspec'
diff --git a/external_tests/chefspec.gemfile b/external_tests/chefspec.gemfile
deleted file mode 100644
index fb7878afbd..0000000000
--- a/external_tests/chefspec.gemfile
+++ /dev/null
@@ -1,7 +0,0 @@
-source 'https://rubygems.org'
-
-gemspec(name: 'chef', path: "../")
-
-gem 'chefspec', github: 'sethvargo/chefspec', group: :development
-gem 'aruba'
-gem 'yard'
diff --git a/external_tests/foodcritic.gemfile b/external_tests/foodcritic.gemfile
deleted file mode 100644
index a2b71a0d8c..0000000000
--- a/external_tests/foodcritic.gemfile
+++ /dev/null
@@ -1,9 +0,0 @@
-source 'https://rubygems.org'
-
-gemspec(name: 'chef', path: "../")
-
-gem 'foodcritic', github: 'acrmp/foodcritic'
-gem 'cucumber'
-gem 'rubocop'
-gem 'simplecov'
-gem 'minitest'
diff --git a/external_tests/halite.gemfile b/external_tests/halite.gemfile
deleted file mode 100644
index cd8cd05668..0000000000
--- a/external_tests/halite.gemfile
+++ /dev/null
@@ -1,8 +0,0 @@
-source 'https://rubygems.org'
-
-gemspec(name: 'chef', path: "../")
-
-gem 'poise', github: 'poise/poise'
-gem 'halite', github: 'poise/halite'
-gem 'poise-boiler', github: 'poise/poise-boiler'
-gem 'rspec-command', github: 'coderanger/rspec-command'
diff --git a/external_tests/poise.gemfile b/external_tests/poise.gemfile
deleted file mode 100644
index 7d274b7a29..0000000000
--- a/external_tests/poise.gemfile
+++ /dev/null
@@ -1,7 +0,0 @@
-source 'https://rubygems.org'
-
-gemspec(name: 'chef', path: "../")
-
-gem 'poise', github: 'poise/poise'
-gem 'halite', github: 'poise/halite'
-gem 'poise-boiler', github: 'poise/poise-boiler'
diff --git a/lib/chef/chef_class.rb b/lib/chef/chef_class.rb
index b18c3fbdde..6a0d09ec96 100644
--- a/lib/chef/chef_class.rb
+++ b/lib/chef/chef_class.rb
@@ -226,5 +226,10 @@ class Chef
end
end
+ # @api private Only for test dependency injection; not evenly implemented as yet.
+ def self.path_to(path)
+ path
+ end
+
reset!
end
diff --git a/lib/chef/cookbook_site_streaming_uploader.rb b/lib/chef/cookbook_site_streaming_uploader.rb
index 0302a51165..2be189e942 100644
--- a/lib/chef/cookbook_site_streaming_uploader.rb
+++ b/lib/chef/cookbook_site_streaming_uploader.rb
@@ -26,7 +26,7 @@ require 'openssl'
class Chef
# == Chef::CookbookSiteStreamingUploader
# A streaming multipart HTTP upload implementation. Used to upload cookbooks
- # (in tarball form) to http://cookbooks.opscode.com
+ # (in tarball form) to https://supermarket.chef.io
#
# inspired by http://stanislavvitvitskiy.blogspot.com/2008/12/multipart-post-in-ruby.html
class CookbookSiteStreamingUploader
diff --git a/lib/chef/knife/bootstrap/templates/README.md b/lib/chef/knife/bootstrap/templates/README.md
index 13a0fe7ada..b5bca25d8e 100644
--- a/lib/chef/knife/bootstrap/templates/README.md
+++ b/lib/chef/knife/bootstrap/templates/README.md
@@ -1,12 +1,11 @@
This directory contains bootstrap templates which can be used with the -d flag
to 'knife bootstrap' to install Chef in different ways. To simplify installation,
and reduce the matrix of common installation patterns to support, we have
-standardized on the [Omnibus](https://github.com/opscode/omnibus-ruby) built installation
+standardized on the [Omnibus](https://github.com/chef/omnibus) built installation
packages.
The 'chef-full' template downloads a script which is used to determine the correct
-Omnibus package for this system from the [Omnitruck](https://github.com/opscode/opscode-omnitruck) API. All other templates in this directory are deprecated and will be removed
-in the future.
+Omnibus package for this system from the [Omnitruck](https://docs.chef.io/api_omnitruck.html) API.
You can still utilize custom bootstrap templates on your system if your installation
-needs are unique. Additional information can be found on the [docs site](http://docs.opscode.com/knife_bootstrap.html#custom-templates). \ No newline at end of file
+needs are unique. Additional information can be found on the [docs site](https://docs.chef.io/knife_bootstrap.html#custom-templates).
diff --git a/lib/chef/knife/cookbook_create.rb b/lib/chef/knife/cookbook_create.rb
index e17a54079f..97f6e65d3c 100644
--- a/lib/chef/knife/cookbook_create.rb
+++ b/lib/chef/knife/cookbook_create.rb
@@ -48,7 +48,7 @@ class Chef
option :cookbook_copyright,
:short => "-C COPYRIGHT",
:long => "--copyright COPYRIGHT",
- :description => "Name of Copyright holder"
+ :description => "Name of copyright holder"
option :cookbook_email,
:short => "-m EMAIL",
diff --git a/lib/chef/knife/cookbook_site_download.rb b/lib/chef/knife/cookbook_site_download.rb
index c2d72ef8da..3e586e6542 100644
--- a/lib/chef/knife/cookbook_site_download.rb
+++ b/lib/chef/knife/cookbook_site_download.rb
@@ -84,7 +84,7 @@ class Chef
end
def download_cookbook
- ui.info "Downloading #{@name_args[0]} from the cookbooks site at version #{version} to #{download_location}"
+ ui.info "Downloading #{@name_args[0]} from Supermarket at version #{version} to #{download_location}"
noauth_rest.sign_on_redirect = false
tf = noauth_rest.get_rest desired_cookbook_data["file"], true
diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb
index d0ab6da3ef..aee8b7fa94 100644
--- a/lib/chef/knife/cookbook_site_install.rb
+++ b/lib/chef/knife/cookbook_site_install.rb
@@ -93,7 +93,7 @@ class Chef
# TODO: it'd be better to store these outside the cookbook repo and
# keep them around, e.g., in ~/Library/Caches on OS X.
- ui.info("removing downloaded tarball")
+ ui.info("Removing downloaded tarball")
File.unlink(upstream_file)
if @repo.finalize_updates_to(@cookbook_name, downloader.version)
diff --git a/lib/chef/knife/cookbook_site_share.rb b/lib/chef/knife/cookbook_site_share.rb
index efd2e7f129..beb98b71b8 100644
--- a/lib/chef/knife/cookbook_site_share.rb
+++ b/lib/chef/knife/cookbook_site_share.rb
@@ -48,7 +48,7 @@ class Chef
:short => '-n',
:boolean => true,
:default => false,
- :description => "Don't take action, only print what files will be upload to SuperMarket."
+ :description => "Don't take action, only print what files will be uploaded to Supermarket."
def run
config[:cookbook_path] ||= Chef::Config[:cookbook_path]
@@ -94,7 +94,7 @@ class Chef
Chef::Log.debug("Removing local staging directory at #{tmp_cookbook_dir}")
FileUtils.rm_rf tmp_cookbook_dir
rescue => e
- ui.error("Error uploading cookbook #{cookbook_name} to the Opscode Cookbook Site: #{e.message}. Increase log verbosity (-VV) for more information.")
+ ui.error("Error uploading cookbook #{cookbook_name} to Supermarket: #{e.message}. Increase log verbosity (-VV) for more information.")
Chef::Log.debug("\n#{e.backtrace.join("\n")}")
exit(1)
end
@@ -108,15 +108,15 @@ class Chef
def get_category(cookbook_name)
begin
- data = noauth_rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{@name_args[0]}")
+ data = noauth_rest.get_rest("https://supermarket.chef.io/api/v1/cookbooks/#{@name_args[0]}")
if !data["category"] && data["error_code"]
- ui.fatal("Received an error from the Opscode Cookbook site: #{data["error_code"]}. On the first time you upload it, you are required to specify the category you want to share this cookbook to.")
+ ui.fatal("Received an error from Supermarket: #{data["error_code"]}. On the first time you upload it, you are required to specify the category you want to share this cookbook to.")
exit(1)
else
data['category']
end
rescue => e
- ui.fatal("Unable to reach Opscode Cookbook Site: #{e.message}. Increase log verbosity (-VV) for more information.")
+ ui.fatal("Unable to reach Supermarket: #{e.message}. Increase log verbosity (-VV) for more information.")
Chef::Log.debug("\n#{e.backtrace.join("\n")}")
exit(1)
end
@@ -136,7 +136,7 @@ class Chef
if http_resp.code.to_i != 201
if res['error_messages']
if res['error_messages'][0] =~ /Version already exists/
- ui.error "The same version of this cookbook already exists on the Opscode Cookbook Site."
+ ui.error "The same version of this cookbook already exists on Supermarket."
exit(1)
else
ui.error "#{res['error_messages'][0]}"
diff --git a/lib/chef/knife/search.rb b/lib/chef/knife/search.rb
index 2b0c79ff6c..014fc8dd87 100644
--- a/lib/chef/knife/search.rb
+++ b/lib/chef/knife/search.rb
@@ -136,7 +136,7 @@ class Chef
def read_cli_args
if config[:query]
if @name_args[1]
- ui.error "please specify query as an argument or an option via -q, not both"
+ ui.error "Please specify query as an argument or an option via -q, not both"
ui.msg opt_parser
exit 1
end
@@ -145,7 +145,7 @@ class Chef
else
case name_args.size
when 0
- ui.error "no query specified"
+ ui.error "No query specified"
ui.msg opt_parser
exit 1
when 1
diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb
index bb3d9d78bb..62af853e88 100644
--- a/lib/chef/knife/ssh.rb
+++ b/lib/chef/knife/ssh.rb
@@ -425,7 +425,7 @@ class Chef
begin
require 'appscript'
rescue LoadError
- STDERR.puts "you need the rb-appscript gem to use knife ssh macterm. `(sudo) gem install rb-appscript` to install"
+ STDERR.puts "You need the rb-appscript gem to use knife ssh macterm. `(sudo) gem install rb-appscript` to install"
raise
end
diff --git a/lib/chef/mixin/which.rb b/lib/chef/mixin/which.rb
index 4179c97b62..4e1c516386 100644
--- a/lib/chef/mixin/which.rb
+++ b/lib/chef/mixin/which.rb
@@ -28,7 +28,7 @@ class Chef
paths = ENV['PATH'].split(File::PATH_SEPARATOR) + extra_path
paths.each do |path|
filename = File.join(path, cmd)
- return filename if File.executable?(filename)
+ return filename if File.executable?(Chef.path_to(filename))
end
false
end
diff --git a/lib/chef/platform/service_helpers.rb b/lib/chef/platform/service_helpers.rb
index d50812e687..8365141c6e 100644
--- a/lib/chef/platform/service_helpers.rb
+++ b/lib/chef/platform/service_helpers.rb
@@ -19,6 +19,7 @@
# XXX: mixing shellout into a mixin into classes has to be code smell
require 'chef/mixin/shell_out'
require 'chef/mixin/which'
+require 'chef/chef_class'
class Chef
class Platform
@@ -42,56 +43,56 @@ class Chef
# different services is NOT a design concern of this module.
#
def service_resource_providers
- @service_resource_providers ||= [].tap do |service_resource_providers|
+ providers = []
- if ::File.exist?("/usr/sbin/update-rc.d")
- service_resource_providers << :debian
- end
-
- if ::File.exist?("/usr/sbin/invoke-rc.d")
- service_resource_providers << :invokercd
- end
+ if ::File.exist?(Chef.path_to("/usr/sbin/update-rc.d"))
+ providers << :debian
+ end
- if ::File.exist?("/sbin/insserv")
- service_resource_providers << :insserv
- end
+ if ::File.exist?(Chef.path_to("/usr/sbin/invoke-rc.d"))
+ providers << :invokercd
+ end
- # debian >= 6.0 has /etc/init but does not have upstart
- if ::File.exist?("/etc/init") && ::File.exist?("/sbin/start")
- service_resource_providers << :upstart
- end
+ if ::File.exist?(Chef.path_to("/sbin/insserv"))
+ providers << :insserv
+ end
- if ::File.exist?("/sbin/chkconfig")
- service_resource_providers << :redhat
- end
+ # debian >= 6.0 has /etc/init but does not have upstart
+ if ::File.exist?(Chef.path_to("/etc/init")) && ::File.exist?(Chef.path_to("/sbin/start"))
+ providers << :upstart
+ end
- if systemd_sanity_check?
- service_resource_providers << :systemd
- end
+ if ::File.exist?(Chef.path_to("/sbin/chkconfig"))
+ providers << :redhat
+ end
+ if systemd_sanity_check?
+ providers << :systemd
end
+
+ providers
end
def config_for_service(service_name)
configs = []
- if ::File.exist?("/etc/init.d/#{service_name}")
+ if ::File.exist?(Chef.path_to("/etc/init.d/#{service_name}"))
configs << :initd
end
- if ::File.exist?("/etc/init/#{service_name}.conf")
+ if ::File.exist?(Chef.path_to("/etc/init/#{service_name}.conf"))
configs << :upstart
end
- if ::File.exist?("/etc/xinetd.d/#{service_name}")
+ if ::File.exist?(Chef.path_to("/etc/xinetd.d/#{service_name}"))
configs << :xinetd
end
- if ::File.exist?("/etc/rc.d/#{service_name}")
+ if ::File.exist?(Chef.path_to("/etc/rc.d/#{service_name}"))
configs << :etc_rcd
end
- if ::File.exist?("/usr/local/etc/rc.d/#{service_name}")
+ if ::File.exist?(Chef.path_to("/usr/local/etc/rc.d/#{service_name}"))
configs << :usr_local_etc_rcd
end
@@ -105,14 +106,11 @@ class Chef
private
def systemctl_path
- if @systemctl_path.nil?
- @systemctl_path = which("systemctl")
- end
- @systemctl_path
+ which("systemctl")
end
def systemd_sanity_check?
- systemctl_path && File.exist?("/proc/1/comm") && File.open("/proc/1/comm").gets.chomp == "systemd"
+ systemctl_path && File.exist?(Chef.path_to("/proc/1/comm")) && File.open(Chef.path_to("/proc/1/comm")).gets.chomp == "systemd"
end
def extract_systemd_services(command)
@@ -126,7 +124,7 @@ class Chef
# this splits off the suffix after the last dot to return "sshd"
services += services.select {|s| s.match(/\.service$/) }.map { |s| s.sub(/(.*)\.service$/, '\1') }
rescue Mixlib::ShellOut::ShellCommandFailed
- false
+ []
end
def platform_has_systemd_unit?(service_name)
diff --git a/lib/chef/policy_builder/expand_node_object.rb b/lib/chef/policy_builder/expand_node_object.rb
index 26b98afa52..933960a429 100644
--- a/lib/chef/policy_builder/expand_node_object.rb
+++ b/lib/chef/policy_builder/expand_node_object.rb
@@ -33,6 +33,9 @@ class Chef
# expands the run_list on a node object and then queries the chef-server
# to find the correct set of cookbooks, given version constraints of the
# node's environment.
+ #
+ # Note that this class should only be used via PolicyBuilder::Dynamic and
+ # not instantiated directly.
class ExpandNodeObject
attr_reader :events
@@ -94,6 +97,33 @@ class Chef
run_context
end
+ # DEPRECATED: As of Chef 12.5, chef selects either policyfile mode or
+ # "expand node" mode dynamically, based on the content of the node
+ # object, first boot JSON, and config. This happens in
+ # PolicyBuilder::Dynamic, which selects the implementation during
+ # #load_node and then delegates to either ExpandNodeObject or Policyfile
+ # implementations as appropriate. Tools authors should update their code
+ # to create a PolicyBuilder::Dynamc policy builder and allow it to select
+ # the proper implementation.
+ def load_node
+ Chef.log_deprecation("ExpandNodeObject#load_node is deprecated. Please use Chef::PolicyBuilder::Dynamic instead of using ExpandNodeObject directly")
+
+ events.node_load_start(node_name, config)
+ Chef::Log.debug("Building node object for #{node_name}")
+
+ @node =
+ if Chef::Config[:solo]
+ Chef::Node.build(node_name)
+ else
+ Chef::Node.find_or_create(node_name)
+ end
+ finish_load_node(node)
+ node
+ rescue Exception => e
+ events.node_load_failed(node_name, e, config)
+ raise
+ end
+
def finish_load_node(node)
@node = node
end
diff --git a/lib/chef/property.rb b/lib/chef/property.rb
index 2b151b350a..c1207d9132 100644
--- a/lib/chef/property.rb
+++ b/lib/chef/property.rb
@@ -422,7 +422,16 @@ class Chef
# @return [Property] The new property type.
#
def derive(**modified_options)
- Property.new(**options.merge(**modified_options))
+ # Since name_property, name_attribute and default override each other,
+ # if you specify one of them in modified_options it overrides anything in
+ # the original options.
+ options = self.options
+ if modified_options.has_key?(:name_property) ||
+ modified_options.has_key?(:name_attribute) ||
+ modified_options.has_key?(:default)
+ options = options.reject { |k,v| k == :name_attribute || k == :name_property || k == :default }
+ end
+ Property.new(options.merge(modified_options))
end
#
diff --git a/lib/chef/provider/package/rpm.rb b/lib/chef/provider/package/rpm.rb
index c5d52a8384..6ce0dd689f 100644
--- a/lib/chef/provider/package/rpm.rb
+++ b/lib/chef/provider/package/rpm.rb
@@ -61,7 +61,7 @@ class Chef
Chef::Log.debug("#{@new_resource} checking rpm status")
shell_out_with_timeout!("rpm -qp --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{@new_resource.source}").stdout.each_line do |line|
case line
- when /^([\w\d+_.-]+)\s([\w\d~_.-]+)$/
+ when /^(\S+)\s(\S+)$/
@current_resource.package_name($1)
@new_resource.version($2)
@candidate_version = $2
@@ -78,7 +78,7 @@ class Chef
@rpm_status = shell_out_with_timeout("rpm -q --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{@current_resource.package_name}")
@rpm_status.stdout.each_line do |line|
case line
- when /^([\w\d+_.-]+)\s([\w\d~_.-]+)$/
+ when /^(\S+)\s(\S+)$/
Chef::Log.debug("#{@new_resource} current version is #{$2}")
@current_resource.version($2)
end
diff --git a/lib/chef/provider/remote_directory.rb b/lib/chef/provider/remote_directory.rb
index 56c2ff0caf..3c1c50b963 100644
--- a/lib/chef/provider/remote_directory.rb
+++ b/lib/chef/provider/remote_directory.rb
@@ -161,7 +161,7 @@ class Chef
def files_to_transfer
cookbook = run_context.cookbook_collection[resource_cookbook]
files = cookbook.relative_filenames_in_preferred_directory(node, :files, source)
- files.sort!.reverse!
+ files.sort_by! { |x| x.count(::File::SEPARATOR) }
end
# Either the explicit cookbook that the user sets on the resource, or the implicit
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index 0c8d3d1a48..b2a4b13ea4 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -522,6 +522,9 @@ ERROR_MESSAGE
ChildRunContext.new(self)
end
+ # @api private
+ attr_writer :resource_collection
+
protected
attr_reader :cookbook_compiler
@@ -532,11 +535,6 @@ ERROR_MESSAGE
###
# These need to be settable so deploy can run a resource_collection
# independent of any cookbooks via +recipe_eval+
- def resource_collection=(value)
- Chef.log_deprecation("Setting run_context.resource_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
- @resource_collection = value
- end
-
def audits=(value)
Chef.log_deprecation("Setting run_context.audits will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
@audits = value
diff --git a/lib/chef/run_lock.rb b/lib/chef/run_lock.rb
index cefe637db6..9e0952bdcb 100644
--- a/lib/chef/run_lock.rb
+++ b/lib/chef/run_lock.rb
@@ -87,27 +87,8 @@ class Chef
# 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,'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
+ create_lock
+ acquire_lock
end
#
@@ -147,6 +128,34 @@ class Chef
end
end
+ # @api private solely for race condition tests
+ def create_lock
+ # ensure the runlock_file path exists
+ create_path(File.dirname(runlock_file))
+ @runlock = File.open(runlock_file,'a+')
+ end
+
+ # @api private solely for race condition tests
+ def acquire_lock
+ 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
+ end
+
private
def reset
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index faa61aee54..c0ff754873 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -21,7 +21,7 @@
class Chef
CHEF_ROOT = File.dirname(File.expand_path(File.dirname(__FILE__)))
- VERSION = '12.5.0.current.0'
+ VERSION = '12.5.0'
end
#
diff --git a/spec/functional/run_lock_spec.rb b/spec/functional/run_lock_spec.rb
index ce0598bead..78b3847d19 100644
--- a/spec/functional/run_lock_spec.rb
+++ b/spec/functional/run_lock_spec.rb
@@ -34,8 +34,15 @@ describe Chef::RunLock do
let(:lockfile){ "#{random_temp_root}/this/long/path/does/not/exist/chef-client-running.pid" }
# make sure to start with a clean slate.
- before(:each){ FileUtils.rm_r(random_temp_root) if File.exist?(random_temp_root) }
- after(:each){ FileUtils.rm_r(random_temp_root) if File.exist?(random_temp_root) }
+ before(:each){ log_event("rm -rf before"); FileUtils.rm_r(random_temp_root) if File.exist?(random_temp_root) }
+ after(:each){ log_event("rm -rf after"); FileUtils.rm_r(random_temp_root) if File.exist?(random_temp_root) }
+
+ def log_event(message, time=Time.now.strftime("%H:%M:%S.%L"))
+ events << [ message, time ]
+ end
+ def events
+ @events ||= []
+ end
WAIT_ON_LOCK_TIME = 1.0
def wait_on_lock
@@ -48,118 +55,90 @@ describe Chef::RunLock do
raise "Lockfile never created, abandoning test"
end
- ##
- # Side channel via a pipe allows child processes to send errors to the parent
-
- # Don't lazy create the pipe or else we might not share it with subprocesses
- let!(:error_pipe) do
- r,w = IO.pipe
- w.sync = true
- [r,w]
- end
-
- let(:error_read) { error_pipe[0] }
- let(:error_write) { error_pipe[1] }
-
- after do
- error_read.close unless error_read.closed?
- error_write.close unless error_write.closed?
- end
-
- # Send a RuntimeError from the child process to the parent process. Also
- # prints error to $stdout, just in case something goes wrong with the error
- # marshaling stuff.
- def send_side_channel_error(message)
- $stderr.puts(message)
- $stderr.puts(caller)
- e = RuntimeError.new(message)
- error_write.print(Marshal.dump(e))
- end
+ CLIENT_PROCESS_TIMEOUT = 10
+ BREATHING_ROOM = 1
- # Read the error (if any) from the error channel. If a marhaled error is
- # present, it is unmarshaled and raised (which will fail the test)
- def raise_side_channel_error!
- error_write.close
- err = error_read.read
- error_read.close
+ # ClientProcess is defined below
+ let!(:p1) { ClientProcess.new(self, 'p1') }
+ let!(:p2) { ClientProcess.new(self, 'p2') }
+ after(:each) do |example|
begin
- # ArgumentError from Marshal.load indicates no data, which we assume
- # means no error in child process.
- raise Marshal.load(err)
- rescue ArgumentError
- nil
+ p1.stop
+ p2.stop
+ rescue
+ example.exception = $!
+ raise
+ ensure
+ if example.exception
+ print_events
+ end
end
end
- ##
- # Interprocess synchronization via a pipe. This allows us to control the
- # state of the processes competing over the lock without relying on sleep.
-
- let!(:sync_pipe) do
- r,w = IO.pipe
- w.sync = true
- [r,w]
- end
- let(:sync_read) { sync_pipe[0] }
- let(:sync_write) { sync_pipe[1] }
-
- after do
- sync_read.close unless sync_read.closed?
- sync_write.close unless sync_write.closed?
- end
-
- # Wait on synchronization signal. If not received within the timeout, an
- # error is sent via the error channel, and the process exits.
- def sync_wait
- if IO.select([sync_read], nil, nil, 20).nil?
- # timeout reading from the sync pipe.
- send_side_channel_error("Error syncing processes in run lock test (timeout)")
- exit!(1)
- else
- sync_read.getc
+ def print_events
+ # Consume any remaining events that went on the channel and print them all
+ p1.last_event
+ p2.last_event
+ events.each_with_index.sort_by { |(message, time), index| [ time, index ] }.each do |(message, time), index|
+ print "#{time} #{message}\n"
end
end
- # Sends a character in the sync pipe, which wakes ("unlocks") another
- # process that is waiting on the sync signal
- def sync_send
- sync_write.putc("!")
- sync_write.flush
- end
+ context "when the lockfile does not already exist" do
+ context "when a client creates the lockfile but has not yet acquired the lock" do
+ before { p1.run_to("created lock") }
+ shared_context "second client gets the lock" do
+ it "the lockfile is created" do
+ log_event("lockfile exists? #{File.exist?(lockfile)}")
+ expect(File.exist?(lockfile)).to be_truthy
+ end
- ##
- # IPC to record test results in a pipe. Tests can read pipe contents to
- # check that operations occur in the expected order.
+ it "the lockfile is not locked" do
+ run_lock = Chef::RunLock.new(lockfile)
+ begin
+ expect(run_lock.test).to be_truthy
+ ensure
+ run_lock.release
+ end
+ end
- let!(:results_pipe) do
- r,w = IO.pipe
- w.sync = true
- [r,w]
- end
- let(:results_read) { results_pipe[0] }
- let(:results_write) { results_pipe[1] }
+ it "the lockfile is empty" do
+ expect(IO.read(lockfile)).to eq('')
+ end
- after do
- results_read.close unless results_read.closed?
- results_write.close unless results_write.closed?
- end
+ context "and a second client gets the lock" do
+ before { p2.run_to("acquired lock") }
+ it "the first client does not get the lock until the second finishes" do
+ p1.run_to("acquired lock") do
+ p2.run_to_completion
+ end
+ end
+ it "and the first client tries to get the lock and the second is killed, the first client gets the lock immediately" do
+ p1.run_to("acquired lock") do
+ sleep BREATHING_ROOM
+ expect(p1.last_event).to match(/after (started|created lock)/)
+ p2.stop
+ end
+ p1.run_to_completion
+ end
+ end
+ end
- CLIENT_PROCESS_TIMEOUT = 2
- BREATHING_ROOM = 1
+ context "and the second client has done nothing" do
+ include_context "second client gets the lock"
+ end
- # ClientProcess is defined below
- let!(:p1) { ClientProcess.new(self, 'p1') }
- let!(:p2) { ClientProcess.new(self, 'p2') }
- after do
- p1.stop
- p2.stop
- end
+ context "and the second client has created the lockfile but not yet acquired the lock" do
+ before { p2.run_to("created lock") }
+ include_context "second client gets the lock"
+ end
+ end
- context "when the lockfile does not already exist" do
context "when a client acquires the lock but has not yet saved the pid" do
before { p1.run_to("acquired lock") }
it "the lockfile is created" do
+ log_event("lockfile exists? #{File.exist?(lockfile)}")
expect(File.exist?(lockfile)).to be_truthy
end
@@ -186,7 +165,7 @@ describe Chef::RunLock do
p2.run_to("acquired lock") do
# While p2 is trying to acquire, wait a bit and then let p1 complete
sleep(BREATHING_ROOM)
- expect(p2.last_event).to eq("started")
+ expect(p2.last_event).to match(/after (started|created lock)/)
p1.run_to_completion
end
@@ -196,7 +175,7 @@ describe Chef::RunLock do
it "and a second client tries to get the lock and the first is killed, the second client gets the lock immediately" do
p2.run_to("acquired lock") do
sleep BREATHING_ROOM
- expect(p2.last_event).to eq("started")
+ expect(p2.last_event).to match(/after (started|created lock)/)
p1.stop
end
p2.run_to_completion
@@ -233,7 +212,7 @@ describe Chef::RunLock do
p2.run_to("acquired lock") do
# While p2 is trying to acquire, wait a bit and then let p1 complete
sleep(BREATHING_ROOM)
- expect(p2.last_event).to eq("started")
+ expect(p2.last_event).to match(/after (started|created lock)/)
p1.run_to_completion
end
@@ -243,7 +222,7 @@ describe Chef::RunLock do
it "when a second client tries to get the lock and the first is killed, the second client gets the lock immediately" do
p2.run_to("acquired lock") do
sleep BREATHING_ROOM
- expect(p2.last_event).to eq("started")
+ expect(p2.last_event).to match(/after (started|created lock)/)
p1.stop
end
p2.run_to_completion
@@ -341,73 +320,97 @@ describe Chef::RunLock do
attr_reader :name
attr_reader :pid
- def fire_event(event)
- # Let the caller know what event we've reached
- write_to_tests.puts(event)
-
- # Block until the client tells us where to stop
- if !@run_to_event || event == @run_to_event
- @run_to_event = read_from_tests.gets.strip
- end
- end
-
def last_event
while true
- event = readline_nonblock(read_from_process)
- break if event.nil?
- @last_event = event.strip
+ line = readline_nonblock(read_from_process)
+ break if line.nil?
+ event, time = line.split("@")
+ example.log_event("#{name}.last_event got #{event}")
+ example.log_event("[#{name}] #{event}", time.strip)
+ @last_event = event
end
@last_event
end
- def run_to(event, &background_block)
+ def run_to(to_event, &background_block)
+ example.log_event("#{name}.run_to(#{to_event.inspect})")
+
# Start the process if it's not started
start if !pid
# Tell the process what to stop at (also means it can go)
- write_to_process.puts event
+ write_to_process.print "#{to_event}\n"
# Run the background block
background_block.call if background_block
# Wait until it gets there
Timeout::timeout(CLIENT_PROCESS_TIMEOUT) do
- until @last_event == event
- @last_event = read_from_process.gets.strip
+ until @last_event == "after #{to_event}"
+ got_event, time = read_from_process.gets.split("@")
+ example.log_event("#{name}.last_event got #{got_event}")
+ example.log_event("[#{name}] #{got_event}", time.strip)
+ @last_event = got_event
end
end
+
+ example.log_event("#{name}.run_to(#{to_event.inspect}) finished")
end
def run_to_completion
+ example.log_event("#{name}.run_to_completion")
# Start the process if it's not started
start if !pid
# Tell the process to stop at nothing (no blocking)
- @write_to_process.puts "nothing"
+ @write_to_process.print "nothing\n"
# Wait for the process to exit
wait_for_exit
+ example.log_event("#{name}.run_to_completion finished")
end
def wait_for_exit
+ example.log_event("#{name}.wait_for_exit (pid #{pid})")
Timeout::timeout(CLIENT_PROCESS_TIMEOUT) do
Process.wait(pid) if pid
end
+ example.log_event("#{name}.wait_for_exit finished (pid #{pid})")
end
def stop
if pid
+ example.log_event("#{name}.stop (pid #{pid})")
begin
- Process.kill(:KILL, pid)
+ # Send it the kill signal over and over until it dies
Timeout::timeout(CLIENT_PROCESS_TIMEOUT) do
- Process.waitpid2(pid)
+ Process.kill(:KILL, pid)
+ while !Process.waitpid2(pid, Process::WNOHANG)
+ sleep(0.05)
+ end
end
+ example.log_event("#{name}.stop finished (stopped pid #{pid})")
# Process not found is perfectly fine when we're trying to kill a process :)
rescue Errno::ESRCH
+ example.log_event("#{name}.stop finished (pid #{pid} wasn't running)")
end
end
end
+ def fire_event(event)
+ # Let the caller know what event we've reached
+ write_to_tests.print("after #{event}@#{Time.now.strftime("%H:%M:%S.%L")}\n")
+
+ # Block until the client tells us where to stop
+ if !@run_to_event || event == @run_to_event
+ write_to_tests.print("waiting for instructions after #{event}@#{Time.now.strftime("%H:%M:%S.%L")}\n")
+ @run_to_event = read_from_tests.gets.strip
+ write_to_tests.print("told to run to #{@run_to_event} after #{event}@#{Time.now.strftime("%H:%M:%S.%L")}\n")
+ elsif @run_to_event
+ write_to_tests.print("continuing until #{@run_to_event} after #{event}@#{Time.now.strftime("%H:%M:%S.%L")}\n")
+ end
+ end
+
private
attr_reader :read_from_process
@@ -415,18 +418,34 @@ describe Chef::RunLock do
attr_reader :read_from_tests
attr_reader :write_to_process
+ class TestRunLock < Chef::RunLock
+ attr_accessor :client_process
+ def create_lock
+ super
+ client_process.fire_event("created lock")
+ end
+ end
+
def start
+ example.log_event("#{name}.start")
@pid = fork do
- Timeout::timeout(CLIENT_PROCESS_TIMEOUT) do
- run_lock = Chef::RunLock.new(example.lockfile)
- fire_event("started")
- run_lock.acquire
- fire_event("acquired lock")
- run_lock.save_pid
- fire_event("saved pid")
- exit!(0)
+ begin
+ Timeout::timeout(CLIENT_PROCESS_TIMEOUT) do
+ run_lock = TestRunLock.new(example.lockfile)
+ run_lock.client_process = self
+ fire_event("started")
+ run_lock.acquire
+ fire_event("acquired lock")
+ run_lock.save_pid
+ fire_event("saved pid")
+ exit!(0)
+ end
+ rescue
+ fire_event($!.message.lines.join(" // "))
+ raise
end
end
+ example.log_event("#{name}.start forked (pid #{pid})")
end
def readline_nonblock(fd)
diff --git a/spec/integration/recipes/remote_directory.rb b/spec/integration/recipes/remote_directory.rb
new file mode 100644
index 0000000000..a1988ccd52
--- /dev/null
+++ b/spec/integration/recipes/remote_directory.rb
@@ -0,0 +1,74 @@
+require 'support/shared/integration/integration_helper'
+
+describe Chef::Resource::RemoteDirectory do
+ include IntegrationSupport
+ include Chef::Mixin::ShellOut
+
+ # Until Cheffish::RSpec has cookbook support, we have to run the whole client
+ let(:chef_dir) { File.join(File.dirname(__FILE__), "..", "..", "..", "bin") }
+
+ # Invoke `chef-client` as `ruby PATH/TO/chef-client`. This ensures the
+ # following constraints are satisfied:
+ # * Windows: windows can only run batch scripts as bare executables. Rubygems
+ # creates batch wrappers for installed gems, but we don't have batch wrappers
+ # in the source tree.
+ # * Other `chef-client` in PATH: A common case is running the tests on a
+ # machine that has omnibus chef installed. In that case we need to ensure
+ # we're running `chef-client` from the source tree and not the external one.
+ # cf. CHEF-4914
+ let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" }
+
+ when_the_repository "has a cookbook with a source_dir with two subdirectories, each with one file and subdir in a different alphabetical order" do
+ before do
+ file 'config/client.rb', <<-EOM
+ local_mode true
+ cookbook_path "#{path_to('cookbooks')}"
+ EOM
+ directory "cookbooks/test" do
+ directory "files/default/source_dir" do
+ directory "sub1" do
+ file "aaa", ""
+ file "zzz/file", ""
+ end
+ directory "sub2" do
+ file "aaa/file", ""
+ file "zzz", ""
+ end
+ end
+ end
+ end
+
+ context "and a recipe is run with a remote_directory that syncs source_dir with different mode and file_mode" do
+ let!(:dest_dir) { path_to("dest_dir") }
+ before do
+ directory "cookbooks/test" do
+ file "recipes/default.rb", <<-EOM
+ remote_directory #{dest_dir.inspect} do
+ source "source_dir"
+ mode "0754"
+ files_mode 0777
+ end
+ EOM
+ end
+ shell_out!("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'test::default'", :cwd => chef_dir)
+ end
+
+ def mode_of(path)
+ path = path_to(path)
+ stat = File.stat(path)
+ (stat.mode & 0777).to_s(8)
+ end
+
+ it "creates all directories and files with the correct permissions" do
+ expect(mode_of("dest_dir/sub1")).to eq "754"
+ expect(mode_of("dest_dir/sub1/aaa")).to eq "777"
+ expect(mode_of("dest_dir/sub1/zzz")).to eq "754"
+ expect(mode_of("dest_dir/sub1/zzz/file")).to eq "777"
+ expect(mode_of("dest_dir/sub2")).to eq "754"
+ expect(mode_of("dest_dir/sub2/aaa")).to eq "754"
+ expect(mode_of("dest_dir/sub2/aaa/file")).to eq "777"
+ expect(mode_of("dest_dir/sub2/zzz")).to eq "777"
+ end
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index aadf55f64b..92a4daf6d5 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -73,6 +73,7 @@ require 'spec/support/local_gems.rb' if File.exists?(File.join(File.dirname(__FI
# Explicitly require spec helpers that need to load first
require 'spec/support/platform_helpers'
+require 'spec/support/shared/unit/mock_shellout'
# Autoloads support files
# Excludes support/platforms by default
@@ -98,6 +99,7 @@ TEST_PLATFORM_VERSION = TEST_NODE['platform_version']
RSpec.configure do |config|
config.include(Matchers)
+ config.include(MockShellout::RSpec)
config.filter_run :focus => true
config.filter_run_excluding :external => true
diff --git a/spec/support/shared/unit/mock_shellout.rb b/spec/support/shared/unit/mock_shellout.rb
new file mode 100644
index 0000000000..7c3e49ec82
--- /dev/null
+++ b/spec/support/shared/unit/mock_shellout.rb
@@ -0,0 +1,46 @@
+#
+# Author:: John Keiser <jkeiser@chef.io>
+# Copyright:: Copyright (c) 2015 John Keiser.
+# 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.
+#
+
+#
+# Mocks shellout results. Examples:
+# mock_shellout_command("systemctl --all", exitstatus: 1)
+#
+class MockShellout
+ module RSpec
+ def mock_shellout_command(command, **result)
+ allow(::Mixlib::ShellOut).to receive(:new).with(command, anything).and_return MockShellout.new(result)
+ end
+ end
+
+ def initialize(**properties)
+ @properties = {
+ stdout: "",
+ stderr: "",
+ exitstatus: 0
+ }.merge(properties)
+ end
+ def method_missing(name, *args)
+ @properties[name.to_sym]
+ end
+ def error?
+ exitstatus != 0
+ end
+ def error!
+ raise Mixlib::ShellOut::ShellCommandFailed, "Expected process to exit with 0, but received #{exitstatus}" if error?
+ end
+end
diff --git a/spec/unit/knife/cookbook_site_share_spec.rb b/spec/unit/knife/cookbook_site_share_spec.rb
index 76e4ec730e..a7caca9744 100644
--- a/spec/unit/knife/cookbook_site_share_spec.rb
+++ b/spec/unit/knife/cookbook_site_share_spec.rb
@@ -78,21 +78,21 @@ describe Chef::Knife::CookbookSiteShare do
it 'should not fail when given only 1 argument and can determine category' do
@knife.name_args = ['cookbook_name']
- expect(@noauth_rest).to receive(:get_rest).with("http://cookbooks.opscode.com/api/v1/cookbooks/cookbook_name").and_return(@category_response)
+ expect(@noauth_rest).to receive(:get_rest).with("https://supermarket.chef.io/api/v1/cookbooks/cookbook_name").and_return(@category_response)
expect(@knife).to receive(:do_upload)
@knife.run
end
it 'should print error and exit when given only 1 argument and cannot determine category' do
@knife.name_args = ['cookbook_name']
- expect(@noauth_rest).to receive(:get_rest).with("http://cookbooks.opscode.com/api/v1/cookbooks/cookbook_name").and_return(@bad_category_response)
+ expect(@noauth_rest).to receive(:get_rest).with("https://supermarket.chef.io/api/v1/cookbooks/cookbook_name").and_return(@bad_category_response)
expect(@knife.ui).to receive(:fatal)
expect { @knife.run }.to raise_error(SystemExit)
end
it 'should print error and exit when given only 1 argument and Chef::REST throws an exception' do
@knife.name_args = ['cookbook_name']
- expect(@noauth_rest).to receive(:get_rest).with("http://cookbooks.opscode.com/api/v1/cookbooks/cookbook_name") { raise Errno::ECONNREFUSED, "Connection refused" }
+ expect(@noauth_rest).to receive(:get_rest).with("https://supermarket.chef.io/api/v1/cookbooks/cookbook_name") { raise Errno::ECONNREFUSED, "Connection refused" }
expect(@knife.ui).to receive(:fatal)
expect { @knife.run }.to raise_error(SystemExit)
end
diff --git a/spec/unit/policy_builder/expand_node_object_spec.rb b/spec/unit/policy_builder/expand_node_object_spec.rb
index 815926ffb7..306d677108 100644
--- a/spec/unit/policy_builder/expand_node_object_spec.rb
+++ b/spec/unit/policy_builder/expand_node_object_spec.rb
@@ -34,6 +34,14 @@ describe Chef::PolicyBuilder::ExpandNodeObject do
expect(policy_builder).to respond_to(:node)
end
+ it "implements a load_node method for backwards compatibility until Chef 13" do
+ expect(policy_builder).to respond_to(:load_node)
+ end
+
+ it "has removed the deprecated #load_node method", :chef_gte_13_only do
+ expect(policy_builder).to_not respond_to(:load_node)
+ end
+
it "implements a finish_load_node method" do
expect(policy_builder).to respond_to(:finish_load_node)
end
@@ -98,6 +106,27 @@ describe Chef::PolicyBuilder::ExpandNodeObject do
end
+ context "deprecated #load_node method" do
+
+ let(:node) do
+ node = Chef::Node.new
+ node.name(node_name)
+ node.run_list(["recipe[a::default]", "recipe[b::server]"])
+ node
+ end
+
+ before do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ expect(Chef::Node).to receive(:find_or_create).with(node_name).and_return(node)
+ policy_builder.load_node
+ end
+
+ it "loads the node" do
+ expect(policy_builder.node).to eq(node)
+ end
+
+ end
+
context "once the node has been loaded" do
let(:node) do
node = Chef::Node.new
diff --git a/spec/unit/property_spec.rb b/spec/unit/property_spec.rb
index 64638d9be9..9ecf7a4cde 100644
--- a/spec/unit/property_spec.rb
+++ b/spec/unit/property_spec.rb
@@ -107,6 +107,56 @@ describe "Chef::Resource.property" do
end
end
+ with_property ":x, name_property: true" do
+ context "and subclass" do
+ let(:subresource_class) do
+ new_resource_name = self.class.new_resource_name
+ Class.new(resource_class) do
+ resource_name new_resource_name
+ end
+ end
+ let(:subresource) do
+ subresource_class.new('blah')
+ end
+
+ context "with property :x on the subclass" do
+ before do
+ subresource_class.class_eval do
+ property :x
+ end
+ end
+
+ it "x is still name_property" do
+ expect(subresource.x).to eq 'blah'
+ end
+ end
+
+ context "with property :x, name_attribute: false on the subclass" do
+ before do
+ subresource_class.class_eval do
+ property :x, name_attribute: false
+ end
+ end
+
+ it "x is no longer name_property" do
+ expect(subresource.x).to be_nil
+ end
+ end
+
+ context "with property :x, default: 10 on the subclass" do
+ before do
+ subresource_class.class_eval do
+ property :x, default: 10
+ end
+ end
+
+ it "x is no longer name_property" do
+ expect(subresource.x).to eq(10)
+ end
+ end
+ end
+ end
+
with_property ":x, Integer" do
context "and subclass" do
let(:subresource_class) do
@@ -1031,8 +1081,14 @@ describe "Chef::Resource.property" do
end
end
- it "raises an error if both name_property and name_attribute are specified (even if they are false or nil)" do
- expect { resource_class.property :x, :name_property => false, :name_attribute => true }.to raise_error ArgumentError,
+ it "raises an error if both name_property and name_attribute are specified" do
+ expect { resource_class.property :x, :name_property => false, :name_attribute => 1 }.to raise_error ArgumentError,
+ /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
+ expect { resource_class.property :x, :name_property => false, :name_attribute => nil }.to raise_error ArgumentError,
+ /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
+ expect { resource_class.property :x, :name_property => false, :name_attribute => false }.to raise_error ArgumentError,
+ /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
+ expect { resource_class.property :x, :name_property => true, :name_attribute => true }.to raise_error ArgumentError,
/Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
end
end
diff --git a/spec/unit/provider/package/rpm_spec.rb b/spec/unit/provider/package/rpm_spec.rb
index e0e45d0b4f..ad9d694e34 100644
--- a/spec/unit/provider/package/rpm_spec.rb
+++ b/spec/unit/provider/package/rpm_spec.rb
@@ -256,6 +256,24 @@ describe Chef::Provider::Package::Rpm do
end
end
+ context "when the package name contains a plus symbol (chef#3671)" do
+
+ let(:package_name) { "chef-server-core" }
+
+ let(:package_source) { "/tmp/chef-server-core-12.2.0+20150713220422-1.el6.x86_64.rpm" }
+
+ let(:rpm_qp_stdout) { "chef-server-core 12.2.0+20150713220422-1.el6" }
+ let(:rpm_q_stdout) { "chef-server-core 12.2.0+20150713220422-1.el6" }
+
+ let(:rpm_qp_exitstatus) { 0 }
+ let(:rpm_q_exitstatus) { 0 }
+
+ it "should correctly determine the candidate version and installed version" do
+ expect(provider.current_resource.package_name).to eq("chef-server-core")
+ expect(provider.new_resource.version).to eq("12.2.0+20150713220422-1.el6")
+ end
+ end
+
end
context "when the source is given as an URI" do
@@ -413,4 +431,3 @@ describe Chef::Provider::Package::Rpm do
end
-
diff --git a/spec/unit/provider_resolver_spec.rb b/spec/unit/provider_resolver_spec.rb
index 88df4a20cc..2fb99f610c 100644
--- a/spec/unit/provider_resolver_spec.rb
+++ b/spec/unit/provider_resolver_spec.rb
@@ -20,6 +20,9 @@ require 'spec_helper'
require 'chef/mixin/convert_to_class_name'
require 'chef/provider_resolver'
require 'chef/platform/service_helpers'
+require 'support/shared/integration/integration_helper'
+require 'tmpdir'
+require 'fileutils'
include Chef::Mixin::ConvertToClassName
@@ -27,833 +30,887 @@ include Chef::Mixin::ConvertToClassName
#module Chef::Provider
describe Chef::ProviderResolver do
+ include IntegrationSupport
- let(:resource_name) { :service }
- let(:provider) { nil }
- let(:action) { :start }
-
- let(:node) do
- node = Chef::Node.new
- node.automatic[:os] = os
- node.automatic[:platform_family] = platform_family
- node.automatic[:platform] = platform
- node.automatic[:platform_version] = platform_version
- node.automatic[:kernel] = { machine: 'i386' }
- node
- end
- let(:run_context) { Chef::RunContext.new(node, nil, nil) }
-
- let(:provider_resolver) { Chef::ProviderResolver.new(node, resource, action) }
- let(:resolved_provider) do
- begin
- resource ? resource.provider_for_action(action).class : nil
- rescue Chef::Exceptions::ProviderNotFound
- nil
+ # Root the filesystem under a temp directory so Chef.path_to will point at it
+ when_the_repository "is empty" do
+ before do
+ allow(Chef).to receive(:path_to) { |path| File.join(path_to(""), path) }
end
- end
- let(:resource) do
- resource_class = Chef::ResourceResolver.resolve(resource_name, node: node)
- if resource_class
- resource = resource_class.new('test', run_context)
- resource.provider = provider if provider
+ let(:resource_name) { :service }
+ let(:provider) { nil }
+ let(:action) { :start }
+
+ let(:node) do
+ node = Chef::Node.new
+ node.automatic[:os] = os
+ node.automatic[:platform_family] = platform_family
+ node.automatic[:platform] = platform
+ node.automatic[:platform_version] = platform_version
+ node.automatic[:kernel] = { machine: 'i386' }
+ node
end
- resource
- end
-
- def self.on_platform(platform, *tags,
- platform_version: '11.0.1',
- platform_family: nil,
- os: nil,
- &block)
- Array(platform).each do |platform|
- Array(platform_version).each do |platform_version|
- on_one_platform(platform, platform_version, platform_family || platform, os || platform_family || platform, *tags, &block)
+ let(:run_context) { Chef::RunContext.new(node, nil, nil) }
+
+ let(:provider_resolver) { Chef::ProviderResolver.new(node, resource, action) }
+ let(:resolved_provider) do
+ begin
+ resource ? resource.provider_for_action(action).class : nil
+ rescue Chef::Exceptions::ProviderNotFound
+ nil
end
end
- end
-
- def self.on_one_platform(platform, platform_version, platform_family, os, *tags, &block)
- describe "on #{platform} #{platform_version}, platform_family: #{platform_family}, os: #{os}", *tags do
- let(:os) { os }
- let(:platform) { platform }
- let(:platform_family) { platform_family }
- let(:platform_version) { platform_version }
- define_singleton_method(:os) { os }
- define_singleton_method(:platform) { platform }
- define_singleton_method(:platform_family) { platform_family }
- define_singleton_method(:platform_version) { platform_version }
-
- instance_eval(&block)
+ let(:service_name) { "test" }
+ let(:resource) do
+ resource_class = Chef::ResourceResolver.resolve(resource_name, node: node)
+ if resource_class
+ resource = resource_class.new(service_name, run_context)
+ resource.provider = provider if provider
+ end
+ resource
end
- end
- def self.expect_providers(**providers)
- providers.each do |name, expected|
- describe name.to_s do
- let(:resource_name) { name }
-
- tags = []
- expected_provider = nil
- expected_resource = nil
- Array(expected).each do |p|
- if p.is_a?(Class) && p <= Chef::Provider
- expected_provider = p
- elsif p.is_a?(Class) && p <= Chef::Resource
- expected_resource = p
- else
- tags << p
- end
- end
-
- if expected_resource && expected_provider
- it "'#{name}' resolves to resource #{expected_resource} and provider #{expected_provider}", *tags do
- expect(resource.class).to eql(expected_resource)
- provider = double(expected_provider, class: expected_provider)
- expect(provider).to receive(:action=).with(action)
- expect(expected_provider).to receive(:new).with(resource, run_context).and_return(provider)
- expect(resolved_provider).to eql(expected_provider)
- end
- elsif expected_provider
- it "'#{name}' resolves to provider #{expected_provider}", *tags do
- provider = double(expected_provider)
- expect(provider).to receive(:action=).with(action)
- expect(expected_provider).to receive(:new).with(resource, run_context).and_return(provider)
- expect(resolved_provider).to eql(expected_provider)
- end
- else
- it "'#{name}' fails to resolve (since #{name.inspect} is unsupported on #{platform} #{platform_version})", *tags do
- expect(resolved_provider).to be_nil
- end
+ def self.on_platform(platform, *tags,
+ platform_version: '11.0.1',
+ platform_family: nil,
+ os: nil,
+ &block)
+ Array(platform).each do |platform|
+ Array(platform_version).each do |platform_version|
+ on_one_platform(platform, platform_version, platform_family || platform, os || platform_family || platform, *tags, &block)
end
end
end
- end
-
- describe "resolving service resource" do
- def stub_service_providers(*services)
- services ||= []
- allow(Chef::Platform::ServiceHelpers).to receive(:service_resource_providers)
- .and_return(services)
- end
-
- def stub_service_configs(*configs)
- configs ||= []
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return(configs)
- end
-
- before do
- allow(resource).to receive(:service_name).and_return("ntp")
- end
-
- shared_examples_for "an ubuntu platform with upstart, update-rc.d and systemd" do
- before do
- stub_service_providers(:debian, :invokercd, :upstart, :systemd)
- end
- it "when only the SysV init script exists, it returns a Service::Debian provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :initd, :systemd ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
- end
-
- it "when both SysV and Upstart scripts exist, it returns a Service::Upstart provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :initd, :upstart, :systemd ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
- end
+ def self.on_one_platform(platform, platform_version, platform_family, os, *tags, &block)
+ describe "on #{platform} #{platform_version}, platform_family: #{platform_family}, os: #{os}", *tags do
+ let(:os) { os }
+ let(:platform) { platform }
+ let(:platform_family) { platform_family }
+ let(:platform_version) { platform_version }
- it "when only the Upstart script exists, it returns a Service::Upstart provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :upstart, :systemd ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
- end
+ define_singleton_method(:os) { os }
+ define_singleton_method(:platform) { platform }
+ define_singleton_method(:platform_family) { platform_family }
+ define_singleton_method(:platform_version) { platform_version }
- it "when both do not exist, it calls the old style provider resolver and returns a Debian Provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :systemd ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
- end
- it "when only the SysV init script exists, it returns a Service::Debian provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :initd ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Debian)
+ instance_eval(&block)
end
+ end
- it "when both SysV and Upstart scripts exist, it returns a Service::Upstart provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :initd, :upstart ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
- end
+ def self.expect_providers(**providers)
+ providers.each do |name, expected|
+ describe name.to_s do
+ let(:resource_name) { name }
+
+ tags = []
+ expected_provider = nil
+ expected_resource = nil
+ Array(expected).each do |p|
+ if p.is_a?(Class) && p <= Chef::Provider
+ expected_provider = p
+ elsif p.is_a?(Class) && p <= Chef::Resource
+ expected_resource = p
+ else
+ tags << p
+ end
+ end
- it "when only the Upstart script exists, it returns a Service::Upstart provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :upstart ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
+ if expected_resource && expected_provider
+ it "'#{name}' resolves to resource #{expected_resource} and provider #{expected_provider}", *tags do
+ expect(resource.class).to eql(expected_resource)
+ provider = double(expected_provider, class: expected_provider)
+ expect(provider).to receive(:action=).with(action)
+ expect(expected_provider).to receive(:new).with(resource, run_context).and_return(provider)
+ expect(resolved_provider).to eql(expected_provider)
+ end
+ elsif expected_provider
+ it "'#{name}' resolves to provider #{expected_provider}", *tags do
+ provider = double(expected_provider)
+ expect(provider).to receive(:action=).with(action)
+ expect(expected_provider).to receive(:new).with(resource, run_context).and_return(provider)
+ expect(resolved_provider).to eql(expected_provider)
+ end
+ else
+ it "'#{name}' fails to resolve (since #{name.inspect} is unsupported on #{platform} #{platform_version})", *tags do
+ expect(resolved_provider).to be_nil
+ end
+ end
+ end
end
+ end
- it "when both do not exist, it calls the old style provider resolver and returns a Debian Provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
+ describe "resolving service resource" do
+ def stub_service_providers(*services)
+ services.each do |service|
+ case service
+ when :debian
+ directory 'usr/sbin/update-rc.d'
+ when :invokercd
+ directory 'usr/sbin/invoke-rc.d'
+ when :insserv
+ directory 'sbin/insserv'
+ when :upstart
+ directory 'etc/init'
+ directory 'sbin/start'
+ when :redhat
+ directory 'sbin/chkconfig'
+ when :systemd
+ file 'bin/systemctl', ''
+ # Make systemctl executable
+ File.chmod(0755, path_to('bin/systemctl'))
+ # Windows doesn't respect executable bit, do this to let Windows users see if they've broken the resolver
+ allow(::File).to receive(:executable?) { |p| p == path_to('bin/systemctl') } if windows?
+ file 'proc/1/comm', "systemd\n"
+ mock_shellout_command("/bin/systemctl --all", stdout: "")
+ mock_shellout_command("/bin/systemctl list-unit-files", stdout: "")
+ else
+ raise ArgumentError, service
+ end
+ end
end
- end
- shared_examples_for "an ubuntu platform with upstart and update-rc.d" do
- before do
- stub_service_providers(:debian, :invokercd, :upstart)
+ def stub_service_configs(*configs)
+ configs.each do |config|
+ case config
+ when :initd
+ file "etc/init.d/#{service_name}", ""
+ when :upstart
+ file "etc/init/#{service_name}.conf", ""
+ when :xinetd
+ file "etc/xinetd.d/#{service_name}", ""
+ when :etc_rcd
+ file "etc/rc.d/#{service_name}", ""
+ when :usr_local_etc_rcd
+ file "usr/local/etc/rc.d/#{service_name}", ""
+ when :systemd
+ file 'bin/systemctl', ''
+ # Make systemctl executable
+ File.chmod(0755, path_to("bin/systemctl"))
+ # Windows doesn't respect executable bit, do this to let Windows users see if they've broken the resolver
+ allow(::File).to receive(:executable?) { |p| p == path_to('bin/systemctl') } if windows?
+ file 'proc/1/comm', "systemd\n"
+ mock_shellout_command("/bin/systemctl --all", stdout: <<-EOM)
+ superv loaded
+ stinky something-else
+ #{service_name} loaded
+ blargh not-found
+ EOM
+ mock_shellout_command("/bin/systemctl list-unit-files", stdout: <<-EOM)
+ usuperv loaded
+ ustinky something-else
+ u#{service_name} loaded
+ ublargh not-found
+ EOM
+ else
+ raise ArgumentError, config
+ end
+ end
end
- # needs to be handled by the highest priority init.d handler
- context "when only the SysV init script exists" do
+ shared_examples_for "an ubuntu platform with upstart, update-rc.d and systemd" do
before do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :initd ] )
+ stub_service_providers(:debian, :invokercd, :upstart, :systemd)
end
- it "enables init, invokercd, debian and upstart providers" do
- expect(provider_resolver.enabled_handlers).to include(
- Chef::Provider::Service::Debian,
- Chef::Provider::Service::Init,
- Chef::Provider::Service::Invokercd,
- Chef::Provider::Service::Upstart,
- )
+ it "when only the SysV init script exists, it returns a Service::Debian provider" do
+ stub_service_configs(:initd, :systemd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
end
- it "supports all the enabled handlers except for upstart" do
- expect(provider_resolver.supported_handlers).to include(
- Chef::Provider::Service::Debian,
- Chef::Provider::Service::Init,
- Chef::Provider::Service::Invokercd,
- )
- expect(provider_resolver.supported_handlers).to_not include(
- Chef::Provider::Service::Upstart,
- )
+ it "when both SysV and Upstart scripts exist, it returns a Service::Upstart provider" do
+ stub_service_configs(:initd, :upstart, :systemd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
end
- it "returns a Service::Debian provider" do
- expect(resolved_provider).to eql(Chef::Provider::Service::Debian)
+ it "when only the Upstart script exists, it returns a Service::Upstart provider" do
+ stub_service_configs(:upstart, :systemd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
end
- end
- # on ubuntu this must be handled by upstart, the init script will exit 1 and fail
- context "when both SysV and Upstart scripts exist" do
- before do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :initd, :upstart ] )
+ it "when both do not exist, it calls the old style provider resolver and returns a Debian Provider" do
+ stub_service_configs(:systemd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
end
- it "enables init, invokercd, debian and upstart providers" do
- expect(provider_resolver.enabled_handlers).to include(
- Chef::Provider::Service::Debian,
- Chef::Provider::Service::Init,
- Chef::Provider::Service::Invokercd,
- Chef::Provider::Service::Upstart,
- )
+ it "when only the SysV init script exists, it returns a Service::Debian provider" do
+ stub_service_configs(:initd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Debian)
end
- it "supports all the enabled handlers" do
- expect(provider_resolver.supported_handlers).to include(
- Chef::Provider::Service::Debian,
- Chef::Provider::Service::Init,
- Chef::Provider::Service::Invokercd,
- Chef::Provider::Service::Upstart,
- )
+ it "when both SysV and Upstart scripts exist, it returns a Service::Upstart provider" do
+ stub_service_configs(:initd, :upstart)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
end
- it "returns a Service::Upstart provider" do
+ it "when only the Upstart script exists, it returns a Service::Upstart provider" do
+ stub_service_configs(:upstart)
expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
end
+
+ it "when both do not exist, it calls the old style provider resolver and returns a Debian Provider" do
+ stub_service_configs
+ expect(resolved_provider).to eql(Chef::Provider::Service::Systemd)
+ end
end
- # this case is a pure-upstart script which is easy
- context "when only the Upstart script exists" do
+ shared_examples_for "an ubuntu platform with upstart and update-rc.d" do
before do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :upstart ] )
+ stub_service_providers(:debian, :invokercd, :upstart)
end
- it "enables init, invokercd, debian and upstart providers" do
- expect(provider_resolver.enabled_handlers).to include(
- Chef::Provider::Service::Debian,
- Chef::Provider::Service::Init,
- Chef::Provider::Service::Invokercd,
- Chef::Provider::Service::Upstart,
- )
- end
+ # needs to be handled by the highest priority init.d handler
+ context "when only the SysV init script exists" do
+ before do
+ stub_service_configs(:initd)
+ end
- it "supports only the upstart handler" do
- expect(provider_resolver.supported_handlers).to include(
- Chef::Provider::Service::Upstart,
- )
- expect(provider_resolver.supported_handlers).to_not include(
- Chef::Provider::Service::Debian,
- Chef::Provider::Service::Init,
- Chef::Provider::Service::Invokercd,
- )
- end
+ it "enables init, invokercd, debian and upstart providers" do
+ expect(provider_resolver.enabled_handlers).to include(
+ Chef::Provider::Service::Debian,
+ Chef::Provider::Service::Init,
+ Chef::Provider::Service::Invokercd,
+ Chef::Provider::Service::Upstart,
+ )
+ end
- it "returns a Service::Upstart provider" do
- expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
- end
- end
+ it "supports all the enabled handlers except for upstart" do
+ expect(provider_resolver.supported_handlers).to include(
+ Chef::Provider::Service::Debian,
+ Chef::Provider::Service::Init,
+ Chef::Provider::Service::Invokercd,
+ )
+ expect(provider_resolver.supported_handlers).to_not include(
+ Chef::Provider::Service::Upstart,
+ )
+ end
- # this case is important to get correct for why-run when no config is setup
- context "when both do not exist" do
- before do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ ] )
+ it "returns a Service::Debian provider" do
+ expect(resolved_provider).to eql(Chef::Provider::Service::Debian)
+ end
end
- it "enables init, invokercd, debian and upstart providers" do
- expect(provider_resolver.enabled_handlers).to include(
- Chef::Provider::Service::Debian,
- Chef::Provider::Service::Init,
- Chef::Provider::Service::Invokercd,
- Chef::Provider::Service::Upstart,
- )
- end
+ # on ubuntu this must be handled by upstart, the init script will exit 1 and fail
+ context "when both SysV and Upstart scripts exist" do
+ before do
+ stub_service_configs(:initd, :upstart)
+ end
- it "no providers claim to support the resource" do
- expect(provider_resolver.supported_handlers).to_not include(
- Chef::Provider::Service::Upstart,
- Chef::Provider::Service::Debian,
- Chef::Provider::Service::Init,
- Chef::Provider::Service::Invokercd,
- )
- end
+ it "enables init, invokercd, debian and upstart providers" do
+ expect(provider_resolver.enabled_handlers).to include(
+ Chef::Provider::Service::Debian,
+ Chef::Provider::Service::Init,
+ Chef::Provider::Service::Invokercd,
+ Chef::Provider::Service::Upstart,
+ )
+ end
- it "returns a Debian Provider" do
- expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
- end
- end
- end
+ it "supports all the enabled handlers" do
+ expect(provider_resolver.supported_handlers).to include(
+ Chef::Provider::Service::Debian,
+ Chef::Provider::Service::Init,
+ Chef::Provider::Service::Invokercd,
+ Chef::Provider::Service::Upstart,
+ )
+ end
- shared_examples_for "a debian platform using the insserv provider" do
- context "with a default install" do
- before do
- stub_service_providers(:debian, :invokercd, :insserv)
+ it "returns a Service::Upstart provider" do
+ expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
+ end
end
- it "uses the Service::Insserv Provider to manage sysv init scripts" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :initd ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Insserv)
- end
+ # this case is a pure-upstart script which is easy
+ context "when only the Upstart script exists" do
+ before do
+ stub_service_configs(:upstart)
+ end
- it "uses the Service::Insserv Provider when there is no config" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Insserv)
- end
- end
+ it "enables init, invokercd, debian and upstart providers" do
+ expect(provider_resolver.enabled_handlers).to include(
+ Chef::Provider::Service::Debian,
+ Chef::Provider::Service::Init,
+ Chef::Provider::Service::Invokercd,
+ Chef::Provider::Service::Upstart,
+ )
+ end
- context "when the user has installed upstart" do
- before do
- stub_service_providers(:debian, :invokercd, :insserv, :upstart)
- end
+ it "supports only the upstart handler" do
+ expect(provider_resolver.supported_handlers).to include(
+ Chef::Provider::Service::Upstart,
+ )
+ expect(provider_resolver.supported_handlers).to_not include(
+ Chef::Provider::Service::Debian,
+ Chef::Provider::Service::Init,
+ Chef::Provider::Service::Invokercd,
+ )
+ end
- it "when only the SysV init script exists, it returns an Insserv provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :initd ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Insserv)
+ it "returns a Service::Upstart provider" do
+ expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
+ end
end
- it "when both SysV and Upstart scripts exist, it returns a Service::Upstart provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :initd, :upstart ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
- end
+ # this case is important to get correct for why-run when no config is setup
+ context "when both do not exist" do
+ before do
+ stub_service_configs
+ end
- it "when only the Upstart script exists, it returns a Service::Upstart provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ :upstart ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
- end
+ it "enables init, invokercd, debian and upstart providers" do
+ expect(provider_resolver.enabled_handlers).to include(
+ Chef::Provider::Service::Debian,
+ Chef::Provider::Service::Init,
+ Chef::Provider::Service::Invokercd,
+ Chef::Provider::Service::Upstart,
+ )
+ end
- it "when both do not exist, it calls the old style provider resolver and returns a Debian Provider" do
- allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp")
- .and_return( [ ] )
- expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
+ it "no providers claim to support the resource" do
+ expect(provider_resolver.supported_handlers).to_not include(
+ Chef::Provider::Service::Upstart,
+ Chef::Provider::Service::Debian,
+ Chef::Provider::Service::Init,
+ Chef::Provider::Service::Invokercd,
+ )
+ end
+
+ it "returns a Debian Provider" do
+ expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
+ end
end
end
- end
- on_platform "ubuntu", platform_version: "14.10", platform_family: "debian", os: "linux" do
- it_behaves_like "an ubuntu platform with upstart, update-rc.d and systemd"
- end
+ shared_examples_for "a debian platform using the insserv provider" do
+ context "with a default install" do
+ before do
+ stub_service_providers(:debian, :invokercd, :insserv)
+ end
- on_platform "ubuntu", platform_version: "14.04", platform_family: "debian", os: "linux" do
- it_behaves_like "an ubuntu platform with upstart and update-rc.d"
- end
+ it "uses the Service::Insserv Provider to manage sysv init scripts" do
+ stub_service_configs(:initd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Insserv)
+ end
- on_platform "ubuntu", platform_version: "10.04", platform_family: "debian", os: "linux" do
- it_behaves_like "an ubuntu platform with upstart and update-rc.d"
- end
+ it "uses the Service::Insserv Provider when there is no config" do
+ stub_service_configs
+ expect(resolved_provider).to eql(Chef::Provider::Service::Insserv)
+ end
+ end
- # old debian uses the Debian provider (does not have insserv or upstart, or update-rc.d???)
- on_platform "debian", platform_version: "4.0", os: "linux" do
- #it_behaves_like "a debian platform using the debian provider"
- end
+ context "when the user has installed upstart" do
+ before do
+ stub_service_providers(:debian, :invokercd, :insserv, :upstart)
+ end
- # Debian replaced the debian provider with insserv in the FIXME:VERSION distro
- on_platform "debian", platform_version: "7.0", os: "linux" do
- it_behaves_like "a debian platform using the insserv provider"
- end
+ it "when only the SysV init script exists, it returns an Insserv provider" do
+ stub_service_configs(:initd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Insserv)
+ end
+
+ it "when both SysV and Upstart scripts exist, it returns a Service::Upstart provider" do
+ stub_service_configs(:initd, :upstart)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
+ end
+
+ it "when only the Upstart script exists, it returns a Service::Upstart provider" do
+ stub_service_configs(:upstart)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
+ end
- on_platform %w{solaris2 openindiana opensolaris nexentacore omnios smartos}, os: "solaris2", platform_version: "5.11" do
- it "returns a Solaris provider" do
- stub_service_providers
- stub_service_configs
- expect(resolved_provider).to eql(Chef::Provider::Service::Solaris)
+ it "when both do not exist, it calls the old style provider resolver and returns a Debian Provider" do
+ stub_service_configs
+ expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
+ end
+ end
end
- it "always returns a Solaris provider" do
- # no matter what we stub on the next two lines we should get a Solaris provider
- stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
- stub_service_configs(:initd, :upstart, :xinetd, :user_local_etc_rcd, :systemd)
- expect(resolved_provider).to eql(Chef::Provider::Service::Solaris)
+ on_platform "ubuntu", platform_version: "15.10", platform_family: "debian", os: "linux" do
+ it_behaves_like "an ubuntu platform with upstart, update-rc.d and systemd"
+
+ it "when the unit-files are missing and system-ctl list-unit-files returns an error" do
+ stub_service_providers(:debian, :invokercd, :upstart, :systemd)
+ stub_service_configs(:initd, :upstart)
+ mock_shellout_command("/bin/systemctl list-unit-files", exitstatus: 1)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Upstart)
+ end
end
- end
- on_platform %w{mswin mingw32 windows}, platform_family: "windows", platform_version: "5.11" do
- it "returns a Windows provider" do
- stub_service_providers
- stub_service_configs
- expect(resolved_provider).to eql(Chef::Provider::Service::Windows)
+ on_platform "ubuntu", platform_version: "14.10", platform_family: "debian", os: "linux" do
+ it_behaves_like "an ubuntu platform with upstart, update-rc.d and systemd"
end
- it "always returns a Windows provider" do
- # no matter what we stub on the next two lines we should get a Windows provider
- stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
- stub_service_configs(:initd, :upstart, :xinetd, :user_local_etc_rcd, :systemd)
- expect(resolved_provider).to eql(Chef::Provider::Service::Windows)
+ on_platform "ubuntu", platform_version: "14.04", platform_family: "debian", os: "linux" do
+ it_behaves_like "an ubuntu platform with upstart and update-rc.d"
end
- end
- on_platform %w{mac_os_x mac_os_x_server}, os: "darwin", platform_family: "mac_os_x", platform_version: "10.9.2" do
- it "returns a Macosx provider" do
- stub_service_providers
- stub_service_configs
- expect(resolved_provider).to eql(Chef::Provider::Service::Macosx)
+ on_platform "ubuntu", platform_version: "10.04", platform_family: "debian", os: "linux" do
+ it_behaves_like "an ubuntu platform with upstart and update-rc.d"
end
- it "always returns a Macosx provider" do
- # no matter what we stub on the next two lines we should get a Macosx provider
- stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
- stub_service_configs(:initd, :upstart, :xinetd, :user_local_etc_rcd, :systemd)
- expect(resolved_provider).to eql(Chef::Provider::Service::Macosx)
+ # old debian uses the Debian provider (does not have insserv or upstart, or update-rc.d???)
+ on_platform "debian", platform_version: "4.0", os: "linux" do
+ #it_behaves_like "a debian platform using the debian provider"
end
- end
- on_platform %w(freebsd netbsd), platform_version: '3.1.4' do
- it "returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do
- stub_service_providers
- stub_service_configs(:usr_local_etc_rcd)
- expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ # Debian replaced the debian provider with insserv in the FIXME:VERSION distro
+ on_platform "debian", platform_version: "7.0", os: "linux" do
+ it_behaves_like "a debian platform using the insserv provider"
end
- it "returns a Freebsd provider if it finds the /etc/rc.d initscript" do
- stub_service_providers
- stub_service_configs(:etc_rcd)
- expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ on_platform %w{solaris2 openindiana opensolaris nexentacore omnios smartos}, os: "solaris2", platform_version: "5.11" do
+ it "returns a Solaris provider" do
+ stub_service_providers
+ stub_service_configs
+ expect(resolved_provider).to eql(Chef::Provider::Service::Solaris)
+ end
+
+ it "always returns a Solaris provider" do
+ # no matter what we stub on the next two lines we should get a Solaris provider
+ stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
+ stub_service_configs(:initd, :upstart, :xinetd, :usr_local_etc_rcd, :systemd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Solaris)
+ end
end
- it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do
- # should only care about :usr_local_etc_rcd stub in the service configs
- stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
- stub_service_configs(:usr_local_etc_rcd, :initd, :upstart, :xinetd, :systemd)
- expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ on_platform %w{mswin mingw32 windows}, platform_family: "windows", platform_version: "5.11" do
+ it "returns a Windows provider" do
+ stub_service_providers
+ stub_service_configs
+ expect(resolved_provider).to eql(Chef::Provider::Service::Windows)
+ end
+
+ it "always returns a Windows provider" do
+ # no matter what we stub on the next two lines we should get a Windows provider
+ stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
+ stub_service_configs(:initd, :upstart, :xinetd, :usr_local_etc_rcd, :systemd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Windows)
+ end
end
- it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do
- # should only care about :etc_rcd stub in the service configs
- stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
- stub_service_configs(:etc_rcd, :initd, :upstart, :xinetd, :systemd)
- expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ on_platform %w{mac_os_x mac_os_x_server}, os: "darwin", platform_family: "mac_os_x", platform_version: "10.9.2" do
+ it "returns a Macosx provider" do
+ stub_service_providers
+ stub_service_configs
+ expect(resolved_provider).to eql(Chef::Provider::Service::Macosx)
+ end
+
+ it "always returns a Macosx provider" do
+ # no matter what we stub on the next two lines we should get a Macosx provider
+ stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
+ stub_service_configs(:initd, :upstart, :xinetd, :usr_local_etc_rcd, :systemd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Macosx)
+ end
end
- it "foo" do
- stub_service_providers
- stub_service_configs
- expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ on_platform %w(freebsd netbsd), platform_version: '3.1.4' do
+ it "returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do
+ stub_service_providers
+ stub_service_configs(:usr_local_etc_rcd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ end
+
+ it "returns a Freebsd provider if it finds the /etc/rc.d initscript" do
+ stub_service_providers
+ stub_service_configs(:etc_rcd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ end
+
+ it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do
+ # should only care about :usr_local_etc_rcd stub in the service configs
+ stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
+ stub_service_configs(:usr_local_etc_rcd, :initd, :upstart, :xinetd, :systemd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ end
+
+ it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do
+ # should only care about :etc_rcd stub in the service configs
+ stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd)
+ stub_service_configs(:etc_rcd, :initd, :upstart, :xinetd, :systemd)
+ expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ end
+
+ it "foo" do
+ stub_service_providers
+ stub_service_configs
+ expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd)
+ end
end
- end
- end
+ end
- PROVIDERS =
- {
- bash: [ Chef::Resource::Bash, Chef::Provider::Script ],
- breakpoint: [ Chef::Resource::Breakpoint, Chef::Provider::Breakpoint ],
- chef_gem: [ Chef::Resource::ChefGem, Chef::Provider::Package::Rubygems ],
- cookbook_file: [ Chef::Resource::CookbookFile, Chef::Provider::CookbookFile ],
- csh: [ Chef::Resource::Csh, Chef::Provider::Script ],
- deploy: [ Chef::Resource::Deploy, Chef::Provider::Deploy::Timestamped ],
- deploy_revision: [ Chef::Resource::DeployRevision, Chef::Provider::Deploy::Revision ],
- directory: [ Chef::Resource::Directory, Chef::Provider::Directory ],
- easy_install_package: [ Chef::Resource::EasyInstallPackage, Chef::Provider::Package::EasyInstall ],
- erl_call: [ Chef::Resource::ErlCall, Chef::Provider::ErlCall ],
- execute: [ Chef::Resource::Execute, Chef::Provider::Execute ],
- file: [ Chef::Resource::File, Chef::Provider::File ],
- gem_package: [ Chef::Resource::GemPackage, Chef::Provider::Package::Rubygems ],
- git: [ Chef::Resource::Git, Chef::Provider::Git ],
- group: [ Chef::Resource::Group, Chef::Provider::Group::Gpasswd ],
- homebrew_package: [ Chef::Resource::HomebrewPackage, Chef::Provider::Package::Homebrew ],
- http_request: [ Chef::Resource::HttpRequest, Chef::Provider::HttpRequest ],
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
- link: [ Chef::Resource::Link, Chef::Provider::Link ],
- log: [ Chef::Resource::Log, Chef::Provider::Log::ChefLog ],
- macports_package: [ Chef::Resource::MacportsPackage, Chef::Provider::Package::Macports ],
- mdadm: [ Chef::Resource::Mdadm, Chef::Provider::Mdadm ],
- mount: [ Chef::Resource::Mount, Chef::Provider::Mount::Mount ],
- perl: [ Chef::Resource::Perl, Chef::Provider::Script ],
- portage_package: [ Chef::Resource::PortagePackage, Chef::Provider::Package::Portage ],
- python: [ Chef::Resource::Python, Chef::Provider::Script ],
- remote_directory: [ Chef::Resource::RemoteDirectory, Chef::Provider::RemoteDirectory ],
- route: [ Chef::Resource::Route, Chef::Provider::Route ],
- ruby: [ Chef::Resource::Ruby, Chef::Provider::Script ],
- ruby_block: [ Chef::Resource::RubyBlock, Chef::Provider::RubyBlock ],
- script: [ Chef::Resource::Script, Chef::Provider::Script ],
- subversion: [ Chef::Resource::Subversion, Chef::Provider::Subversion ],
- template: [ Chef::Resource::Template, Chef::Provider::Template ],
- timestamped_deploy: [ Chef::Resource::TimestampedDeploy, Chef::Provider::Deploy::Timestamped ],
- user: [ Chef::Resource::User, Chef::Provider::User::Useradd ],
- whyrun_safe_ruby_block: [ Chef::Resource::WhyrunSafeRubyBlock, Chef::Provider::WhyrunSafeRubyBlock ],
-
- # We want to check that these are unsupported:
- apt_package: nil,
- bff_package: nil,
- dpkg_package: nil,
- dsc_script: nil,
- ips_package: nil,
- pacman_package: nil,
- paludis_package: nil,
- rpm_package: nil,
- smartos_package: nil,
- solaris_package: nil,
- yum_package: nil,
- windows_package: nil,
- windows_service: nil,
-
- "linux" => {
- apt_package: [ Chef::Resource::AptPackage, Chef::Provider::Package::Apt ],
- dpkg_package: [ Chef::Resource::DpkgPackage, Chef::Provider::Package::Dpkg ],
- pacman_package: [ Chef::Resource::PacmanPackage, Chef::Provider::Package::Pacman ],
- paludis_package: [ Chef::Resource::PaludisPackage, Chef::Provider::Package::Paludis ],
- rpm_package: [ Chef::Resource::RpmPackage, Chef::Provider::Package::Rpm ],
- yum_package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
-
- "debian" => {
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig::Debian ],
- package: [ Chef::Resource::AptPackage, Chef::Provider::Package::Apt ],
-# service: [ Chef::Resource::DebianService, Chef::Provider::Service::Debian ],
+ PROVIDERS =
+ {
+ bash: [ Chef::Resource::Bash, Chef::Provider::Script ],
+ breakpoint: [ Chef::Resource::Breakpoint, Chef::Provider::Breakpoint ],
+ chef_gem: [ Chef::Resource::ChefGem, Chef::Provider::Package::Rubygems ],
+ cookbook_file: [ Chef::Resource::CookbookFile, Chef::Provider::CookbookFile ],
+ csh: [ Chef::Resource::Csh, Chef::Provider::Script ],
+ deploy: [ Chef::Resource::Deploy, Chef::Provider::Deploy::Timestamped ],
+ deploy_revision: [ Chef::Resource::DeployRevision, Chef::Provider::Deploy::Revision ],
+ directory: [ Chef::Resource::Directory, Chef::Provider::Directory ],
+ easy_install_package: [ Chef::Resource::EasyInstallPackage, Chef::Provider::Package::EasyInstall ],
+ erl_call: [ Chef::Resource::ErlCall, Chef::Provider::ErlCall ],
+ execute: [ Chef::Resource::Execute, Chef::Provider::Execute ],
+ file: [ Chef::Resource::File, Chef::Provider::File ],
+ gem_package: [ Chef::Resource::GemPackage, Chef::Provider::Package::Rubygems ],
+ git: [ Chef::Resource::Git, Chef::Provider::Git ],
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Gpasswd ],
+ homebrew_package: [ Chef::Resource::HomebrewPackage, Chef::Provider::Package::Homebrew ],
+ http_request: [ Chef::Resource::HttpRequest, Chef::Provider::HttpRequest ],
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
+ link: [ Chef::Resource::Link, Chef::Provider::Link ],
+ log: [ Chef::Resource::Log, Chef::Provider::Log::ChefLog ],
+ macports_package: [ Chef::Resource::MacportsPackage, Chef::Provider::Package::Macports ],
+ mdadm: [ Chef::Resource::Mdadm, Chef::Provider::Mdadm ],
+ mount: [ Chef::Resource::Mount, Chef::Provider::Mount::Mount ],
+ perl: [ Chef::Resource::Perl, Chef::Provider::Script ],
+ portage_package: [ Chef::Resource::PortagePackage, Chef::Provider::Package::Portage ],
+ python: [ Chef::Resource::Python, Chef::Provider::Script ],
+ remote_directory: [ Chef::Resource::RemoteDirectory, Chef::Provider::RemoteDirectory ],
+ route: [ Chef::Resource::Route, Chef::Provider::Route ],
+ ruby: [ Chef::Resource::Ruby, Chef::Provider::Script ],
+ ruby_block: [ Chef::Resource::RubyBlock, Chef::Provider::RubyBlock ],
+ script: [ Chef::Resource::Script, Chef::Provider::Script ],
+ subversion: [ Chef::Resource::Subversion, Chef::Provider::Subversion ],
+ template: [ Chef::Resource::Template, Chef::Provider::Template ],
+ timestamped_deploy: [ Chef::Resource::TimestampedDeploy, Chef::Provider::Deploy::Timestamped ],
+ user: [ Chef::Resource::User, Chef::Provider::User::Useradd ],
+ whyrun_safe_ruby_block: [ Chef::Resource::WhyrunSafeRubyBlock, Chef::Provider::WhyrunSafeRubyBlock ],
+
+ # We want to check that these are unsupported:
+ apt_package: nil,
+ bff_package: nil,
+ dpkg_package: nil,
+ dsc_script: nil,
+ ips_package: nil,
+ pacman_package: nil,
+ paludis_package: nil,
+ rpm_package: nil,
+ smartos_package: nil,
+ solaris_package: nil,
+ yum_package: nil,
+ windows_package: nil,
+ windows_service: nil,
+
+ "linux" => {
+ apt_package: [ Chef::Resource::AptPackage, Chef::Provider::Package::Apt ],
+ dpkg_package: [ Chef::Resource::DpkgPackage, Chef::Provider::Package::Dpkg ],
+ pacman_package: [ Chef::Resource::PacmanPackage, Chef::Provider::Package::Pacman ],
+ paludis_package: [ Chef::Resource::PaludisPackage, Chef::Provider::Package::Paludis ],
+ rpm_package: [ Chef::Resource::RpmPackage, Chef::Provider::Package::Rpm ],
+ yum_package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
"debian" => {
- "7.0" => {
- },
- "6.0" => {
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
-# service: [ Chef::Resource::InsservService, Chef::Provider::Service::Insserv ],
- },
- "5.0" => {
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig::Debian ],
+ package: [ Chef::Resource::AptPackage, Chef::Provider::Package::Apt ],
+ # service: [ Chef::Resource::DebianService, Chef::Provider::Service::Debian ],
+
+ "debian" => {
+ "7.0" => {
+ },
+ "6.0" => {
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
+ # service: [ Chef::Resource::InsservService, Chef::Provider::Service::Insserv ],
+ },
+ "5.0" => {
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
+ },
+ },
+ "gcel" => {
+ "3.1.4" => {
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
+ },
+ },
+ "linaro" => {
+ "3.1.4" => {
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
+ },
+ },
+ "linuxmint" => {
+ "3.1.4" => {
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
+ # service: [ Chef::Resource::UpstartService, Chef::Provider::Service::Upstart ],
+ },
+ },
+ "raspbian" => {
+ "3.1.4" => {
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
+ },
+ },
+ "ubuntu" => {
+ "11.10" => {
+ },
+ "10.04" => {
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
+ },
},
},
- "gcel" => {
- "3.1.4" => {
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
- },
- },
- "linaro" => {
- "3.1.4" => {
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
- },
- },
- "linuxmint" => {
- "3.1.4" => {
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
-# service: [ Chef::Resource::UpstartService, Chef::Provider::Service::Upstart ],
- },
- },
- "raspbian" => {
- "3.1.4" => {
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
- },
- },
- "ubuntu" => {
- "11.10" => {
- },
- "10.04" => {
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig ],
- },
- },
- },
-
- "arch" => {
- # TODO should be Chef::Resource::PacmanPackage
- package: [ Chef::Resource::Package, Chef::Provider::Package::Pacman ],
"arch" => {
- "3.1.4" => {
- }
- },
- },
+ # TODO should be Chef::Resource::PacmanPackage
+ package: [ Chef::Resource::Package, Chef::Provider::Package::Pacman ],
- "freebsd" => {
- group: [ Chef::Resource::Group, Chef::Provider::Group::Pw ],
- user: [ Chef::Resource::User, Chef::Provider::User::Pw ],
+ "arch" => {
+ "3.1.4" => {
+ }
+ },
+ },
"freebsd" => {
- "3.1.4" => {
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Pw ],
+ user: [ Chef::Resource::User, Chef::Provider::User::Pw ],
+
+ "freebsd" => {
+ "3.1.4" => {
+ },
},
},
- },
- "suse" => {
- group: [ Chef::Resource::Group, Chef::Provider::Group::Gpasswd ],
"suse" => {
- "12.0" => {
- },
- %w(11.1 11.2 11.3) => {
- group: [ Chef::Resource::Group, Chef::Provider::Group::Suse ],
- },
- },
- "opensuse" => {
-# service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
- package: [ Chef::Resource::ZypperPackage, Chef::Provider::Package::Zypper ],
- group: [ Chef::Resource::Group, Chef::Provider::Group::Usermod ],
- "12.3" => {
- },
- "12.2" => {
- group: [ Chef::Resource::Group, Chef::Provider::Group::Suse ],
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Gpasswd ],
+ "suse" => {
+ "12.0" => {
+ },
+ %w(11.1 11.2 11.3) => {
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Suse ],
+ },
+ },
+ "opensuse" => {
+ # service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
+ package: [ Chef::Resource::ZypperPackage, Chef::Provider::Package::Zypper ],
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Usermod ],
+ "12.3" => {
+ },
+ "12.2" => {
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Suse ],
+ },
},
},
- },
-
- "gentoo" => {
- # TODO should be Chef::Resource::PortagePackage
- package: [ Chef::Resource::Package, Chef::Provider::Package::Portage ],
- portage_package: [ Chef::Resource::PortagePackage, Chef::Provider::Package::Portage ],
-# service: [ Chef::Resource::GentooService, Chef::Provider::Service::Gentoo ],
"gentoo" => {
- "3.1.4" => {
- },
- },
- },
+ # TODO should be Chef::Resource::PortagePackage
+ package: [ Chef::Resource::Package, Chef::Provider::Package::Portage ],
+ portage_package: [ Chef::Resource::PortagePackage, Chef::Provider::Package::Portage ],
+ # service: [ Chef::Resource::GentooService, Chef::Provider::Service::Gentoo ],
- "rhel" => {
-# service: [ Chef::Resource::SystemdService, Chef::Provider::Service::Systemd ],
- package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig::Redhat ],
-
- %w(amazon xcp xenserver ibm_powerkvm cloudlinux parallels) => {
- "3.1.4" => {
-# service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
+ "gentoo" => {
+ "3.1.4" => {
+ },
},
},
- %w(redhat centos scientific oracle) => {
- "7.0" => {
- },
- "6.0" => {
-# service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
- },
- },
- "fedora" => {
- "15.0" => {
- },
- "14.0" => {
-# service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
+
+ "rhel" => {
+ # service: [ Chef::Resource::SystemdService, Chef::Provider::Service::Systemd ],
+ package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig::Redhat ],
+
+ %w(amazon xcp xenserver ibm_powerkvm cloudlinux parallels) => {
+ "3.1.4" => {
+ # service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
+ },
+ },
+ %w(redhat centos scientific oracle) => {
+ "7.0" => {
+ },
+ "6.0" => {
+ # service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
+ },
+ },
+ "fedora" => {
+ "15.0" => {
+ },
+ "14.0" => {
+ # service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
+ },
},
},
- },
- },
+ },
- "darwin" => {
- %w(mac_os_x mac_os_x_server) => {
- group: [ Chef::Resource::Group, Chef::Provider::Group::Dscl ],
- package: [ Chef::Resource::HomebrewPackage, Chef::Provider::Package::Homebrew ],
- user: [ Chef::Resource::User, Chef::Provider::User::Dscl ],
+ "darwin" => {
+ %w(mac_os_x mac_os_x_server) => {
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Dscl ],
+ package: [ Chef::Resource::HomebrewPackage, Chef::Provider::Package::Homebrew ],
+ user: [ Chef::Resource::User, Chef::Provider::User::Dscl ],
- "mac_os_x" => {
- "10.9.2" => {
+ "mac_os_x" => {
+ "10.9.2" => {
+ },
},
},
},
- },
-
- "windows" => {
- batch: [ Chef::Resource::Batch, Chef::Provider::Batch ],
- dsc_script: [ Chef::Resource::DscScript, Chef::Provider::DscScript ],
- env: [ Chef::Resource::Env, Chef::Provider::Env::Windows ],
- group: [ Chef::Resource::Group, Chef::Provider::Group::Windows ],
- mount: [ Chef::Resource::Mount, Chef::Provider::Mount::Windows ],
- package: [ Chef::Resource::WindowsPackage, Chef::Provider::Package::Windows ],
- powershell_script: [ Chef::Resource::PowershellScript, Chef::Provider::PowershellScript ],
- service: [ Chef::Resource::WindowsService, Chef::Provider::Service::Windows ],
- user: [ Chef::Resource::User, Chef::Provider::User::Windows ],
- windows_package: [ Chef::Resource::WindowsPackage, Chef::Provider::Package::Windows ],
- windows_service: [ Chef::Resource::WindowsService, Chef::Provider::Service::Windows ],
"windows" => {
- %w(mswin mingw32 windows) => {
- "10.9.2" => {
+ batch: [ Chef::Resource::Batch, Chef::Provider::Batch ],
+ dsc_script: [ Chef::Resource::DscScript, Chef::Provider::DscScript ],
+ env: [ Chef::Resource::Env, Chef::Provider::Env::Windows ],
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Windows ],
+ mount: [ Chef::Resource::Mount, Chef::Provider::Mount::Windows ],
+ package: [ Chef::Resource::WindowsPackage, Chef::Provider::Package::Windows ],
+ powershell_script: [ Chef::Resource::PowershellScript, Chef::Provider::PowershellScript ],
+ service: [ Chef::Resource::WindowsService, Chef::Provider::Service::Windows ],
+ user: [ Chef::Resource::User, Chef::Provider::User::Windows ],
+ windows_package: [ Chef::Resource::WindowsPackage, Chef::Provider::Package::Windows ],
+ windows_service: [ Chef::Resource::WindowsService, Chef::Provider::Service::Windows ],
+
+ "windows" => {
+ %w(mswin mingw32 windows) => {
+ "10.9.2" => {
+ },
},
},
},
- },
-
- "aix" => {
- bff_package: [ Chef::Resource::BffPackage, Chef::Provider::Package::Aix ],
- cron: [ Chef::Resource::Cron, Chef::Provider::Cron::Aix ],
- group: [ Chef::Resource::Group, Chef::Provider::Group::Aix ],
- ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig::Aix ],
- mount: [ Chef::Resource::Mount, Chef::Provider::Mount::Aix ],
- # TODO should be Chef::Resource::BffPackage
- package: [ Chef::Resource::Package, Chef::Provider::Package::Aix ],
- rpm_package: [ Chef::Resource::RpmPackage, Chef::Provider::Package::Rpm ],
- user: [ Chef::Resource::User, Chef::Provider::User::Aix ],
-# service: [ Chef::Resource::AixService, Chef::Provider::Service::Aix ],
"aix" => {
+ bff_package: [ Chef::Resource::BffPackage, Chef::Provider::Package::Aix ],
+ cron: [ Chef::Resource::Cron, Chef::Provider::Cron::Aix ],
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Aix ],
+ ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig::Aix ],
+ mount: [ Chef::Resource::Mount, Chef::Provider::Mount::Aix ],
+ # TODO should be Chef::Resource::BffPackage
+ package: [ Chef::Resource::Package, Chef::Provider::Package::Aix ],
+ rpm_package: [ Chef::Resource::RpmPackage, Chef::Provider::Package::Rpm ],
+ user: [ Chef::Resource::User, Chef::Provider::User::Aix ],
+ # service: [ Chef::Resource::AixService, Chef::Provider::Service::Aix ],
+
"aix" => {
- "5.6" => {
+ "aix" => {
+ "5.6" => {
+ },
},
},
},
- },
- "hpux" => {
"hpux" => {
"hpux" => {
- "3.1.4" => {
- group: [ Chef::Resource::Group, Chef::Provider::Group::Usermod ]
+ "hpux" => {
+ "3.1.4" => {
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Usermod ]
+ }
}
}
- }
- },
+ },
- "netbsd" => {
"netbsd" => {
"netbsd" => {
- "3.1.4" => {
- group: [ Chef::Resource::Group, Chef::Provider::Group::Groupmod ],
+ "netbsd" => {
+ "3.1.4" => {
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Groupmod ],
+ },
},
},
},
- },
-
- "openbsd" => {
- group: [ Chef::Resource::Group, Chef::Provider::Group::Usermod ],
- package: [ Chef::Resource::OpenbsdPackage, Chef::Provider::Package::Openbsd ],
"openbsd" => {
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Usermod ],
+ package: [ Chef::Resource::OpenbsdPackage, Chef::Provider::Package::Openbsd ],
+
"openbsd" => {
- "3.1.4" => {
+ "openbsd" => {
+ "3.1.4" => {
+ },
},
},
},
- },
- "solaris2" => {
- group: [ Chef::Resource::Group, Chef::Provider::Group::Usermod ],
- ips_package: [ Chef::Resource::IpsPackage, Chef::Provider::Package::Ips ],
- package: [ Chef::Resource::SolarisPackage, Chef::Provider::Package::Solaris ],
- mount: [ Chef::Resource::Mount, Chef::Provider::Mount::Solaris ],
- solaris_package: [ Chef::Resource::SolarisPackage, Chef::Provider::Package::Solaris ],
-
- "smartos" => {
- smartos_package: [ Chef::Resource::SmartosPackage, Chef::Provider::Package::SmartOS ],
- package: [ Chef::Resource::SmartosPackage, Chef::Provider::Package::SmartOS ],
+ "solaris2" => {
+ group: [ Chef::Resource::Group, Chef::Provider::Group::Usermod ],
+ ips_package: [ Chef::Resource::IpsPackage, Chef::Provider::Package::Ips ],
+ package: [ Chef::Resource::SolarisPackage, Chef::Provider::Package::Solaris ],
+ mount: [ Chef::Resource::Mount, Chef::Provider::Mount::Solaris ],
+ solaris_package: [ Chef::Resource::SolarisPackage, Chef::Provider::Package::Solaris ],
"smartos" => {
- "3.1.4" => {
+ smartos_package: [ Chef::Resource::SmartosPackage, Chef::Provider::Package::SmartOS ],
+ package: [ Chef::Resource::SmartosPackage, Chef::Provider::Package::SmartOS ],
+
+ "smartos" => {
+ "3.1.4" => {
+ },
},
},
- },
- "solaris2" => {
- "nexentacore" => {
- "3.1.4" => {
+ "solaris2" => {
+ "nexentacore" => {
+ "3.1.4" => {
+ },
},
- },
- "omnios" => {
- "3.1.4" => {
- user: [ Chef::Resource::User, Chef::Provider::User::Solaris ],
- }
- },
- "openindiana" => {
- "3.1.4" => {
+ "omnios" => {
+ "3.1.4" => {
+ user: [ Chef::Resource::User, Chef::Provider::User::Solaris ],
+ }
},
- },
- "opensolaris" => {
- "3.1.4" => {
+ "openindiana" => {
+ "3.1.4" => {
+ },
},
- },
- "solaris2" => {
- user: [ Chef::Resource::User, Chef::Provider::User::Solaris ],
- "5.11" => {
- package: [ Chef::Resource::IpsPackage, Chef::Provider::Package::Ips ],
+ "opensolaris" => {
+ "3.1.4" => {
+ },
},
- "5.9" => {
+ "solaris2" => {
+ user: [ Chef::Resource::User, Chef::Provider::User::Solaris ],
+ "5.11" => {
+ package: [ Chef::Resource::IpsPackage, Chef::Provider::Package::Ips ],
+ },
+ "5.9" => {
+ },
},
},
- },
- },
+ },
- "solaris" => {
"solaris" => {
"solaris" => {
- "3.1.4" => {
+ "solaris" => {
+ "3.1.4" => {
+ },
},
},
},
- },
- "exherbo" => {
"exherbo" => {
"exherbo" => {
- "3.1.4" => {
- # TODO should be Chef::Resource::PaludisPackage
- package: [ Chef::Resource::Package, Chef::Provider::Package::Paludis ]
+ "exherbo" => {
+ "3.1.4" => {
+ # TODO should be Chef::Resource::PaludisPackage
+ package: [ Chef::Resource::Package, Chef::Provider::Package::Paludis ]
+ }
}
}
}
}
- }
-
- def self.create_provider_tests(providers, test, expected, filter)
- expected = expected.merge(providers.select { |key, value| key.is_a?(Symbol) })
- providers.each do |key, value|
- if !key.is_a?(Symbol)
- next_test = test.merge({ filter => key })
- next_filter =
- case filter
- when :os
- :platform_family
- when :platform_family
- :platform
- when :platform
- :platform_version
- when :platform_version
- nil
- else
- raise "Hash too deep; only os, platform_family, platform and platform_version supported"
- end
- create_provider_tests(value, next_test, expected, next_filter)
+
+ def self.create_provider_tests(providers, test, expected, filter)
+ expected = expected.merge(providers.select { |key, value| key.is_a?(Symbol) })
+ providers.each do |key, value|
+ if !key.is_a?(Symbol)
+ next_test = test.merge({ filter => key })
+ next_filter =
+ case filter
+ when :os
+ :platform_family
+ when :platform_family
+ :platform
+ when :platform
+ :platform_version
+ when :platform_version
+ nil
+ else
+ raise "Hash too deep; only os, platform_family, platform and platform_version supported"
+ end
+ create_provider_tests(value, next_test, expected, next_filter)
+ end
end
- end
- # If there is no filter, we're as deep as we need to go
- if !filter
- on_platform test.delete(:platform), test do
- expect_providers(expected)
+ # If there is no filter, we're as deep as we need to go
+ if !filter
+ on_platform test.delete(:platform), test do
+ expect_providers(expected)
+ end
end
end
- end
- create_provider_tests(PROVIDERS, {}, {}, :os)
+ create_provider_tests(PROVIDERS, {}, {}, :os)
+ end
end
diff --git a/tasks/external_tests.rb b/tasks/external_tests.rb
index 2ff991ddf7..9304244424 100644
--- a/tasks/external_tests.rb
+++ b/tasks/external_tests.rb
@@ -1,29 +1,53 @@
-task :chef_sugar_spec do
- gem_path = Bundler.environment.specs['chef-sugar'].first.full_gem_path
- system("cd #{gem_path} && rake")
-end
+require 'tempfile'
-task :foodcritic_spec do
- gem_path = Bundler.environment.specs['foodcritic'].first.full_gem_path
- system("cd #{gem_path} && rake test")
+def bundle_exec_with_chef(test_gem, commands)
+ gem_path = Bundler.environment.specs[test_gem].first.full_gem_path
+ gemfile_path = File.join(gem_path, 'Gemfile.chef-external-test')
+ gemfile = File.open(gemfile_path, "w")
+ begin
+ IO.read(File.join(gem_path, 'Gemfile')).each_line do |line|
+ if line =~ /^\s*gemspec/
+ next
+ elsif line =~ /^\s*gem 'chef'|\s*gem "chef"/
+ next
+ elsif line =~ /^\s*dev_gem\s*['"](.+)['"]\s*$/
+ line = "gem '#{$1}', github: 'poise/#{$1}'"
+ elsif line =~ /\s*gem\s*['"]#{test_gem}['"]/ # foodcritic
+ next
+ end
+ gemfile.puts(line)
+ end
+ gemfile.puts("gem 'chef', path: #{File.expand_path('../..', __FILE__).inspect}")
+ gemfile.puts("gemspec path: #{gem_path.inspect}")
+ gemfile.close
+ Dir.chdir(gem_path) do
+ system({ 'BUNDLE_GEMFILE' => gemfile.path, 'RUBYOPT' => nil }, "bundle install")
+ Array(commands).each do |command|
+ system({ 'BUNDLE_GEMFILE' => gemfile.path, 'RUBYOPT' => nil }, "bundle exec #{command}")
+ end
+ end
+ ensure
+ File.delete(gemfile_path)
+ end
end
-task :chefspec_spec do
- gem_path = Bundler.environment.specs['chefspec'].first.full_gem_path
- system("cd #{gem_path} && rake")
-end
+EXTERNAL_PROJECTS = {
+ "chef-zero" => [ "rake spec", "rake pedant" ],
+ "cheffish" => "rake spec",
+ "chef-provisioning" => "rake spec",
+ "chef-provisioning-aws" => "rake spec",
+ "chef-sugar" => "rake",
+ "foodcritic" => "rake test",
+ "chefspec" => "rake",
+ "chef-rewind" => "rake spec",
+ "poise" => "rake spec",
+ "halite" => "rake spec"
+}
-task :chef_rewind_spec do
- gem_path = Bundler.environment.specs['chef-rewind'].first.full_gem_path
- system("cd #{gem_path} && rake spec")
-end
-
-task :poise_spec do
- gem_path = Bundler.environment.specs['poise'].first.full_gem_path
- system("cd #{gem_path} && rake spec")
-end
+task :external_specs => EXTERNAL_PROJECTS.keys.map { |g| :"#{g.sub("-","_")}_spec" }
-task :halite_spec do
- gem_path = Bundler.environment.specs['halite'].first.full_gem_path
- system("cd #{gem_path} && rake spec")
+EXTERNAL_PROJECTS.each do |test_gem, commands|
+ task :"#{test_gem.gsub('-','_')}_spec" do
+ bundle_exec_with_chef(test_gem, commands)
+ end
end