summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml12
-rw-r--r--CHANGELOG.md17
-rw-r--r--Gemfile.lock14
-rw-r--r--ROADMAP.md11
-rw-r--r--VERSION2
-rw-r--r--chef-config/lib/chef-config/version.rb2
-rw-r--r--chef-config/spec/unit/config_spec.rb4
-rw-r--r--chef.gemspec2
-rwxr-xr-xci/verify-chef.sh3
-rw-r--r--kitchen-tests/cookbooks/base/metadata.rb3
-rw-r--r--kitchen-tests/cookbooks/base/recipes/default.rb3
-rw-r--r--lib/chef/api_client/registration.rb10
-rw-r--r--lib/chef/application/client.rb2
-rw-r--r--lib/chef/chef_fs/chef_fs_data_store.rb5
-rw-r--r--lib/chef/knife/configure.rb4
-rw-r--r--lib/chef/knife/ssh.rb2
-rw-r--r--lib/chef/provider/ifconfig/debian.rb6
-rw-r--r--lib/chef/provider/package/powershell.rb29
-rw-r--r--lib/chef/resource/apt_package.rb3
-rw-r--r--lib/chef/resource/apt_preference.rb8
-rw-r--r--lib/chef/resource/apt_repository.rb8
-rw-r--r--lib/chef/resource/apt_update.rb7
-rw-r--r--lib/chef/resource/bash.rb10
-rw-r--r--lib/chef/resource/batch.rb14
-rw-r--r--lib/chef/resource/bff_package.rb9
-rw-r--r--lib/chef/resource/breakpoint.rb15
-rw-r--r--lib/chef/resource/cab_package.rb7
-rw-r--r--lib/chef/resource/chocolatey_package.rb8
-rw-r--r--lib/chef/resource/cookbook_file.rb21
-rw-r--r--lib/chef/resource/cron.rb5
-rw-r--r--lib/chef/resource/csh.rb10
-rw-r--r--lib/chef/resource/directory.rb11
-rw-r--r--lib/chef/resource/dnf_package.rb13
-rw-r--r--lib/chef/resource/dpkg_package.rb6
-rw-r--r--lib/chef/resource/dsc_resource.rb11
-rw-r--r--lib/chef/resource/dsc_script.rb14
-rw-r--r--lib/chef/resource/execute.rb8
-rw-r--r--lib/chef/resource/file.rb3
-rw-r--r--lib/chef/resource/freebsd_package.rb3
-rw-r--r--lib/chef/resource/gem_package.rb7
-rw-r--r--lib/chef/resource/git.rb6
-rw-r--r--lib/chef/resource/group.rb5
-rw-r--r--lib/chef/resource/homebrew_package.rb6
-rw-r--r--lib/chef/resource/hostname.rb252
-rw-r--r--lib/chef/resource/http_request.rb6
-rw-r--r--lib/chef/resource/ifconfig.rb5
-rw-r--r--lib/chef/resource/ips_package.rb3
-rw-r--r--lib/chef/resource/ksh.rb13
-rw-r--r--lib/chef/resource/launchd.rb6
-rw-r--r--lib/chef/resource/macos_userdefaults.rb126
-rw-r--r--lib/chef/resource/ohai_hint.rb96
-rw-r--r--lib/chef/resource/powershell_package.rb1
-rw-r--r--lib/chef/resource/rhsm_errata.rb45
-rw-r--r--lib/chef/resource/rhsm_errata_level.rb53
-rw-r--r--lib/chef/resource/rhsm_register.rb170
-rw-r--r--lib/chef/resource/rhsm_repo.rb63
-rw-r--r--lib/chef/resource/rhsm_subscription.rb96
-rw-r--r--lib/chef/resources.rb8
-rw-r--r--lib/chef/version.rb2
-rw-r--r--omnibus_overrides.rb2
-rw-r--r--spec/unit/knife/configure_spec.rb3
-rw-r--r--spec/unit/provider/package/powershell_spec.rb265
-rw-r--r--spec/unit/resource/hostname_spec.rb43
-rw-r--r--spec/unit/resource/macos_user_defaults_spec.rb45
-rw-r--r--spec/unit/resource/ohai_hint_spec.rb43
-rw-r--r--spec/unit/resource/powershell_package_spec.rb9
-rw-r--r--spec/unit/resource/rhsm_errata_level_spec.rb46
-rw-r--r--spec/unit/resource/rhsm_errata_spec.rb35
-rw-r--r--spec/unit/resource/rhsm_register_spec.rb199
-rw-r--r--spec/unit/resource/rhsm_repo_spec.rb59
-rw-r--r--spec/unit/resource/rhsm_subscription_spec.rb93
72 files changed, 1919 insertions, 220 deletions
diff --git a/.gitignore b/.gitignore
index 35aecf92cc..2e2447ae2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,6 @@ kitchen-tests/vendor
# Visual Studio Code files
.vscode
+
+# ignore nodes generated during local testing
+nodes/
diff --git a/.travis.yml b/.travis.yml
index db5edab1ad..7f3a518d53 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -61,18 +61,18 @@ matrix:
- env:
UNIT_SPECS_24: 1
rvm: 2.4.3
- sudo: true
+ sudo: false
script:
- - sudo -E $(which bundle) exec rake spec:unit;
- - sudo -E $(which bundle) exec rake component_specs
+ - bundle exec rake spec:unit;
+ - bundle exec rake component_specs
bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
- env:
UNIT_SPECS_25: 1
rvm: 2.5.0
- sudo: true
+ sudo: false
script:
- - sudo -E $(which bundle) exec rake spec:unit;
- - sudo -E $(which bundle) exec rake component_specs
+ - bundle exec rake spec:unit;
+ - bundle exec rake component_specs
bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
- env:
CHEFSTYLE: 1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b6c23086c7..f47f0d905b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,26 @@
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
-<!-- latest_release 14.0.60 -->
-## [v14.0.60](https://github.com/chef/chef/tree/v14.0.60) (2018-02-19)
+<!-- latest_release 14.0.71 -->
+## [v14.0.71](https://github.com/chef/chef/tree/v14.0.71) (2018-02-21)
#### Merged Pull Requests
-- registry_key: Add sensitive property support for suppressing output (fixes #5695) [#6496](https://github.com/chef/chef/pull/6496) ([shoekstra](https://github.com/shoekstra))
+- Disable sudo on unit tests [#6879](https://github.com/chef/chef/pull/6879) ([lamont-granquist](https://github.com/lamont-granquist))
<!-- latest_release -->
<!-- release_rollup since=13.7.16 -->
### Changes since 13.7.16 release
#### Merged Pull Requests
+- Disable sudo on unit tests [#6879](https://github.com/chef/chef/pull/6879) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.71 -->
+- Add macos_user_defaults resource from mac_os_x cookbook [#6878](https://github.com/chef/chef/pull/6878) ([tas50](https://github.com/tas50)) <!-- 14.0.70 -->
+- updating paranoid to verify_host_key [#6869](https://github.com/chef/chef/pull/6869) ([tarcinil](https://github.com/tarcinil)) <!-- 14.0.69 -->
+- make sure all proxy settings are dealt with [#6875](https://github.com/chef/chef/pull/6875) ([thommay](https://github.com/thommay)) <!-- 14.0.68 -->
+- fix chefstyle [#6874](https://github.com/chef/chef/pull/6874) ([thommay](https://github.com/thommay)) <!-- 14.0.67 -->
+- check identifier to resolve exported cookbooks by chef export [#6859](https://github.com/chef/chef/pull/6859) ([sawanoboly](https://github.com/sawanoboly)) <!-- 14.0.66 -->
+- Add ohai_hint resource from ohai cookbook [#6793](https://github.com/chef/chef/pull/6793) ([tas50](https://github.com/tas50)) <!-- 14.0.65 -->
+- Add powershell_package source param [#6843](https://github.com/chef/chef/pull/6843) ([Happycoil](https://github.com/Happycoil)) <!-- 14.0.64 -->
+- Add new Redhat Subscription Manager resources [#6827](https://github.com/chef/chef/pull/6827) ([tas50](https://github.com/tas50)) <!-- 14.0.63 -->
+- fix ohai tests after require_plugin removal [#6867](https://github.com/chef/chef/pull/6867) ([thommay](https://github.com/thommay)) <!-- 14.0.62 -->
+- Add hostname resource from chef_hostname cookbook [#6795](https://github.com/chef/chef/pull/6795) ([tas50](https://github.com/tas50)) <!-- 14.0.61 -->
- registry_key: Add sensitive property support for suppressing output (fixes #5695) [#6496](https://github.com/chef/chef/pull/6496) ([shoekstra](https://github.com/shoekstra)) <!-- 14.0.60 -->
- Use the updated inspec gem - 1.51.18 [#6845](https://github.com/chef/chef/pull/6845) ([tas50](https://github.com/tas50)) <!-- 14.0.59 -->
- add Chef::NodeMap#delete_class API [#6846](https://github.com/chef/chef/pull/6846) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.58 -->
diff --git a/Gemfile.lock b/Gemfile.lock
index 8d83200775..b21f28e410 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -35,10 +35,10 @@ GIT
PATH
remote: .
specs:
- chef (14.0.60)
+ chef (14.0.71)
addressable
bundler (>= 1.10)
- chef-config (= 14.0.60)
+ chef-config (= 14.0.71)
chef-zero (>= 13.0)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
@@ -52,7 +52,7 @@ PATH
mixlib-log (~> 1.3)
mixlib-shellout (~> 2.0)
net-sftp (~> 2.1, >= 2.1.2)
- net-ssh (>= 2.9, < 5.0)
+ net-ssh (~> 4.2)
net-ssh-multi (~> 1.2, >= 1.2.1)
ohai (~> 14.0)
plist (~> 3.2)
@@ -65,10 +65,10 @@ PATH
specinfra (~> 2.10)
syslog-logger (~> 1.6)
uuidtools (~> 2.1.5)
- chef (14.0.60-universal-mingw32)
+ chef (14.0.71-universal-mingw32)
addressable
bundler (>= 1.10)
- chef-config (= 14.0.60)
+ chef-config (= 14.0.71)
chef-zero (>= 13.0)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
@@ -83,7 +83,7 @@ PATH
mixlib-log (~> 1.3)
mixlib-shellout (~> 2.0)
net-sftp (~> 2.1, >= 2.1.2)
- net-ssh (>= 2.9, < 5.0)
+ net-ssh (~> 4.2)
net-ssh-multi (~> 1.2, >= 1.2.1)
ohai (~> 14.0)
plist (~> 3.2)
@@ -110,7 +110,7 @@ PATH
PATH
remote: chef-config
specs:
- chef-config (14.0.60)
+ chef-config (14.0.71)
addressable
fuzzyurl
mixlib-config (~> 2.0)
diff --git a/ROADMAP.md b/ROADMAP.md
deleted file mode 100644
index eeec513a3f..0000000000
--- a/ROADMAP.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Roadmap
-
-This file provides direction for the project as set forth by [RFC030#Roadmap](https://github.com/chef/chef-rfc/blob/master/rfc030-maintenance-policy.md#roadmap).
-
-It is drafted by the Project Lead and the Lieutenants, with input from Maintainers and Contributors.
-
-## 2016 Q1
-* Windows - core windows_feature
- - Move windows_feature from Windows cookbook, add caching
-* Windows - knife windows bootstrap, knife windows winrm in core
- - Migrate Windows bootstrapping functionality into core
diff --git a/VERSION b/VERSION
index e76cd1fbec..dfdd04d7de 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-14.0.60 \ No newline at end of file
+14.0.71 \ No newline at end of file
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index b378970758..44c07a0d8d 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.expand_path("../..", __FILE__)
- VERSION = "14.0.60"
+ VERSION = "14.0.71"
end
#
diff --git a/chef-config/spec/unit/config_spec.rb b/chef-config/spec/unit/config_spec.rb
index f5e9a914c9..41b4382cf0 100644
--- a/chef-config/spec/unit/config_spec.rb
+++ b/chef-config/spec/unit/config_spec.rb
@@ -852,9 +852,13 @@ RSpec.describe ChefConfig::Config do
before(:all) do
@original_env = ENV.to_hash
ENV["http_proxy"] = nil
+ ENV["HTTP_PROXY"] = nil
ENV["https_proxy"] = nil
+ ENV["HTTPS_PROXY"] = nil
ENV["ftp_proxy"] = nil
+ ENV["FTP_PROXY"] = nil
ENV["no_proxy"] = nil
+ ENV["NO_PROXY"] = nil
end
after(:all) do
diff --git a/chef.gemspec b/chef.gemspec
index 9dd85d74c6..352ce5dab0 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
s.add_dependency "ohai", "~> 14.0"
s.add_dependency "ffi-yajl", "~> 2.2"
- s.add_dependency "net-ssh", ">= 2.9", "< 5.0"
+ s.add_dependency "net-ssh", "~> 4.2"
s.add_dependency "net-ssh-multi", "~> 1.2", ">= 1.2.1"
s.add_dependency "net-sftp", "~> 2.1", ">= 2.1.2"
s.add_dependency "highline", "~> 1.6", ">= 1.6.9"
diff --git a/ci/verify-chef.sh b/ci/verify-chef.sh
index 528152b3b6..3a9bcf2111 100755
--- a/ci/verify-chef.sh
+++ b/ci/verify-chef.sh
@@ -8,6 +8,9 @@ export TMPDIR
sudo rm -rf $TMPDIR
mkdir -p $TMPDIR
+# Verify that we kill any orphaned test processes. Kill any orphaned rspec processes.
+ps ax | egrep 'rspec' | grep -v grep | awk '{ print $1 }' | xargs sudo kill -s KILL || true
+
# $PROJECT_NAME is set by Jenkins, this allows us to use the same script to verify
# Chef and Angry Chef
PATH=/opt/$PROJECT_NAME/bin:$PATH
diff --git a/kitchen-tests/cookbooks/base/metadata.rb b/kitchen-tests/cookbooks/base/metadata.rb
index 9d4e663bec..83d460a17b 100644
--- a/kitchen-tests/cookbooks/base/metadata.rb
+++ b/kitchen-tests/cookbooks/base/metadata.rb
@@ -10,10 +10,7 @@ gem "chef-sugar"
depends "apt"
depends "build-essential"
-depends "chef-apt-docker"
depends "chef-client"
-depends "chef-yum-docker"
-depends "chef_hostname"
depends "logrotate"
depends "multipackage"
depends "nscd"
diff --git a/kitchen-tests/cookbooks/base/recipes/default.rb b/kitchen-tests/cookbooks/base/recipes/default.rb
index e2d92cadc4..62823c1d37 100644
--- a/kitchen-tests/cookbooks/base/recipes/default.rb
+++ b/kitchen-tests/cookbooks/base/recipes/default.rb
@@ -44,9 +44,6 @@ include_recipe "chef-client::delete_validation"
include_recipe "chef-client::config"
include_recipe "chef-client"
-include_recipe "chef-apt-docker"
-include_recipe "chef-yum-docker"
-
include_recipe "openssh"
include_recipe "nscd"
diff --git a/lib/chef/api_client/registration.rb b/lib/chef/api_client/registration.rb
index e61ef4a160..27e1f18c17 100644
--- a/lib/chef/api_client/registration.rb
+++ b/lib/chef/api_client/registration.rb
@@ -70,15 +70,15 @@ class Chef
end
def assert_destination_writable!
- if !File.exists?(File.dirname(destination))
+ abs_path = File.expand_path(destination)
+ if !File.exists?(File.dirname(abs_path))
begin
- FileUtils.mkdir_p(File.dirname(destination))
+ FileUtils.mkdir_p(File.dirname(abs_path))
rescue Errno::EACCES
- raise Chef::Exceptions::CannotWritePrivateKey, "I can't write your private key to #{abs_path} - check permissions?"
+ raise Chef::Exceptions::CannotWritePrivateKey, "I can't create the configuration directory at #{File.dirname(abs_path)} - check permissions?"
end
end
- if (File.exists?(destination) && !File.writable?(destination)) || !File.writable?(File.dirname(destination))
- abs_path = File.expand_path(destination)
+ if (File.exists?(abs_path) && !File.writable?(abs_path)) || !File.writable?(File.dirname(abs_path))
raise Chef::Exceptions::CannotWritePrivateKey, "I can't write your private key to #{abs_path} - check permissions?"
end
end
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index 32530925d5..0834e5f037 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -345,6 +345,8 @@ class Chef::Application::Client < Chef::Application
tarball_path = File.join(Chef::Config.chef_repo_path, "recipes.tgz")
fetch_recipe_tarball(Chef::Config[:recipe_url], tarball_path)
Mixlib::Archive.new(tarball_path).extract(Chef::Config.chef_repo_path, perms: false, ignore: /^\.$/)
+ config_path = File.join(Chef::Config.chef_repo_path, ".chef/config.rb")
+ Chef::Config.from_string(IO.read(config_path), config_path) if File.file?(config_path)
end
end
diff --git a/lib/chef/chef_fs/chef_fs_data_store.rb b/lib/chef/chef_fs/chef_fs_data_store.rb
index 4f248625b3..cdb793f808 100644
--- a/lib/chef/chef_fs/chef_fs_data_store.rb
+++ b/lib/chef/chef_fs/chef_fs_data_store.rb
@@ -309,7 +309,10 @@ class Chef
elsif %w{cookbooks cookbook_artifacts}.include?(path[0]) && path.length == 3
with_entry([path[0]]) do |entry|
cookbook_type = path[0]
- cookbook_entry = entry.children.select { |child| child.chef_object.full_name == "#{path[1]}-#{path[2]}" }[0]
+ cookbook_entry = entry.children.select do |child|
+ child.chef_object.full_name == "#{path[1]}-#{path[2]}" ||
+ (child.chef_object.name.to_s == path[1] && child.chef_object.identifier == path[2])
+ end[0]
raise ChefZero::DataStore::DataNotFoundError.new(path) if cookbook_entry.nil?
result = nil
begin
diff --git a/lib/chef/knife/configure.rb b/lib/chef/knife/configure.rb
index 10ae62b6c9..b277a14a3e 100644
--- a/lib/chef/knife/configure.rb
+++ b/lib/chef/knife/configure.rb
@@ -131,9 +131,7 @@ EOH
def guess_servername
o = Ohai::System.new
- o.load_plugins
- o.require_plugin "os"
- o.require_plugin "hostname"
+ o.all_plugins(%w{ os hostname fqdn })
o[:fqdn] || o[:machinename] || o[:hostname] || "localhost"
end
diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb
index 885ebc4faa..e02ea4ae1d 100644
--- a/lib/chef/knife/ssh.rb
+++ b/lib/chef/knife/ssh.rb
@@ -273,7 +273,7 @@ class Chef
opts[:port] = port unless port.nil?
opts[:logger] = Chef::Log.logger if Chef::Log.level == :debug
if !config[:host_key_verify]
- opts[:paranoid] = false
+ opts[:verify_host_key] = false
opts[:user_known_hosts_file] = "/dev/null"
end
if ssh_config[:keepalive]
diff --git a/lib/chef/provider/ifconfig/debian.rb b/lib/chef/provider/ifconfig/debian.rb
index 369c222b7a..e1e978fdde 100644
--- a/lib/chef/provider/ifconfig/debian.rb
+++ b/lib/chef/provider/ifconfig/debian.rb
@@ -36,11 +36,11 @@ class Chef
<% if new_resource.onboot == "yes" %>auto <%= new_resource.device %><% end %>
<% case new_resource.bootproto
when "dhcp" %>
-iface <%= new_resource.device %> inet dhcp
+iface <%= new_resource.device %> <%= new_resource.family %> dhcp
<% when "bootp" %>
-iface <%= new_resource.device %> inet bootp
+iface <%= new_resource.device %> <%= new_resource.family %> bootp
<% else %>
-iface <%= new_resource.device %> inet static
+iface <%= new_resource.device %> <%= new_resource.family %> static
<% if new_resource.target %>address <%= new_resource.target %><% end %>
<% if new_resource.mask %>netmask <%= new_resource.mask %><% end %>
<% if new_resource.network %>network <%= new_resource.network %><% end %>
diff --git a/lib/chef/provider/package/powershell.rb b/lib/chef/provider/package/powershell.rb
index 9111869c2b..f553aada0a 100644
--- a/lib/chef/provider/package/powershell.rb
+++ b/lib/chef/provider/package/powershell.rb
@@ -53,7 +53,7 @@ class Chef
# Installs the package specified with the version passed else latest version will be installed
def install_package(names, versions)
names.each_with_index do |name, index|
- powershell_out("Install-Package '#{name}' -Force -ForceBootstrap -RequiredVersion #{versions[index]}", timeout: new_resource.timeout)
+ powershell_out(build_powershell_command("Install-Package '#{name}'", versions[index]), timeout: new_resource.timeout)
end
end
@@ -61,11 +61,11 @@ class Chef
def remove_package(names, versions)
names.each_with_index do |name, index|
if versions && !versions[index].nil?
- powershell_out("Uninstall-Package '#{name}' -Force -ForceBootstrap -RequiredVersion #{versions[index]}", timeout: new_resource.timeout)
+ powershell_out(build_powershell_command("Uninstall-Package '#{name}'", versions[index]), timeout: new_resource.timeout)
else
version = "0"
until version.empty?
- version = powershell_out("(Uninstall-Package '#{name}' -Force -ForceBootstrap).Version", timeout: new_resource.timeout).stdout.strip
+ version = powershell_out(build_powershell_command("Uninstall-Package '#{name}'"), timeout: new_resource.timeout).stdout.strip
unless version.empty?
Chef::Log.info("Removed package '#{name}' with version #{version}")
end
@@ -79,9 +79,9 @@ class Chef
versions = []
new_resource.package_name.each_with_index do |name, index|
version = if new_resource.version && !new_resource.version[index].nil?
- powershell_out("(Find-Package '#{name}' -RequiredVersion #{new_resource.version[index]} -ForceBootstrap -Force).Version", timeout: new_resource.timeout).stdout.strip
+ powershell_out(build_powershell_command("Find-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).stdout.strip
else
- powershell_out("(Find-Package '#{name}' -ForceBootstrap -Force).Version", timeout: new_resource.timeout).stdout.strip
+ powershell_out(build_powershell_command("Find-Package '#{name}'"), timeout: new_resource.timeout).stdout.strip
end
if version.empty?
version = nil
@@ -96,9 +96,9 @@ class Chef
version_list = []
new_resource.package_name.each_with_index do |name, index|
version = if new_resource.version && !new_resource.version[index].nil?
- powershell_out("(Get-Package -Name '#{name}' -RequiredVersion #{new_resource.version[index]} -ForceBootstrap -Force).Version", timeout: new_resource.timeout).stdout.strip
+ powershell_out(build_powershell_command("Get-Package '#{name}'", new_resource.version[index]), timeout: new_resource.timeout).stdout.strip
else
- powershell_out("(Get-Package -Name '#{name}' -ForceBootstrap -Force).Version", timeout: new_resource.timeout).stdout.strip
+ powershell_out(build_powershell_command("Get-Package '#{name}'"), timeout: new_resource.timeout).stdout.strip
end
if version.empty?
version = nil
@@ -108,6 +108,21 @@ class Chef
version_list
end
+ def build_powershell_command(command, version = nil)
+ command = [command] unless command.is_a?(Array)
+ command.unshift("(")
+ %w{-Force -ForceBootstrap}.each do |arg|
+ command.push(arg)
+ end
+ command.push("-RequiredVersion #{version}") if version
+ command.push("-Source #{new_resource.source}") if new_resource.source && command[1] =~ Regexp.union(/Install-Package/, /Find-Package/)
+ command.push(").Version")
+ command.join(" ")
+ end
+
+ def check_resource_semantics!
+ # This validation method from Chef::Provider::Package does not apply here, so no-op it.
+ end
end
end
end
diff --git a/lib/chef/resource/apt_package.rb b/lib/chef/resource/apt_package.rb
index 51e38834b6..ea0c9c6183 100644
--- a/lib/chef/resource/apt_package.rb
+++ b/lib/chef/resource/apt_package.rb
@@ -21,11 +21,12 @@ require "chef/provider/package/apt"
class Chef
class Resource
- # Use the apt_package resource to manage packages on Debian and Ubuntu platforms.
class AptPackage < Chef::Resource::Package
resource_name :apt_package
provides :package, os: "linux", platform_family: "debian"
+ description "Use the apt_package resource to manage packages on Debian and Ubuntu platforms."
+
property :default_release, String, desired_state: false
property :overwrite_config_files, [TrueClass, FalseClass], default: false
diff --git a/lib/chef/resource/apt_preference.rb b/lib/chef/resource/apt_preference.rb
index 87c5a5a016..442d85a78a 100644
--- a/lib/chef/resource/apt_preference.rb
+++ b/lib/chef/resource/apt_preference.rb
@@ -20,14 +20,16 @@ require "chef/resource"
class Chef
class Resource
- # The apt_preference resource allows for the creation of APT preference files. Preference files are used to control
- # which package versions and sources are prioritized during installation.
- #
# @since 13.3
class AptPreference < Chef::Resource
resource_name :apt_preference
provides :apt_preference
+ description "The apt_preference resource allows for the creation of APT preference"\
+ " files. Preference files are used to control which package versions and"\
+ " sources are prioritized during installation."
+ introduced "13.3"
+
property :package_name, String, name_property: true, regex: [/^([a-z]|[A-Z]|[0-9]|_|-|\.|\*|\+)+$/]
property :glob, String
property :pin, String, required: true
diff --git a/lib/chef/resource/apt_repository.rb b/lib/chef/resource/apt_repository.rb
index 5b81112cbe..6b044afe27 100644
--- a/lib/chef/resource/apt_repository.rb
+++ b/lib/chef/resource/apt_repository.rb
@@ -20,14 +20,14 @@ require "chef/resource"
class Chef
class Resource
- # Use the apt_repository resource to specify additional APT repositories. Adding a new repository will update
- # APT package cache immediately.
- #
- # @since 12.9
class AptRepository < Chef::Resource
resource_name :apt_repository
provides :apt_repository
+ description "Use the apt_repository resource to specify additional APT repositories."\
+ " Adding a new repository will update APT package cache immediately."
+ introduced "12.9"
+
property :repo_name, String, name_property: true
property :uri, String
property :distribution, [ String, nil, false ], default: lazy { node["lsb"]["codename"] }, coerce: proc { |x| x ? x : nil }
diff --git a/lib/chef/resource/apt_update.rb b/lib/chef/resource/apt_update.rb
index 0349614ad2..378edd2170 100644
--- a/lib/chef/resource/apt_update.rb
+++ b/lib/chef/resource/apt_update.rb
@@ -20,13 +20,14 @@ require "chef/resource"
class Chef
class Resource
- # Use the apt_update resource to manage APT repository updates on Debian and Ubuntu platforms.
- #
- # @since 12.7
class AptUpdate < Chef::Resource
resource_name :apt_update
provides :apt_update
+ description "Use the apt_update resource to manage APT repository updates on"\
+ " Debian and Ubuntu platforms."
+ introduced "12.7"
+
# allow bare apt_update with no name
property :name, String, default: ""
property :frequency, Integer, default: 86_400
diff --git a/lib/chef/resource/bash.rb b/lib/chef/resource/bash.rb
index ebc4a7790b..03fdd0e396 100644
--- a/lib/chef/resource/bash.rb
+++ b/lib/chef/resource/bash.rb
@@ -21,11 +21,13 @@ require "chef/provider/script"
class Chef
class Resource
- # Use the bash resource to execute scripts using the Bash interpreter. This resource may also use any of the actions
- # and properties that are available to the execute resource. Commands that are executed with this resource are (by
- # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if
- # and only_if to guard this resource for idempotence.
class Bash < Chef::Resource::Script
+ description "Use the bash resource to execute scripts using the Bash interpreter."\
+ " This resource may also use any of the actions and properties that are"\
+ " available to the execute resource. Commands that are executed with this"\
+ " resource are (by their nature) not idempotent, as they are typically"\
+ " unique to the environment in which they are run. Use not_if and only_if"\
+ " to guard this resource for idempotence."
def initialize(name, run_context = nil)
super
diff --git a/lib/chef/resource/batch.rb b/lib/chef/resource/batch.rb
index b3c7b17cef..1c666a46ba 100644
--- a/lib/chef/resource/batch.rb
+++ b/lib/chef/resource/batch.rb
@@ -20,15 +20,17 @@ require "chef/resource/windows_script"
class Chef
class Resource
- # Use the batch resource to execute a batch script using the cmd.exe interpreter on Windows. The batch resource
- # creates and executes a temporary file (similar to how the script resource behaves), rather than running the
- # command inline. Commands that are executed with this resource are (by their nature) not idempotent, as they are
- # typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for
- # idempotence.
class Batch < Chef::Resource::WindowsScript
-
provides :batch, os: "windows"
+ description "Use the batch resource to execute a batch script using the cmd.exe"\
+ " interpreter on Windows. The batch resource creates and executes a"\
+ " temporary file (similar to how the script resource behaves), rather"\
+ " than running the command inline. Commands that are executed with this"\
+ " resource are (by their nature) not idempotent, as they are typically"\
+ " unique to the environment in which they are run. Use not_if and only_if"\
+ " to guard this resource for idempotence."
+
def initialize(name, run_context = nil)
super(name, run_context, nil, "cmd.exe")
end
diff --git a/lib/chef/resource/bff_package.rb b/lib/chef/resource/bff_package.rb
index d91777cb74..f67d6d253e 100644
--- a/lib/chef/resource/bff_package.rb
+++ b/lib/chef/resource/bff_package.rb
@@ -21,11 +21,12 @@ require "chef/provider/package/aix"
class Chef
class Resource
- # Use the bff_package resource to manage packages for the AIX platform using the installp utility. When a package is
- # installed from a local file, it must be added to the node using the remote_file or cookbook_file resources.
- #
- # @since 12.0
class BffPackage < Chef::Resource::Package
+ description "Use the bff_package resource to manage packages for the AIX platform"\
+ " using the installp utility. When a package is installed from a local"\
+ " file, it must be added to the node using the remote_file or cookbook_file"\
+ " resources."
+ introduced "12.0"
end
end
end
diff --git a/lib/chef/resource/breakpoint.rb b/lib/chef/resource/breakpoint.rb
index 5d2c5555be..1ccc4311b3 100644
--- a/lib/chef/resource/breakpoint.rb
+++ b/lib/chef/resource/breakpoint.rb
@@ -20,16 +20,19 @@ require "chef/resource"
class Chef
class Resource
- # Use the breakpoint resource to add breakpoints to recipes. Run the chef-shell in chef-client mode, and then use
- # those breakpoints to debug recipes. Breakpoints are ignored by the chef-client during an actual chef-client run.
- # That said, breakpoints are typically used to debug recipes only when running them in a non-production environment,
- # after which they are removed from those recipes before the parent cookbook is uploaded to the Chef server.
- #
- # @since 12.0
class Breakpoint < Chef::Resource
provides :breakpoint
resource_name :breakpoint
+ description "Use the breakpoint resource to add breakpoints to recipes. Run the"\
+ " chef-shell in chef-client mode, and then use those breakpoints to debug"\
+ " recipes. Breakpoints are ignored by the chef-client during an actual"\
+ " chef-client run. That said, breakpoints are typically used to debug"\
+ " recipes only when running them in a non-production environment, after"\
+ " which they are removed from those recipes before the parent cookbook is"\
+ " uploaded to the Chef server."
+ introduced "12.0"
+
default_action :break
def initialize(action = "break", *args)
diff --git a/lib/chef/resource/cab_package.rb b/lib/chef/resource/cab_package.rb
index 8f3b3038c4..06c84fa559 100644
--- a/lib/chef/resource/cab_package.rb
+++ b/lib/chef/resource/cab_package.rb
@@ -21,15 +21,16 @@ require "chef/mixin/uris"
class Chef
class Resource
- # Use the cab_package resource to install or remove Microsoft Windows cabinet (.cab) packages.
- #
- # @since 12.15
class CabPackage < Chef::Resource::Package
include Chef::Mixin::Uris
resource_name :cab_package
provides :cab_package, os: "windows"
+ description "Use the cab_package resource to install or remove Microsoft Windows"\
+ " cabinet (.cab) packages."
+ introduced "12.15"
+
allowed_actions :install, :remove
property :source, String,
diff --git a/lib/chef/resource/chocolatey_package.rb b/lib/chef/resource/chocolatey_package.rb
index 58bcab8b39..c5a5d827a2 100644
--- a/lib/chef/resource/chocolatey_package.rb
+++ b/lib/chef/resource/chocolatey_package.rb
@@ -20,14 +20,14 @@ require "chef/resource/package"
class Chef
class Resource
- # Use the chocolatey_package resource to manage packages using Chocolatey on the Microsoft Windows platform.
- #
- # @since 12.7
class ChocolateyPackage < Chef::Resource::Package
-
resource_name :chocolatey_package
provides :chocolatey_package, os: "windows"
+ description "Use the chocolatey_package resource to manage packages using Chocolatey"\
+ " on the Microsoft Windows platform."
+ introduced "12.7"
+
allowed_actions :install, :upgrade, :remove, :uninstall, :purge, :reconfig
# windows can't take Array options yet
diff --git a/lib/chef/resource/cookbook_file.rb b/lib/chef/resource/cookbook_file.rb
index 8c3de119e9..593cb5e137 100644
--- a/lib/chef/resource/cookbook_file.rb
+++ b/lib/chef/resource/cookbook_file.rb
@@ -24,20 +24,23 @@ require "chef/mixin/securable"
class Chef
class Resource
- # Use the cookbook_file resource to transfer files from a sub-directory of COOKBOOK_NAME/files/ to a specified path
- # located on a host that is running the chef-client. The file is selected according to file specificity, which allows
- # different source files to be used based on the hostname, host platform (operating system, distro, or as appropriate),
- # or platform version. Files that are located in the COOKBOOK_NAME/files/default sub-directory may be used on any
- # platform.
- #
- # During a chef-client run, the checksum for each local file is calculated and then compared against the checksum for
- # the same file as it currently exists in the cookbook on the Chef server. A file is not transferred when the checksums
- # match. Only files that require an update are transferred from the Chef server to a node.
class CookbookFile < Chef::Resource::File
include Chef::Mixin::Securable
resource_name :cookbook_file
+ description "Use the cookbook_file resource to transfer files from a sub-directory"\
+ " of COOKBOOK_NAME/files/ to a specified path located on a host that is"\
+ " running the chef-client. The file is selected according to file specificity,"\
+ " which allows different source files to be used based on the hostname, host"\
+ " platform (operating system, distro, or as appropriate), or platform version."\
+ " Files that are located in the COOKBOOK_NAME/files/default sub-directory may be"\
+ " used on any platform.\n\n"\
+ "During a chef-client run, the checksum for each local file is calculated and then"\
+ " compared against the checksum for the same file as it currently exists in the"\
+ " cookbook on the Chef server. A file is not transferred when the checksums match."\
+ " Only files that require an update are transferred from the Chef server to a node."
+
property :source, [ String, Array ], default: lazy { ::File.basename(name) }
property :cookbook, String
diff --git a/lib/chef/resource/cron.rb b/lib/chef/resource/cron.rb
index 2b70be7bb8..72023c31ed 100644
--- a/lib/chef/resource/cron.rb
+++ b/lib/chef/resource/cron.rb
@@ -21,9 +21,10 @@ require "chef/resource"
class Chef
class Resource
- # Use the cron resource to manage cron entries for time-based job scheduling. Properties for a schedule will default
- # to * if not provided. The cron resource requires access to a crontab program, typically cron.
class Cron < Chef::Resource
+ description "Use the cron resource to manage cron entries for time-based job scheduling."\
+ " Properties for a schedule will default to * if not provided. The cron resource"\
+ " requires access to a crontab program, typically cron."
identity_attr :command
diff --git a/lib/chef/resource/csh.rb b/lib/chef/resource/csh.rb
index ef302af6c0..0938a19cb1 100644
--- a/lib/chef/resource/csh.rb
+++ b/lib/chef/resource/csh.rb
@@ -21,11 +21,13 @@ require "chef/provider/script"
class Chef
class Resource
- # Use the csh resource to execute scripts using the csh interpreter. This resource may also use any of the actions
- # and properties that are available to the execute resource. Commands that are executed with this resource are (by
- # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if
- # and only_if to guard this resource for idempotence.
class Csh < Chef::Resource::Script
+ description "Use the csh resource to execute scripts using the csh interpreter."\
+ " This resource may also use any of the actions and properties that are"\
+ " available to the execute resource. Commands that are executed with this"\
+ " resource are (by their nature) not idempotent, as they are typically"\
+ " unique to the environment in which they are run. Use not_if and only_if"\
+ " to guard this resource for idempotence."
def initialize(name, run_context = nil)
super
diff --git a/lib/chef/resource/directory.rb b/lib/chef/resource/directory.rb
index b989b3ecde..1f18a4b951 100644
--- a/lib/chef/resource/directory.rb
+++ b/lib/chef/resource/directory.rb
@@ -23,13 +23,16 @@ require "chef/mixin/securable"
class Chef
class Resource
- # Use the directory resource to manage a directory, which is a hierarchy of folders that comprises all of the
- # information stored on a computer. The root directory is the top-level, under which the rest of the directory
- # is organized. The directory resource uses the name property to specify the path to a location in a directory.
- # Typically, permission to access that location in the directory is required.
class Directory < Chef::Resource
resource_name :directory
+ description "Use the directory resource to manage a directory, which is a hierarchy"\
+ " of folders that comprises all of the information stored on a computer."\
+ " The root directory is the top-level, under which the rest of the directory"\
+ " is organized. The directory resource uses the name property to specify the"\
+ " path to a location in a directory. Typically, permission to access that"\
+ " location in the directory is required."
+
state_attrs :group, :mode, :owner
include Chef::Mixin::Securable
diff --git a/lib/chef/resource/dnf_package.rb b/lib/chef/resource/dnf_package.rb
index 0e09d90d43..08d19ff6b9 100644
--- a/lib/chef/resource/dnf_package.rb
+++ b/lib/chef/resource/dnf_package.rb
@@ -21,17 +21,20 @@ require "chef/mixin/shell_out"
class Chef
class Resource
- # Use the dnf_package resource to install, upgrade, and remove packages with DNF for Fedora platforms. The dnf_package
- # resource is able to resolve provides data for packages much like DNF can do when it is run from the command line.
- # This allows a variety of options for installing packages, like minimum versions, virtual provides, and library names.
- #
- # @since 12.18
class DnfPackage < Chef::Resource::Package
extend Chef::Mixin::Which
extend Chef::Mixin::ShellOut
resource_name :dnf_package
+ description "Use the dnf_package resource to install, upgrade, and remove packages"\
+ " with DNF for Fedora platforms. The dnf_package resource is able to"\
+ " resolve provides data for packages much like DNF can do when it is"\
+ " run from the command line. This allows a variety of options for"\
+ " installing packages, like minimum versions, virtual provides,"\
+ " and library names."
+ introduced "12.18"
+
allowed_actions :install, :upgrade, :remove, :purge, :reconfig, :lock, :unlock, :flush_cache
# all rhel variants >= 8 will use DNF
diff --git a/lib/chef/resource/dpkg_package.rb b/lib/chef/resource/dpkg_package.rb
index c73fc506ad..488af8e1c9 100644
--- a/lib/chef/resource/dpkg_package.rb
+++ b/lib/chef/resource/dpkg_package.rb
@@ -20,12 +20,14 @@ require "chef/resource/package"
class Chef
class Resource
- # Use the dpkg_package resource to manage packages for the dpkg platform. When a package is installed from a local
- # file, it must be added to the node using the remote_file or cookbook_file resources.
class DpkgPackage < Chef::Resource::Package
resource_name :dpkg_package
provides :dpkg_package, os: "linux"
+ description "Use the dpkg_package resource to manage packages for the dpkg platform."\
+ " When a package is installed from a local file, it must be added to the"\
+ " node using the remote_file or cookbook_file resources."
+
property :source, [ String, Array, nil ]
end
end
diff --git a/lib/chef/resource/dsc_resource.rb b/lib/chef/resource/dsc_resource.rb
index 0840b9bca1..95ee32c946 100644
--- a/lib/chef/resource/dsc_resource.rb
+++ b/lib/chef/resource/dsc_resource.rb
@@ -19,14 +19,15 @@ require "chef/dsl/powershell"
class Chef
class Resource
- # The dsc_resource resource allows any DSC resource to be used in a Chef recipe, as well as any custom resources
- # that have been added to your Windows PowerShell environment. Microsoft frequently adds new resources to the DSC
- # resource collection.
- #
- # @since 12.2
class DscResource < Chef::Resource
provides :dsc_resource, os: "windows"
+ description "The dsc_resource resource allows any DSC resource to be used in a"\
+ " Chef recipe, as well as any custom resources that have been added"\
+ " to your Windows PowerShell environment. Microsoft frequently adds"\
+ " new resources to the DSC resource collection."
+ introduced "12.2"
+
# This class will check if the object responds to
# to_text. If it does, it will call that as opposed
# to inspect. This is useful for properties that hold
diff --git a/lib/chef/resource/dsc_script.rb b/lib/chef/resource/dsc_script.rb
index cea52e422b..45372c091a 100644
--- a/lib/chef/resource/dsc_script.rb
+++ b/lib/chef/resource/dsc_script.rb
@@ -21,17 +21,21 @@ require "chef/dsl/powershell"
class Chef
class Resource
- # Many DSC resources are comparable to built-in Chef resources. For example, both DSC and Chef have file, package,
- # and service resources. The dsc_script resource is most useful for those DSC resources that do not have a direct
- # comparison to a resource in Chef, such as the Archive resource, a custom DSC resource, an existing DSC script
- # that performs an important task, and so on. Use the dsc_script resource to embed the code that defines a DSC
- # configuration directly within a Chef recipe.
class DscScript < Chef::Resource
include Chef::DSL::Powershell
resource_name :dsc_script
provides :dsc_script, os: "windows"
+ description "Many DSC resources are comparable to built-in Chef resources. For"\
+ " example, both DSC and Chef have file, package, and service resources."\
+ " The dsc_script resource is most useful for those DSC resources that"\
+ " do not have a direct comparison to a resource in Chef, such as the"\
+ " Archive resource, a custom DSC resource, an existing DSC script"\
+ " that performs an important task, and so on. Use the dsc_script resource"\
+ " to embed the code that defines a DSC configuration directly within a"\
+ " Chef recipe."
+
default_action :run
def initialize(name, run_context = nil)
diff --git a/lib/chef/resource/execute.rb b/lib/chef/resource/execute.rb
index 616195deee..0c1b187ed0 100644
--- a/lib/chef/resource/execute.rb
+++ b/lib/chef/resource/execute.rb
@@ -22,13 +22,15 @@ require "chef/provider/execute"
class Chef
class Resource
- # Use the execute resource to execute a single command. Commands that are executed with this resource are (by their
- # nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if
- # to guard this resource for idempotence.
class Execute < Chef::Resource
identity_attr :command
+ description "Use the execute resource to execute a single command. Commands that"\
+ " are executed with this resource are (by their nature) not idempotent,"\
+ " as they are typically unique to the environment in which they are run."\
+ " Use not_if and only_if to guard this resource for idempotence."
+
# The ResourceGuardInterpreter wraps a resource's guards in another resource. That inner resource
# needs to behave differently during (for example) why_run mode, so we flag it here. For why_run mode
# we still want to execute the guard resource even if we are not executing the wrapping resource.
diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb
index 787992fc24..98341ff940 100644
--- a/lib/chef/resource/file.rb
+++ b/lib/chef/resource/file.rb
@@ -25,10 +25,11 @@ require "pathname"
class Chef
class Resource
- # Use the file resource to manage files directly on a node.
class File < Chef::Resource
include Chef::Mixin::Securable
+ description "Use the file resource to manage files directly on a node."
+
if Platform.windows?
# Use Windows rights instead of standard *nix permissions
state_attrs :checksum, :rights, :deny_rights
diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb
index caaba29129..d16355d027 100644
--- a/lib/chef/resource/freebsd_package.rb
+++ b/lib/chef/resource/freebsd_package.rb
@@ -26,13 +26,14 @@ require "chef/mixin/shell_out"
class Chef
class Resource
- # Use the freebsd_package resource to manage packages for the FreeBSD platform.
class FreebsdPackage < Chef::Resource::Package
include Chef::Mixin::ShellOut
resource_name :freebsd_package
provides :package, platform: "freebsd"
+ description "Use the freebsd_package resource to manage packages for the FreeBSD platform."
+
# make sure we assign the appropriate underlying providers based on what
# package managers exist on this FreeBSD system or the source of the package
#
diff --git a/lib/chef/resource/gem_package.rb b/lib/chef/resource/gem_package.rb
index 8e3a426035..1f9bae614d 100644
--- a/lib/chef/resource/gem_package.rb
+++ b/lib/chef/resource/gem_package.rb
@@ -20,11 +20,14 @@ require "chef/resource/package"
class Chef
class Resource
- # Use the gem_package resource to manage gem packages that are only included in recipes. When a package is installed
- # from a local file, it must be added to the node using the remote_file or cookbook_file resources.
class GemPackage < Chef::Resource::Package
resource_name :gem_package
+ description "Use the gem_package resource to manage gem packages that are only"\
+ " included in recipes. When a package is installed from a local file,"\
+ " it must be added to the node using the remote_file or cookbook_file"\
+ " resources."
+
# the source can either be a path to a package source like:
# source /var/tmp/mygem-1.2.3.4.gem
# or it can be a url rubygems source like:
diff --git a/lib/chef/resource/git.rb b/lib/chef/resource/git.rb
index ac4f027552..9f1702f715 100644
--- a/lib/chef/resource/git.rb
+++ b/lib/chef/resource/git.rb
@@ -20,10 +20,12 @@ require "chef/resource/scm"
class Chef
class Resource
- # Use the git resource to manage source control resources that exist in a git repository. git version 1.6.5 (or higher)
- # is required to use all of the functionality in the git resource.
class Git < Chef::Resource::Scm
+ description "Use the git resource to manage source control resources that exist"\
+ " in a git repository. git version 1.6.5 (or higher) is required to"\
+ " use all of the functionality in the git resource."
+
def initialize(name, run_context = nil)
super
@additional_remotes = Hash[]
diff --git a/lib/chef/resource/group.rb b/lib/chef/resource/group.rb
index 69a3827a5c..79a234cb54 100644
--- a/lib/chef/resource/group.rb
+++ b/lib/chef/resource/group.rb
@@ -19,13 +19,12 @@
class Chef
class Resource
- # Use the group resource to manage a local group.
class Group < Chef::Resource
-
identity_attr :group_name
-
state_attrs :members
+ description "Use the group resource to manage a local group."
+
allowed_actions :create, :remove, :modify, :manage
default_action :create
diff --git a/lib/chef/resource/homebrew_package.rb b/lib/chef/resource/homebrew_package.rb
index 6174a31079..dee132a1b4 100644
--- a/lib/chef/resource/homebrew_package.rb
+++ b/lib/chef/resource/homebrew_package.rb
@@ -23,13 +23,13 @@ require "chef/resource/package"
class Chef
class Resource
- # Use the homebrew_package resource to manage packages for the macOS platform.
- #
- # @since 12.0
class HomebrewPackage < Chef::Resource::Package
resource_name :homebrew_package
provides :package, os: "darwin"
+ description "Use the homebrew_package resource to manage packages for the macOS platform."
+ introduced "12.0"
+
property :homebrew_user, [ String, Integer ]
end
diff --git a/lib/chef/resource/hostname.rb b/lib/chef/resource/hostname.rb
new file mode 100644
index 0000000000..16986c09a3
--- /dev/null
+++ b/lib/chef/resource/hostname.rb
@@ -0,0 +1,252 @@
+class Chef
+ class Resource
+ # Sets the hostname and updates /etc/hosts on *nix systems
+ # @since 14.0.0
+ class Hostname < Chef::Resource
+ provides :hostname
+ resource_name :hostname
+
+ description "Sets the systems hostname, ensures that reboot will preserve the hostname, and re-runs the ohai plugin so the hostname will be available in subsequent cookbooks."
+ introduced "14.0"
+
+ property :hostname,
+ String,
+ description: "The hostname if different than the resource's name",
+ name_property: true
+
+ property :compile_time,
+ [ TrueClass, FalseClass ],
+ description: "Should the resource run at compile time or not.",
+ default: true
+
+ property :ipaddress,
+ String,
+ description: "The ip address to use when configuring the hosts file",
+ default: lazy { node["ipaddress"] }
+
+ property :aliases,
+ [ Array, nil ],
+ description: "An array of hostname aliases to use when configuring the hosts file",
+ default: nil
+
+ property :windows_reboot,
+ [ TrueClass, FalseClass ],
+ description: "Should Windows nodes be rebooted upon changing the name so it can take effect",
+ default: true
+
+ action_class do
+ def append_replacing_matching_lines(path, regex, string)
+ text = IO.read(path).split("\n")
+ text.reject! { |s| s =~ regex }
+ text += [ string ]
+ file path do
+ content text.join("\n") + "\n"
+ owner "root"
+ group node["root_group"]
+ mode "0644"
+ not_if { IO.read(path).split("\n").include?(string) }
+ end
+ end
+
+ # read in the xml file used by Ec2ConfigService and update the Ec2SetComputerName
+ # setting to disable updating the computer name so we don't revert our change on reboot
+ # @return [String]
+ def updated_ec2_config_xml
+ begin
+ require "rexml/document"
+ config_file = 'C:\Program Files\Amazon\Ec2ConfigService\Settings\config.xml'
+ config = REXML::Document.new(::File.read(config_file))
+ # find an element named State with a sibling element whose value is Ec2SetComputerName
+ REXML::XPath.each(config, "//Plugin/State[../Name/text() = 'Ec2SetComputerName']") do |element|
+ element.text = "Disabled"
+ end
+ rescue
+ return ""
+ end
+ config.to_s
+ end
+ end
+
+ action :set do
+ description "Sets the node's hostname"
+
+ ohai "reload hostname" do
+ plugin "hostname"
+ action :nothing
+ end
+
+ if node["platform_family"] != "windows"
+ # set the hostname via /bin/hostname
+ declare_resource(:execute, "set hostname to #{new_resource.hostname}") do
+ command "/bin/hostname #{new_resource.hostname}"
+ not_if { shell_out!("hostname").stdout.chomp == new_resource.hostname }
+ notifies :reload, "ohai[reload hostname]"
+ end
+
+ # make sure node['fqdn'] resolves via /etc/hosts
+ unless new_resource.ipaddress.nil?
+ newline = "#{new_resource.ipaddress} #{new_resource.hostname}"
+ newline << " #{new_resource.aliases.join(" ")}" if new_resource.aliases && !new_resource.aliases.empty?
+ newline << " #{new_resource.hostname[/[^\.]*/]}"
+ r = append_replacing_matching_lines("/etc/hosts", /^#{new_resource.ipaddress}\s+|\s+#{new_resource.hostname}\s+/, newline)
+ r.atomic_update false if docker?
+ r.notifies :reload, "ohai[reload hostname]"
+ end
+
+ # setup the hostname to perist on a reboot
+ case
+ when ::File.exist?("/usr/sbin/scutil")
+ # darwin
+ declare_resource(:execute, "set HostName via scutil") do
+ command "/usr/sbin/scutil --set HostName #{new_resource.hostname}"
+ not_if { shell_out!("/usr/sbin/scutil --get HostName").stdout.chomp == new_resource.hostname }
+ notifies :reload, "ohai[reload hostname]"
+ end
+ declare_resource(:execute, "set ComputerName via scutil") do
+ command "/usr/sbin/scutil --set ComputerName #{new_resource.hostname}"
+ not_if { shell_out!("/usr/sbin/scutil --get ComputerName").stdout.chomp == new_resource.hostname }
+ notifies :reload, "ohai[reload hostname]"
+ end
+ shortname = new_resource.hostname[/[^\.]*/]
+ declare_resource(:execute, "set LocalHostName via scutil") do
+ command "/usr/sbin/scutil --set LocalHostName #{shortname}"
+ not_if { shell_out!("/usr/sbin/scutil --get LocalHostName").stdout.chomp == shortname }
+ notifies :reload, "ohai[reload hostname]"
+ end
+ when node["os"] == "linux"
+ case
+ when ::File.exist?("/usr/bin/hostnamectl") && !docker?
+ # use hostnamectl whenever we find it on linux (as systemd takes over the world)
+ # this must come before other methods like /etc/hostname and /etc/sysconfig/network
+ declare_resource(:execute, "hostnamectl set-hostname #{new_resource.hostname}") do
+ notifies :reload, "ohai[reload hostname]"
+ not_if { shell_out!("hostnamectl status", { :returns => [0, 1] }).stdout =~ /Static hostname:\s+#{new_resource.hostname}/ }
+ end
+ when ::File.exist?("/etc/hostname")
+ # debian family uses /etc/hostname
+ # arch also uses /etc/hostname
+ # the "platform: iox_xr, platform_family: wrlinux, os: linux" platform also hits this
+ # the "platform: nexus, platform_family: wrlinux, os: linux" platform also hits this
+ # this is also fallback for any linux systemd host in a docker container (where /usr/bin/hostnamectl will fail)
+ declare_resource(:file, "/etc/hostname") do
+ atomic_update false if docker?
+ content "#{new_resource.hostname}\n"
+ owner "root"
+ group node["root_group"]
+ mode "0644"
+ end
+ when ::File.file?("/etc/sysconfig/network")
+ # older non-systemd RHEL/Fedora derived
+ append_replacing_matching_lines("/etc/sysconfig/network", /^HOSTNAME\s*=/, "HOSTNAME=#{new_resource.hostname}")
+ when ::File.exist?("/etc/HOSTNAME")
+ # SuSE/OpenSUSE uses /etc/HOSTNAME
+ declare_resource(:file, "/etc/HOSTNAME") do
+ content "#{new_resource.hostname}\n"
+ owner "root"
+ group node["root_group"]
+ mode "0644"
+ end
+ when ::File.exist?("/etc/conf.d/hostname")
+ # Gentoo
+ declare_resource(:file, "/etc/conf.d/hostname") do
+ content "hostname=\"#{new_resource.hostname}\"\n"
+ owner "root"
+ group node["root_group"]
+ mode "0644"
+ end
+ else
+ # This is a failsafe for all other linux distributions where we set the hostname
+ # via /etc/sysctl.conf on reboot. This may get into a fight with other cookbooks
+ # that manage sysctls on linux.
+ append_replacing_matching_lines("/etc/sysctl.conf", /^\s+kernel\.hostname\s+=/, "kernel.hostname=#{new_resource.hostname}")
+ end
+ when ::File.exist?("/etc/rc.conf")
+ # *BSD systems with /etc/rc.conf + /etc/myname
+ append_replacing_matching_lines("/etc/rc.conf", /^\s+hostname\s+=/, "hostname=#{new_resource.hostname}")
+
+ declare_resource(:file, "/etc/myname") do
+ content "#{new_resource.hostname}\n"
+ owner "root"
+ group node["root_group"]
+ mode "0644"
+ end
+ when ::File.exist?("/etc/nodename")
+ # Solaris <= 5.10 systems prior to svccfg taking over this functionality (must come before svccfg handling)
+ declare_resource(:file, "/etc/nodename") do
+ content "#{new_resource.hostname}\n"
+ owner "root"
+ group node["root_group"]
+ mode "0644"
+ end
+ # Solaris also has /etc/inet/hosts (copypasta alert)
+ unless new_resource.ipaddress.nil?
+ newline = "#{new_resource.ipaddress} #{new_resource.hostname}"
+ newline << " #{new_resource.aliases.join(" ")}" if new_resource.aliases && !new_resource.aliases.empty?
+ newline << " #{new_resource.hostname[/[^\.]*/]}"
+ r = append_replacing_matching_lines("/etc/inet/hosts", /^#{new_resource.ipaddress}\s+|\s+#{new_resource.hostname}\s+/, newline)
+ r.notifies :reload, "ohai[reload hostname]"
+ end
+ when ::File.exist?("/usr/sbin/svccfg")
+ # Solaris >= 5.11 systems using svccfg (must come after /etc/nodename handling)
+ declare_resource(:execute, "svccfg -s system/identity:node setprop config/nodename=\'#{new_resource.hostname}\'") do
+ notifies :run, "execute[svcadm refresh]", :immediately
+ notifies :run, "execute[svcadm restart]", :immediately
+ not_if { shell_out!("svccfg -s system/identity:node listprop config/nodename").stdout.chomp =~ /config\/nodename\s+astring\s+#{new_resource.hostname}/ }
+ end
+ declare_resource(:execute, "svcadm refresh") do
+ command "svcadm refresh system/identity:node"
+ action :nothing
+ end
+ declare_resource(:execute, "svcadm restart") do
+ command "svcadm restart system/identity:node"
+ action :nothing
+ end
+ else
+ raise "Do not know how to set hostname on os #{node["os"]}, platform #{node["platform"]},"\
+ "platform_version #{node["platform_version"]}, platform_family #{node["platform_family"]}"
+ end
+
+ else # windows
+
+ # suppress EC2 config service from setting our hostname
+ if ::File.exist?('C:\Program Files\Amazon\Ec2ConfigService\Settings\config.xml')
+ xml_contents = updated_ec2_config_xml
+ if xml_contents.empty?
+ Chef::Log.warn('Unable to properly parse and update C:\Program Files\Amazon\Ec2ConfigService\Settings\config.xml contents. Skipping file update.')
+ else
+ declare_resource(:file, 'C:\Program Files\Amazon\Ec2ConfigService\Settings\config.xml') do
+ content xml_contents
+ end
+ end
+ end
+
+ # update via netdom
+ declare_resource(:powershell_script, "set hostname") do
+ code <<-EOH
+ $sysInfo = Get-WmiObject -Class Win32_ComputerSystem
+ $sysInfo.Rename("#{new_resource.hostname}")
+ EOH
+ notifies :request_reboot, "reboot[setting hostname]"
+ not_if { Socket.gethostbyname(Socket.gethostname).first == new_resource.hostname }
+ end
+
+ # reboot because $windows
+ declare_resource(:reboot, "setting hostname") do
+ reason "chef setting hostname"
+ action :nothing
+ only_if { new_resource.windows_reboot }
+ end
+ end
+ end
+
+ # this resource forces itself to run at compile_time
+ def after_created
+ if compile_time
+ Array(action).each do |action|
+ run_action(action)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/http_request.rb b/lib/chef/resource/http_request.rb
index 9d8fce9b22..d3b782ea12 100644
--- a/lib/chef/resource/http_request.rb
+++ b/lib/chef/resource/http_request.rb
@@ -22,12 +22,14 @@ require "chef/provider/http_request"
class Chef
class Resource
- # Use the http_request resource to send an HTTP request (GET, PUT, POST, DELETE, HEAD, or OPTIONS) with an arbitrary
- # message. This resource is often useful when custom callbacks are necessary.
class HttpRequest < Chef::Resource
identity_attr :url
+ description "Use the http_request resource to send an HTTP request (GET, PUT,"\
+ " POST, DELETE, HEAD, or OPTIONS) with an arbitrary message. This"\
+ " resource is often useful when custom callbacks are necessary."
+
default_action :get
allowed_actions :get, :patch, :put, :post, :delete, :head, :options
diff --git a/lib/chef/resource/ifconfig.rb b/lib/chef/resource/ifconfig.rb
index e9ef47d95b..579a4eeedb 100644
--- a/lib/chef/resource/ifconfig.rb
+++ b/lib/chef/resource/ifconfig.rb
@@ -21,8 +21,6 @@ require "chef/resource"
class Chef
class Resource
- # use the ifconfig resource to manage interfaces on *nix systems
- #
# @example set a static ip on eth1
# ifconfig '33.33.33.80' do
# device 'eth1'
@@ -30,6 +28,8 @@ class Chef
class Ifconfig < Chef::Resource
resource_name :ifconfig
+ description "Use the ifconfig resource to manage interfaces on *nix systems."
+
state_attrs :inet_addr, :mask
default_action :add
@@ -38,6 +38,7 @@ class Chef
property :target, String, name_property: true
property :hwaddr, String
property :mask, String
+ property :family, String, default: "inet"
property :inet_addr, String
property :bcast, String
property :mtu, String
diff --git a/lib/chef/resource/ips_package.rb b/lib/chef/resource/ips_package.rb
index 296919dc1c..88a9f182d4 100644
--- a/lib/chef/resource/ips_package.rb
+++ b/lib/chef/resource/ips_package.rb
@@ -21,12 +21,13 @@ require "chef/provider/package/ips"
class Chef
class Resource
- # Use the ips_package resource to manage packages (using Image Packaging System (IPS)) on the Solaris 11 platform.
class IpsPackage < ::Chef::Resource::Package
resource_name :ips_package
provides :package, os: "solaris2"
provides :ips_package, os: "solaris2"
+ description "Use the ips_package resource to manage packages (using Image Packaging System (IPS)) on the Solaris 11 platform."
+
allowed_actions :install, :remove, :upgrade
property :accept_license, [ true, false ], default: false, desired_state: false
diff --git a/lib/chef/resource/ksh.rb b/lib/chef/resource/ksh.rb
index 8024f0d6bd..f0bc277d17 100644
--- a/lib/chef/resource/ksh.rb
+++ b/lib/chef/resource/ksh.rb
@@ -20,13 +20,14 @@ require "chef/resource/script"
class Chef
class Resource
- # Use the ksh resource to execute scripts using the Korn shell (ksh) interpreter. This resource may also use any
- # f the actions and properties that are available to the execute resource. Commands that are executed with this
- # resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are
- # run. Use not_if and only_if to guard this resource for idempotence.
- #
- # @since 12.6
class Ksh < Chef::Resource::Script
+ description "Use the ksh resource to execute scripts using the Korn shell (ksh)"\
+ " interpreter. This resource may also use any of the actions and properties"\
+ " that are available to the execute resource. Commands that are executed"\
+ " with this resource are (by their nature) not idempotent, as they are"\
+ " typically unique to the environment in which they are run. Use not_if"\
+ " and only_if to guard this resource for idempotence."
+ introduced "12.6"
def initialize(name, run_context = nil)
super
diff --git a/lib/chef/resource/launchd.rb b/lib/chef/resource/launchd.rb
index 121af1555c..bc1b7d48e8 100644
--- a/lib/chef/resource/launchd.rb
+++ b/lib/chef/resource/launchd.rb
@@ -20,13 +20,13 @@ require "chef/resource"
class Chef
class Resource
- # Use the launchd resource to manage system-wide services (daemons) and per-user services (agents) on the macOS platform.
- #
- # @since 12.8
class Launchd < Chef::Resource
resource_name :launchd
provides :launchd, os: "darwin"
+ description "Use the launchd resource to manage system-wide services (daemons) and per-user services (agents) on the macOS platform."
+ introduced "12.8"
+
default_action :create
allowed_actions :create, :create_if_missing, :delete, :enable, :disable, :restart
diff --git a/lib/chef/resource/macos_userdefaults.rb b/lib/chef/resource/macos_userdefaults.rb
new file mode 100644
index 0000000000..c0066c84b5
--- /dev/null
+++ b/lib/chef/resource/macos_userdefaults.rb
@@ -0,0 +1,126 @@
+#
+# Copyright:: 2011-2018, Joshua Timberman
+# Copyright:: 2018, Chef Software, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ class MacosUserDefaults < Chef::Resource
+ # align with apple's marketing department
+ resource_name :macos_userdefaults
+ provides :mac_os_x_userdefaults
+ provides :macos_userdefaults
+
+ introduced "14.0"
+
+ description "Use the macos_userdefaults resource to manage the macOS user defaults"\
+ " system. The properties to the resource are passed to the defaults command"\
+ " and the parameters follow convention of the macOS command. See the defaults(1)"\
+ " man page for details on how the tool works."
+
+ property :domain,
+ String,
+ description: "The domain the defaults belong to.",
+ required: true
+
+ property :global,
+ [true, false],
+ description: "Whether the domain is global.",
+ default: false
+
+ property :key,
+ String,
+ description: "The preference key."
+
+ property :value,
+ [Integer, Float, String, true, false, Hash, Array],
+ description: "The value of the key.",
+ coerce: proc { |v| coerce_booleans(v) },
+ required: true
+
+ property :type,
+ String,
+ description: "Value type of the preference key.",
+ default: ""
+
+ property :user,
+ String,
+ description: "User for which to set the default."
+
+ property :sudo,
+ [true, false],
+ description: "Set to true if the setting requires privileged access to modify.",
+ default: false,
+ desired_state: false
+
+ property :is_set,
+ [true, false],
+ description: "",
+ default: false,
+ desired_state: false
+
+ # coerce various ways of representing a boolean into either 0 (false) or 1 (true)
+ # which is what the defaults CLI expects. Why? Well defaults itself accepts a few
+ # different formats, but when you do a read command it all comes back as 1 or 0.
+ def coerce_booleans(val)
+ return 1 if [true, "TRUE", "1", "true", "YES", "yes"].include?(val)
+ return 0 if [false, "FALSE", "0", "false", "NO", "no"].include?(val)
+ val
+ end
+
+ load_current_value do |desired|
+ drcmd = "defaults read '#{desired.domain}' "
+ drcmd << "'#{desired.key}' " if desired.key
+ shell_out_opts = {}
+ shell_out_opts[:user] = desired.user unless desired.user.nil?
+ vc = shell_out("#{drcmd} | grep -qx '#{desired.value}'", shell_out_opts)
+ is_set vc.exitstatus == 0 ? true : false
+ end
+
+ action :write do
+ description "Write the setting to the specified domain"
+
+ unless current_value.is_set
+ cmd = ["defaults write"]
+ cmd.unshift("sudo") if new_resource.sudo
+
+ cmd << if new_resource.global
+ "NSGlobalDomain"
+ else
+ "'#{new_resource.domain}'"
+ end
+
+ cmd << "'#{new_resource.key}'" if new_resource.key
+ value = new_resource.value
+ type = new_resource.type.empty? ? value_type(value) : new_resource.type
+ # creates a string of Key1 Value1 Key2 Value2...
+ value = value.map { |k, v| "\"#{k}\" \"#{v}\"" }.join(" ") if type == "dict"
+ if type == "array"
+ value = value.join("' '")
+ value = "'#{value}'"
+ end
+ cmd << "-#{type}" if type
+ cmd << value
+
+ declare_resource(:execute, cmd.join(" ")) do
+ user new_resource.user unless new_resource.user.nil?
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/ohai_hint.rb b/lib/chef/resource/ohai_hint.rb
new file mode 100644
index 0000000000..26b76806d7
--- /dev/null
+++ b/lib/chef/resource/ohai_hint.rb
@@ -0,0 +1,96 @@
+#
+# Copyright:: Copyright 2011-2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class Chef
+ class Resource
+ class OhaiHint < Chef::Resource
+ resource_name :ohai_hint
+ provides :ohai_hint
+
+ description "A resource to pass hint data to Ohai to aid in configuration detection."
+ introduced "14.0"
+
+ property :hint_name,
+ String,
+ description: "The name of hints file if different from the resource name",
+ name_property: true
+
+ property :content,
+ Hash,
+ description: "Values to include in the hint file"
+
+ property :compile_time,
+ [TrueClass, FalseClass],
+ description: "Should the resource execute during the compile time phase",
+ default: true
+
+ action :create do
+ description "Create an Ohai hint file"
+
+ declare_resource(:directory, ::Ohai::Config.ohai.hints_path.first) do
+ action :create
+ recursive true
+ end
+
+ declare_resource(:file, ohai_hint_file_path(new_resource.hint_name)) do
+ action :create
+ content format_content(new_resource.content)
+ end
+ end
+
+ action :delete do
+ description "Delete an Ohai hint file"
+
+ declare_resource(:file, ohai_hint_file_path(new_resource.hint_name)) do
+ action :delete
+ notifies :reload, ohai[reload ohai post hint removal]
+ end
+
+ declare_resource(:ohai, "reload ohai post hint removal") do
+ action :nothing
+ end
+ end
+
+ action_class do
+ # given a hint filename return the platform specific hint file path
+ # @param filename [String] the name of the hint file
+ # @return [String] absolute path to the file
+ def ohai_hint_file_path(filename)
+ path = ::File.join(::Ohai::Config.ohai.hints_path.first, filename)
+ path << ".json" unless path.end_with?(".json")
+ path
+ end
+
+ # format content hash as JSON
+ # @param content [Hash] the content of the hint file
+ # @return [JSON] json representation of the content of an empty string if content was nil
+ def format_content(content)
+ return "" if content.nil? || content.empty?
+ JSON.pretty_generate(content)
+ end
+ end
+
+ # this resource forces itself to run at compile_time
+ def after_created
+ return unless compile_time
+ Array(action).each do |action|
+ run_action(action)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/powershell_package.rb b/lib/chef/resource/powershell_package.rb
index 05c59acf73..829db5f4f8 100644
--- a/lib/chef/resource/powershell_package.rb
+++ b/lib/chef/resource/powershell_package.rb
@@ -41,6 +41,7 @@ class Chef
property :version, [String, Array], coerce: proc { |x| [x].flatten }
+ property :source, [String]
end
end
end
diff --git a/lib/chef/resource/rhsm_errata.rb b/lib/chef/resource/rhsm_errata.rb
new file mode 100644
index 0000000000..56779909f5
--- /dev/null
+++ b/lib/chef/resource/rhsm_errata.rb
@@ -0,0 +1,45 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ class RhsmErrata < Chef::Resource
+ resource_name :rhsm_errata
+
+ description "A resource for installing packages associated with a given Red"\
+ " Hat Subscription Manager Errata ID. This is helpful if packages"\
+ " to mitigate a single vulnerability must be installed on your hosts."
+ introduced "14.0"
+
+ property :errata_id,
+ String,
+ description: "An optional property for specifying the errata ID if not using the resource's name.",
+ name_property: true
+
+ action :install do
+ description "Installs a package for a specific errata ID"
+
+ execute "Install errata packages for #{new_resource.errata_id}" do
+ command "yum update --advisory #{new_resource.errata_id} -y"
+ action :run
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/rhsm_errata_level.rb b/lib/chef/resource/rhsm_errata_level.rb
new file mode 100644
index 0000000000..3aa289ac2e
--- /dev/null
+++ b/lib/chef/resource/rhsm_errata_level.rb
@@ -0,0 +1,53 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ class RhsmErrataLevel < Chef::Resource
+ resource_name :rhsm_errata_level
+
+ description "A resource for installing all packages of a specified errata level"\
+ " from the Red Hat Subscript Manager. For example, you can ensure"\
+ " that all packages associated with errata marked at a 'Critical'"\
+ " security level are installed."
+ introduced "14.0"
+
+ property :errata_level,
+ String,
+ coerce: proc { |x| x.downcase },
+ equal_to: %w{critical moderate important low},
+ description: "The errata level of packages to install.",
+ name_property: true
+
+ action :install do
+ descripton "Install all packages of the specified errata level"
+
+ yum_package "yum-plugin-security" do
+ action :install
+ only_if { node["platform_version"].to_i == 6 }
+ end
+
+ execute "Install any #{new_resource.errata_level} errata" do
+ command "yum update --sec-severity=#{new_resource.errata_level.capitalize} -y"
+ action :run
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/rhsm_register.rb b/lib/chef/resource/rhsm_register.rb
new file mode 100644
index 0000000000..47fe67d1cf
--- /dev/null
+++ b/lib/chef/resource/rhsm_register.rb
@@ -0,0 +1,170 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+require "shellwords"
+
+class Chef
+ class Resource
+ class RhsmRegister < Chef::Resource
+ resource_name :rhsm_register
+
+ description "A resource for registering a node with the Red Hat Subscription Manager"\
+ " or a local Red Hat Satellite server."
+ introduced "14.0"
+
+ property :activation_key,
+ [String, Array],
+ coerce: proc { |x| Array(x) },
+ description: "A String or array of the activation keys to use when registering. You must also specify the organization property if using activation_key."
+
+ property :satellite_host,
+ String,
+ description: "The FQDN of the Satellite host to register with. If not specified, the host will be registered with Red Hat's public RHSM service."
+
+ property :organization,
+ String,
+ description: "The organization to use when registering, required when using an activation key"
+
+ property :environment,
+ String,
+ description: "The environment to use when registering, required when using username and password"
+
+ property :username,
+ String,
+ description: "The username to use when registering. Not applicable if using an activation key. If specified, password and environment are also required."
+
+ property :password,
+ String,
+ description: "The password to use when registering. Not applicable if using an activation key. If specified, username and environment are also required."
+
+ property :auto_attach,
+ [TrueClass, FalseClass],
+ description: "If true, RHSM will attempt to automatically attach the host to applicable subscriptions. It is generally better to use an activation key with the subscriptions pre-defined.",
+ default: false
+
+ property :install_katello_agent,
+ [TrueClass, FalseClass],
+ description: "If true, the 'katello-agent' RPM will be installed.",
+ default: true
+
+ property :force,
+ [TrueClass, FalseClass],
+ description: "If true, the system will be registered even if it is already registered. Normally, any register operations will fail if the machine is has already registered.",
+ default: false
+
+ action :register do
+ description "Register the node with RHSM"
+
+ package "subscription-manager"
+
+ unless new_resource.satellite_host.nil? || registered_with_rhsm?
+ remote_file "#{Chef::Config[:file_cache_path]}/katello-package.rpm" do
+ source "http://#{new_resource.satellite_host}/pub/katello-ca-consumer-latest.noarch.rpm"
+ action :create
+ notifies :install, "yum_package[katello-ca-consumer-latest]", :immediately
+ not_if { katello_cert_rpm_installed? }
+ end
+
+ yum_package "katello-ca-consumer-latest" do
+ options "--nogpgcheck"
+ source "#{Chef::Config[:file_cache_path]}/katello-package.rpm"
+ action :nothing
+ end
+
+ file "#{Chef::Config[:file_cache_path]}/katello-package.rpm" do
+ action :delete
+ end
+ end
+
+ execute "Register to RHSM" do
+ sensitive new_resource.sensitive
+ command register_command
+ action :run
+ not_if { registered_with_rhsm? }
+ end
+
+ yum_package "katello-agent" do
+ action :install
+ only_if { new_resource.install_katello_agent && !new_resource.satellite_host.nil? }
+ end
+ end
+
+ action :unregister do
+ description "Unregister the node from RHSM"
+
+ execute "Unregister from RHSM" do
+ command "subscription-manager unregister"
+ action :run
+ only_if { registered_with_rhsm? }
+ notifies :run, "execute[Clean RHSM Config]", :immediately
+ end
+
+ execute "Clean RHSM Config" do
+ command "subscription-manager clean"
+ action :nothing
+ end
+ end
+
+ action_class do
+ def registered_with_rhsm?
+ cmd = Mixlib::ShellOut.new("subscription-manager status", env: { LANG: "en_US" })
+ cmd.run_command
+ !cmd.stdout.match(/Overall Status: Unknown/)
+ end
+
+ def katello_cert_rpm_installed?
+ cmd = Mixlib::ShellOut.new("rpm -qa | grep katello-ca-consumer")
+ cmd.run_command
+ !cmd.stdout.match(/katello-ca-consumer/).nil?
+ end
+
+ def register_command
+ command = %w{subscription-manager register}
+
+ unless new_resource.activation_key.empty?
+ raise "Unable to register - you must specify organization when using activation keys" if new_resource.organization.nil?
+
+ command << new_resource.activation_key.map { |key| "--activationkey=#{Shellwords.shellescape(key)}" }
+ command << "--org=#{Shellwords.shellescape(new_resource.organization)}"
+ command << "--force" if new_resource.force
+
+ return command.join(" ")
+ end
+
+ if new_resource.username && new_resource.password
+ raise "Unable to register - you must specify environment when using username/password" if new_resource.environment.nil? && using_satellite_host?
+
+ command << "--username=#{Shellwords.shellescape(new_resource.username)}"
+ command << "--password=#{Shellwords.shellescape(new_resource.password)}"
+ command << "--environment=#{Shellwords.shellescape(new_resource.environment)}" if using_satellite_host?
+ command << "--auto-attach" if new_resource.auto_attach
+ command << "--force" if new_resource.force
+
+ return command.join(" ")
+ end
+
+ raise "Unable to create register command - you must specify activation_key or username/password"
+ end
+
+ def using_satellite_host?
+ !new_resource.satellite_host.nil?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/rhsm_repo.rb b/lib/chef/resource/rhsm_repo.rb
new file mode 100644
index 0000000000..aef4dd43d6
--- /dev/null
+++ b/lib/chef/resource/rhsm_repo.rb
@@ -0,0 +1,63 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ class RhsmRepo < Chef::Resource
+ resource_name :rhsm_repo
+
+ description "A resource for enabling and disabling Red Hat Subscription Manager"\
+ " repositories that are made available via attached subscriptions."
+ introduced "14.0"
+
+ property :repo_name,
+ String,
+ description: "An optional property for specifying the repository name if not using the resource's name.",
+ name_property: true
+
+ action :enable do
+ description "Enable a RHSM repository"
+
+ execute "Enable repository #{repo_name}" do
+ command "subscription-manager repos --enable=#{repo_name}"
+ action :run
+ not_if { repo_enabled?(repo_name) }
+ end
+ end
+
+ action :disable do
+ description "Disable a RHSM repository"
+
+ execute "Enable repository #{repo_name}" do
+ command "subscription-manager repos --disable=#{repo_name}"
+ action :run
+ only_if { repo_enabled?(repo_name) }
+ end
+ end
+
+ action_class do
+ def repo_enabled?(repo)
+ cmd = Mixlib::ShellOut.new("subscription-manager repos --list-enabled", env: { LANG: "en_US" })
+ cmd.run_command
+ !cmd.stdout.match(/Repo ID:\s+#{repo}$/).nil?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/rhsm_subscription.rb b/lib/chef/resource/rhsm_subscription.rb
new file mode 100644
index 0000000000..41dd398cd5
--- /dev/null
+++ b/lib/chef/resource/rhsm_subscription.rb
@@ -0,0 +1,96 @@
+#
+# Copyright:: 2015-2018 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ class RhsmSubscription < Chef::Resource
+ resource_name :rhsm_subscription
+
+ description "A resource for adding additional Redhat Subscription Manager subscriptions"\
+ " to your host. This can be used when a host's activation_key"\
+ " does not attach all necessary subscriptions to your host."
+ introduced "14.0"
+
+ property :pool_id,
+ String,
+ description: "An optional property for specifying the Pool ID if not using the resource's name.",
+ name_property: true
+
+ action :attach do
+ description "Attach the node to a subscription pool"
+
+ execute "Attach subscription pool #{new_resource.pool_id}" do
+ command "subscription-manager attach --pool=#{new_resource.pool_id}"
+ action :run
+ not_if { subscription_attached?(new_resource.pool_id) }
+ end
+ end
+
+ action :remove do
+ description "Remove the node from a subscription pool"
+
+ execute "Remove subscription pool #{new_resource.pool_id}" do
+ command "subscription-manager remove --serial=#{pool_serial(new_resource.pool_id)}"
+ action :run
+ only_if { subscription_attached?(new_resource.pool_id) }
+ end
+ end
+
+ action_class do
+ def subscription_attached?(subscription)
+ cmd = Mixlib::ShellOut.new("subscription-manager list --consumed | grep #{subscription}", env: { LANG: "en_US" })
+ cmd.run_command
+ !cmd.stdout.match(/Pool ID:\s+#{subscription}$/).nil?
+ end
+
+ def serials_by_pool
+ serials = {}
+ pool = nil
+ serial = nil
+
+ cmd = Mixlib::ShellOut.new("subscription-manager list --consumed", env: { LANG: "en_US" })
+ cmd.run_command
+ cmd.stdout.lines.each do |line|
+ line.strip!
+ key, value = line.split(/:\s+/, 2)
+ next unless ["Pool ID", "Serial"].include?(key)
+
+ if key == "Pool ID"
+ pool = value
+ elsif key == "Serial"
+ serial = value
+ end
+
+ next unless pool && serial
+
+ serials[pool] = serial
+ pool = nil
+ serial = nil
+ end
+
+ serials
+ end
+
+ def pool_serial(pool_id)
+ serials_by_pool[pool_id]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index b580a01c29..c10bf98b2f 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -41,6 +41,7 @@ require "chef/resource/gem_package"
require "chef/resource/git"
require "chef/resource/group"
require "chef/resource/http_request"
+require "chef/resource/hostname"
require "chef/resource/homebrew_package"
require "chef/resource/ifconfig"
require "chef/resource/ksh"
@@ -48,9 +49,11 @@ require "chef/resource/launchd"
require "chef/resource/link"
require "chef/resource/log"
require "chef/resource/macports_package"
+require "chef/resource/macos_userdefaults"
require "chef/resource/mdadm"
require "chef/resource/mount"
require "chef/resource/ohai"
+require "chef/resource/ohai_hint"
require "chef/resource/openbsd_package"
require "chef/resource/openssl_dhparam"
require "chef/resource/openssl_rsa_private_key"
@@ -67,6 +70,11 @@ require "chef/resource/reboot"
require "chef/resource/registry_key"
require "chef/resource/remote_directory"
require "chef/resource/remote_file"
+require "chef/resource/rhsm_errata_level"
+require "chef/resource/rhsm_errata"
+require "chef/resource/rhsm_register"
+require "chef/resource/rhsm_repo"
+require "chef/resource/rhsm_subscription"
require "chef/resource/rpm_package"
require "chef/resource/solaris_package"
require "chef/resource/route"
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index 7aaaf7602a..8d8e5151c5 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -23,7 +23,7 @@ require "chef/version_string"
class Chef
CHEF_ROOT = File.expand_path("../..", __FILE__)
- VERSION = Chef::VersionString.new("14.0.60")
+ VERSION = Chef::VersionString.new("14.0.71")
end
#
diff --git a/omnibus_overrides.rb b/omnibus_overrides.rb
index 8da7dc9940..e40a322775 100644
--- a/omnibus_overrides.rb
+++ b/omnibus_overrides.rb
@@ -8,7 +8,7 @@ override "libffi", version: "3.2.1"
override "libiconv", version: "1.15"
override "liblzma", version: "5.2.3"
override "libtool", version: "2.4.2"
-override "libxml2", version: "2.9.5"
+override "libxml2", version: "2.9.7"
override "libxslt", version: "1.1.30"
override "libyaml", version: "0.1.7"
override "makedepend", version: "1.0.5"
diff --git a/spec/unit/knife/configure_spec.rb b/spec/unit/knife/configure_spec.rb
index f1d3bd0745..27bb0d9a3f 100644
--- a/spec/unit/knife/configure_spec.rb
+++ b/spec/unit/knife/configure_spec.rb
@@ -26,8 +26,7 @@ describe Chef::Knife::Configure do
let(:ohai) do
o = {}
- allow(o).to receive(:require_plugin)
- allow(o).to receive(:load_plugins)
+ allow(o).to receive(:all_plugins).with(%w{ os hostname fqdn })
o[:fqdn] = fqdn
o
end
diff --git a/spec/unit/provider/package/powershell_spec.rb b/spec/unit/provider/package/powershell_spec.rb
index 4e86b0fe83..9bebfa9194 100644
--- a/spec/unit/provider/package/powershell_spec.rb
+++ b/spec/unit/provider/package/powershell_spec.rb
@@ -22,6 +22,7 @@ require "chef/mixin/powershell_out"
describe Chef::Provider::Package::Powershell do
include Chef::Mixin::PowershellOut
let(:timeout) { 900 }
+ let(:source) { nil }
let(:new_resource) { Chef::Resource::PowershellPackage.new("windows_test_pkg") }
@@ -92,6 +93,20 @@ describe Chef::Provider::Package::Powershell do
double("powershell_out", :stdout => "5")
end
+ let(:generated_command) { "( Get-Package posh-git -Force -ForceBootstrap ).Version" }
+ let(:generated_get_cmdlet) { "( Get-Package xNetworking -Force -ForceBootstrap ).Version" }
+ let(:generated_get_cmdlet_with_version) { "( Get-Package xNetworking -Force -ForceBootstrap -RequiredVersion 1.0.0.0 ).Version" }
+ let(:generated_find_cmdlet) { "( Find-Package xNetworking -Force -ForceBootstrap ).Version" }
+ let(:generated_find_cmdlet_with_version) { "( Find-Package xNetworking -Force -ForceBootstrap -RequiredVersion 1.0.0.0 ).Version" }
+ let(:generated_find_cmdlet_with_source) { "( Find-Package xNetworking -Force -ForceBootstrap -Source MyGallery ).Version" }
+ let(:generated_find_cmdlet_with_source_and_version) { "( Find-Package xNetworking -Force -ForceBootstrap -RequiredVersion 1.0.0.0 -Source MyGallery ).Version" }
+ let(:generated_install_cmdlet) { "( Install-Package xNetworking -Force -ForceBootstrap ).Version" }
+ let(:generated_install_cmdlet_with_version) { "( Install-Package xNetworking -Force -ForceBootstrap -RequiredVersion 1.0.0.0 ).Version" }
+ let(:generated_install_cmdlet_with_source) { "( Install-Package xNetworking -Force -ForceBootstrap -Source MyGallery ).Version" }
+ let(:generated_install_cmdlet_with_source_and_version) { "( Install-Package xNetworking -Force -ForceBootstrap -RequiredVersion 1.0.0.0 -Source MyGallery ).Version" }
+ let(:generated_uninstall_cmdlet) { "( Uninstall-Package xNetworking -Force -ForceBootstrap ).Version" }
+ let(:generated_uninstall_cmdlet_with_version) { "( Uninstall-Package xNetworking -Force -ForceBootstrap -RequiredVersion 1.0.0.0 ).Version" }
+
describe "#initialize" do
it "should return the correct class" do
expect(provider).to be_kind_of(Chef::Provider::Package::Powershell)
@@ -101,67 +116,75 @@ describe Chef::Provider::Package::Powershell do
describe "#candidate_version" do
it "should set the candidate_version to the latest version when not pinning" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
new_resource.package_name(["xNetworking"])
new_resource.version(nil)
expect(provider.candidate_version).to eql(["2.12.0.0"])
end
+ it "should use the candidate_version from the correct source" do
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap -Source MyGallery ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ new_resource.package_name(["xNetworking"])
+ new_resource.version(nil)
+ new_resource.source("MyGallery")
+ expect(provider.candidate_version).to eql(["2.12.0.0"])
+ end
+
it "should set the candidate_version to the latest version when not pinning and package name is space seperated" do
- allow(provider).to receive(:powershell_out).with("(Find-Package '7-Zip 16.02 (x64)' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_7zip_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package '7-Zip 16.02 (x64)' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_7zip_available)
new_resource.package_name(["7-Zip 16.02 (x64)"])
new_resource.version(nil)
expect(provider.candidate_version).to eql(["16.02"])
end
it "should set the candidate_version to pinned version if available" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.0.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available_2_0_0_0)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.0.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available_2_0_0_0)
new_resource.package_name(["xCertificate"])
new_resource.version(["2.0.0.0"])
expect(provider.candidate_version).to eql(["2.0.0.0"])
end
it "should set the candidate_version to nil if there is no candidate" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
new_resource.package_name(["xCertificate"])
expect(provider.candidate_version).to eql([nil])
end
it "should set the candidate_version correctly when there are two packages to install" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version(nil)
expect(provider.candidate_version).to eql(["2.1.0.0", "2.12.0.0"])
end
it "should set the candidate_version correctly when only the first is installable" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version(nil)
expect(provider.candidate_version).to eql(["2.1.0.0", nil])
end
it "should set the candidate_version correctly when only the last is installable" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version(nil)
expect(provider.candidate_version).to eql([nil, "2.12.0.0"])
end
it "should set the candidate_version correctly when neither are is installable and version is passed as nil array" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
new_resource.package_name(%w{xNetworking xCertificate})
new_resource.version([nil, nil])
expect(provider.candidate_version).to eql([nil, nil])
end
it "should set the candidate_version correctly when neither are is installable and version is not passed" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
new_resource.package_name(%w{xNetworking xCertificate})
new_resource.version(nil)
expect(provider.candidate_version).to eql([nil, nil])
@@ -169,15 +192,114 @@ describe Chef::Provider::Package::Powershell do
end
+ describe "#build_powershell_command" do
+ it "can build a valid command from a single string" do
+ expect(provider.build_powershell_command("Get-Package posh-git")).to eql(generated_command)
+ end
+
+ it "can build a valid command from an array" do
+ expect(provider.build_powershell_command(["Get-Package", "posh-git"])).to eql(generated_command)
+ end
+
+ context "when source is nil" do
+ it "build get commands correctly" do
+ expect(provider.build_powershell_command("Get-Package xNetworking")).to eql(generated_get_cmdlet)
+ end
+
+ it "build get commands correctly when a version is passed" do
+ expect(provider.build_powershell_command("Get-Package xNetworking", "1.0.0.0")).to eql(generated_get_cmdlet_with_version)
+ end
+
+ it "builds find commands correctly" do
+ expect(provider.build_powershell_command("Find-Package xNetworking")).to eql(generated_find_cmdlet)
+ end
+
+ it "builds find commands correctly when a version is passed" do
+ expect(provider.build_powershell_command("Find-Package xNetworking", "1.0.0.0")).to eql(generated_find_cmdlet_with_version)
+ end
+
+ it "build install commands correctly" do
+ expect(provider.build_powershell_command("Install-Package xNetworking")).to eql(generated_install_cmdlet)
+ end
+
+ it "build install commands correctly when a version is passed" do
+ expect(provider.build_powershell_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_version)
+ end
+
+ it "build install commands correctly" do
+ expect(provider.build_powershell_command("Uninstall-Package xNetworking")).to eql(generated_uninstall_cmdlet)
+ end
+
+ it "build install commands correctly when a version is passed" do
+ expect(provider.build_powershell_command("Uninstall-Package xNetworking", "1.0.0.0")).to eql(generated_uninstall_cmdlet_with_version)
+ end
+ end
+
+ context "when source is set" do
+ it "build get commands correctly" do
+ new_resource.source("MyGallery")
+ expect(provider.build_powershell_command("Get-Package xNetworking")).to eql(generated_get_cmdlet)
+ end
+
+ it "build get commands correctly when a version is passed" do
+ new_resource.source("MyGallery")
+ expect(provider.build_powershell_command("Get-Package xNetworking", "1.0.0.0")).to eql(generated_get_cmdlet_with_version)
+ end
+
+ it "builds find commands correctly" do
+ new_resource.source("MyGallery")
+ expect(provider.build_powershell_command("Find-Package xNetworking")).to eql(generated_find_cmdlet_with_source)
+ end
+
+ it "builds find commands correctly when a version is passed" do
+ new_resource.source("MyGallery")
+ expect(provider.build_powershell_command("Find-Package xNetworking", "1.0.0.0")).to eql(generated_find_cmdlet_with_source_and_version)
+ end
+
+ it "build install commands correctly" do
+ new_resource.source("MyGallery")
+ expect(provider.build_powershell_command("Install-Package xNetworking")).to eql(generated_install_cmdlet_with_source)
+ end
+
+ it "build install commands correctly when a version is passed" do
+ new_resource.source("MyGallery")
+ expect(provider.build_powershell_command("Install-Package xNetworking", "1.0.0.0")).to eql(generated_install_cmdlet_with_source_and_version)
+ end
+
+ it "build install commands correctly" do
+ new_resource.source("MyGallery")
+ expect(provider.build_powershell_command("Uninstall-Package xNetworking")).to eql(generated_uninstall_cmdlet)
+ end
+
+ it "build install commands correctly when a version is passed" do
+ new_resource.source("MyGallery")
+ expect(provider.build_powershell_command("Uninstall-Package xNetworking", "1.0.0.0")).to eql(generated_uninstall_cmdlet_with_version)
+ end
+ end
+ end
+
describe "#action_install" do
it "should install a single package" do
provider.load_current_resource
new_resource.package_name(["xCertificate"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout })
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "should install a single package from a custom source" do
+ provider.load_current_resource
+ new_resource.package_name(["xCertificate"])
+ new_resource.version(nil)
+ new_resource.source("MyGallery")
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap -Source MyGallery ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
- expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 -Source MyGallery ).Version", { :timeout => new_resource.timeout })
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -186,10 +308,10 @@ describe Chef::Provider::Package::Powershell do
provider.load_current_resource
new_resource.package_name(["7-Zip 16.02 (x64)"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package '7-Zip 16.02 (x64)' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_7zip_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name '7-Zip 16.02 (x64)' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_7zip_not_installed)
+ allow(provider).to receive(:powershell_out).with("( Find-Package '7-Zip 16.02 (x64)' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_7zip_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package '7-Zip 16.02 (x64)' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_7zip_not_installed)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
- expect(provider).to receive(:powershell_out).with("Install-Package '7-Zip 16.02 (x64)' -Force -ForceBootstrap -RequiredVersion 16.02", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package '7-Zip 16.02 (x64)' -Force -ForceBootstrap -RequiredVersion 16.02 ).Version", { :timeout => new_resource.timeout })
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -201,10 +323,10 @@ describe Chef::Provider::Package::Powershell do
provider.load_current_resource
new_resource.package_name(["xCertificate"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
- expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout })
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -213,8 +335,8 @@ describe Chef::Provider::Package::Powershell do
it "should not install packages that are up-to-date" do
new_resource.package_name(["xCertificate"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
provider.load_current_resource
expect(provider).not_to receive(:install_package)
@@ -225,8 +347,8 @@ describe Chef::Provider::Package::Powershell do
it "should not install packages that are up-to-date" do
new_resource.package_name(["xNetworking"])
new_resource.version(["2.11.0.0"])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available_2_11_0_0)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.11.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.11.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available_2_11_0_0)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
provider.load_current_resource
expect(provider).not_to receive(:install_package)
@@ -239,13 +361,13 @@ describe Chef::Provider::Package::Powershell do
# new_version.resource[0]
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version([nil, "2.11.0.0"])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available_2_11_0_0)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.11.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available_2_11_0_0)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.11.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
- expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
- expect(provider).to receive(:powershell_out).with("Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.11.0.0", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.11.0.0 ).Version", { :timeout => new_resource.timeout })
provider.load_current_resource
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
@@ -254,13 +376,13 @@ describe Chef::Provider::Package::Powershell do
it "should split up commands when given two packages, one with a version pin" do
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version(["2.1.0.0", nil])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
- expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
- expect(provider).to receive(:powershell_out).with("Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.12.0.0", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.12.0.0 ).Version", { :timeout => new_resource.timeout })
provider.load_current_resource
provider.run_action(:install)
@@ -270,13 +392,29 @@ describe Chef::Provider::Package::Powershell do
it "should do multipackage installs when given two packages without constraints" do
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.12.0.0 ).Version", { :timeout => new_resource.timeout })
+ provider.load_current_resource
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "should do multipackage installs from a custom source when given two packages without constraints" do
+ new_resource.package_name(%w{xCertificate xNetworking})
+ new_resource.version(nil)
+ new_resource.source("MyGallery")
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap -Source MyGallery ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap -Source MyGallery ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
- expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
- expect(provider).to receive(:powershell_out).with("Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.12.0.0", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 -Source MyGallery ).Version", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.12.0.0 -Source MyGallery ).Version", { :timeout => new_resource.timeout })
provider.load_current_resource
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
@@ -288,21 +426,34 @@ describe Chef::Provider::Package::Powershell do
provider.load_current_resource
new_resource.package_name(["xCertificate"])
new_resource.version(["2.1.0.0"])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
expect(provider).not_to receive(:remove_package)
provider.run_action(:remove)
expect(new_resource).not_to be_updated_by_last_action
end
+ it "does not pass the source parameter to get or uninstall cmdlets" do
+ new_resource.package_name(["xCertificate"])
+ new_resource.version(["2.1.0.0"])
+ new_resource.source("MyGallery")
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 -Source MyGallery).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ provider.load_current_resource
+ expect(provider).to receive(:powershell_out).with("( Uninstall-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout })
+ provider.run_action(:remove)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
it "does nothing when all the packages are already removed" do
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xNetworking' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
provider.load_current_resource
expect(provider).not_to receive(:remove_package)
@@ -313,11 +464,11 @@ describe Chef::Provider::Package::Powershell do
it "removes a package when version is specified" do
new_resource.package_name(["xCertificate"])
new_resource.version(["2.1.0.0"])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
provider.load_current_resource
- expect(provider).to receive(:powershell_out).with("Uninstall-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("( Uninstall-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0 ).Version", { :timeout => new_resource.timeout })
provider.run_action(:remove)
expect(new_resource).to be_updated_by_last_action
end
@@ -325,11 +476,11 @@ describe Chef::Provider::Package::Powershell do
it "removes a package when version is not specified" do
new_resource.package_name(["xCertificate"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
- allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Find-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("( Get-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
provider.load_current_resource
- expect(provider).to receive(:powershell_out).with("(Uninstall-Package 'xCertificate' -Force -ForceBootstrap).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ expect(provider).to receive(:powershell_out).with("( Uninstall-Package 'xCertificate' -Force -ForceBootstrap ).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
provider.run_action(:remove)
expect(new_resource).to be_updated_by_last_action
end
diff --git a/spec/unit/resource/hostname_spec.rb b/spec/unit/resource/hostname_spec.rb
new file mode 100644
index 0000000000..33f944dbc9
--- /dev/null
+++ b/spec/unit/resource/hostname_spec.rb
@@ -0,0 +1,43 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::Hostname do
+
+ let(:resource) { Chef::Resource::Hostname.new("foo") }
+
+ it "has a resource name of :hostname" do
+ expect(resource.resource_name).to eql(:hostname)
+ end
+
+ it "has a default action of set" do
+ expect(resource.action).to eql([:set])
+ end
+
+ it "runs at compile_time by default" do
+ expect(resource.compile_time).to eql(true)
+ end
+
+ it "reboots windows nodes by default" do
+ expect(resource.windows_reboot).to eql(true)
+ end
+
+ it "the hostname property is the name property" do
+ expect(resource.hostname).to eql("foo")
+ end
+end
diff --git a/spec/unit/resource/macos_user_defaults_spec.rb b/spec/unit/resource/macos_user_defaults_spec.rb
new file mode 100644
index 0000000000..6ef82853cc
--- /dev/null
+++ b/spec/unit/resource/macos_user_defaults_spec.rb
@@ -0,0 +1,45 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::MacosUserDefaults do
+
+ let(:resource) { Chef::Resource::MacosUserDefaults.new("foo") }
+
+ it "has a resource name of :macos_userdefaults" do
+ expect(resource.resource_name).to eql(:macos_userdefaults)
+ end
+
+ it "has a default action of install" do
+ expect(resource.action).to eql([:write])
+ end
+
+ [true, "TRUE", "1", "true", "YES", "yes"].each do |val|
+ it "coerces value property from #{val} to 1" do
+ resource.value val
+ expect(resource.value).to eql(1)
+ end
+ end
+
+ [false, "FALSE", "0", "false", "NO", "no"].each do |val|
+ it "coerces value property from #{val} to 0" do
+ resource.value val
+ expect(resource.value).to eql(0)
+ end
+ end
+end
diff --git a/spec/unit/resource/ohai_hint_spec.rb b/spec/unit/resource/ohai_hint_spec.rb
new file mode 100644
index 0000000000..1a4f6637fa
--- /dev/null
+++ b/spec/unit/resource/ohai_hint_spec.rb
@@ -0,0 +1,43 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::OhaiHint do
+
+ let(:resource) { Chef::Resource::OhaiHint.new("foo") }
+
+ it "has a resource name of :ohai_hint" do
+ expect(resource.resource_name).to eql(:ohai_hint)
+ end
+
+ it "has a default action of create" do
+ expect(resource.action).to eql([:create])
+ end
+
+ it "supports the :nothing, :create and :delete actions" do
+ expect(resource.allowed_actions).to include(:nothing, :create, :delete)
+ end
+
+ it "runs at compile_time by default" do
+ expect(resource.compile_time).to eql(true)
+ end
+
+ it "the hint_name property is the name property" do
+ expect(resource.hint_name).to eql("foo")
+ end
+end
diff --git a/spec/unit/resource/powershell_package_spec.rb b/spec/unit/resource/powershell_package_spec.rb
index 701014bd95..a448d58d5a 100644
--- a/spec/unit/resource/powershell_package_spec.rb
+++ b/spec/unit/resource/powershell_package_spec.rb
@@ -63,4 +63,13 @@ describe Chef::Resource::PowershellPackage do
resource.version(["1.2.3", "4.5.6"])
expect(resource.version).to eql(["1.2.3", "4.5.6"])
end
+
+ it "the default source is nil" do
+ expect(resource.source).to eql(nil)
+ end
+
+ it "the source setter accepts strings" do
+ resource.source("MyGallery")
+ expect(resource.source).to eql("MyGallery")
+ end
end
diff --git a/spec/unit/resource/rhsm_errata_level_spec.rb b/spec/unit/resource/rhsm_errata_level_spec.rb
new file mode 100644
index 0000000000..3284107e75
--- /dev/null
+++ b/spec/unit/resource/rhsm_errata_level_spec.rb
@@ -0,0 +1,46 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmErrataLevel do
+
+ let(:resource) { Chef::Resource::RhsmErrataLevel.new("moderate") }
+
+ it "has a resource name of :rhsm_errata_level" do
+ expect(resource.resource_name).to eql(:rhsm_errata_level)
+ end
+
+ it "has a default action of install" do
+ expect(resource.action).to eql([:install])
+ end
+
+ it "the errata_level property is the name property" do
+ expect(resource.errata_level).to eql("moderate")
+ end
+
+ it "coerces the errata_level to be lowercase" do
+ resource.errata_level "Important"
+ expect(resource.errata_level).to eql("important")
+ end
+
+ it "raises an exception if invalid errata_level is passed" do
+ expect do
+ resource.errata_level "FOO"
+ end.to raise_error(Chef::Exceptions::ValidationFailed)
+ end
+end
diff --git a/spec/unit/resource/rhsm_errata_spec.rb b/spec/unit/resource/rhsm_errata_spec.rb
new file mode 100644
index 0000000000..8da7269ca8
--- /dev/null
+++ b/spec/unit/resource/rhsm_errata_spec.rb
@@ -0,0 +1,35 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmErrata do
+
+ let(:resource) { Chef::Resource::RhsmErrata.new("foo") }
+
+ it "has a resource name of :rhsm_errata" do
+ expect(resource.resource_name).to eql(:rhsm_errata)
+ end
+
+ it "has a default action of install" do
+ expect(resource.action).to eql([:install])
+ end
+
+ it "the errata_id property is the name property" do
+ expect(resource.errata_id).to eql("foo")
+ end
+end
diff --git a/spec/unit/resource/rhsm_register_spec.rb b/spec/unit/resource/rhsm_register_spec.rb
new file mode 100644
index 0000000000..2e360b5708
--- /dev/null
+++ b/spec/unit/resource/rhsm_register_spec.rb
@@ -0,0 +1,199 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmRegister do
+
+ let(:resource) { Chef::Resource::RhsmRegister.new("foo") }
+ let(:provider) { resource.provider_for_action(:register) }
+
+ it "has a resource name of :rhsm_register" do
+ expect(resource.resource_name).to eql(:rhsm_register)
+ end
+
+ it "has a default action of register" do
+ expect(resource.action).to eql([:register])
+ end
+
+ it "coerces activation_key to an array" do
+ resource.activation_key "foo"
+ expect(resource.activation_key).to eql(["foo"])
+ end
+
+ describe "#katello_cert_rpm_installed?" do
+ let(:cmd) { double("cmd") }
+
+ before do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ end
+
+ context "when the output contains katello-ca-consumer" do
+ it "returns true" do
+ allow(cmd).to receive(:stdout).and_return("katello-ca-consumer-somehostname-1.0-1")
+ expect(provider.katello_cert_rpm_installed?).to eq(true)
+ end
+ end
+
+ context "when the output does not contain katello-ca-consumer" do
+ it "returns false" do
+ allow(cmd).to receive(:stdout).and_return("katello-agent-but-not-the-ca")
+ expect(provider.katello_cert_rpm_installed?).to eq(false)
+ end
+ end
+ end
+
+ describe "#register_command" do
+ before do
+ allow(provider).to receive(:activation_key).and_return([])
+ allow(provider).to receive(:auto_attach)
+ end
+
+ context "when activation keys exist" do
+ before do
+ allow(resource).to receive(:activation_key).and_return(%w{key1 key2})
+ end
+
+ context "when no org exists" do
+ it "raises an exception" do
+ allow(resource).to receive(:organization).and_return(nil)
+ expect { provider.register_command }.to raise_error(RuntimeError)
+ end
+ end
+
+ context "when an org exists" do
+ it "returns a command containing the keys and org" do
+ allow(resource).to receive(:organization).and_return("myorg")
+
+ expect(provider.register_command).to match("--activationkey=key1 --activationkey=key2 --org=myorg")
+ end
+ end
+
+ context "when auto_attach is true" do
+ it "does not return a command with --auto-attach since it is not supported with activation keys" do
+ allow(resource).to receive(:organization).and_return("myorg")
+ allow(resource).to receive(:auto_attach).and_return(true)
+
+ expect(provider.register_command).not_to match("--auto-attach")
+ end
+ end
+ end
+
+ context "when username and password exist" do
+ before do
+ allow(resource).to receive(:username).and_return("myuser")
+ allow(resource).to receive(:password).and_return("mypass")
+ allow(resource).to receive(:environment)
+ allow(resource).to receive(:using_satellite_host?)
+ allow(resource).to receive(:activation_key).and_return([])
+ end
+
+ context "when auto_attach is true" do
+ it "returns a command containing --auto-attach" do
+ allow(resource).to receive(:auto_attach).and_return(true)
+
+ expect(provider.register_command).to match("--auto-attach")
+ end
+ end
+
+ context "when auto_attach is false" do
+ it "returns a command that does not contain --auto-attach" do
+ allow(resource).to receive(:auto_attach).and_return(false)
+
+ expect(provider.register_command).not_to match("--auto-attach")
+ end
+ end
+
+ context "when auto_attach is nil" do
+ it "returns a command that does not contain --auto-attach" do
+ allow(resource).to receive(:auto_attach).and_return(nil)
+
+ expect(provider.register_command).not_to match("--auto-attach")
+ end
+ end
+
+ context "when environment does not exist" do
+ context "when registering to a satellite server" do
+ it "raises an exception" do
+ allow(provider).to receive(:using_satellite_host?).and_return(true)
+ allow(resource).to receive(:environment).and_return(nil)
+ expect { provider.register_command }.to raise_error(RuntimeError)
+ end
+ end
+
+ context "when registering to RHSM proper" do
+ before do
+ allow(provider).to receive(:using_satellite_host?).and_return(false)
+ allow(resource).to receive(:environment).and_return(nil)
+ end
+
+ it "does not raise an exception" do
+ expect { provider.register_command }.not_to raise_error
+ end
+
+ it "returns a command containing the username and password and no environment" do
+ allow(resource).to receive(:environment).and_return("myenv")
+ expect(provider.register_command).to match("--username=myuser --password=mypass")
+ expect(provider.register_command).not_to match("--environment")
+ end
+ end
+ end
+
+ context "when an environment exists" do
+ it "returns a command containing the username, password, and environment" do
+ allow(provider).to receive(:using_satellite_host?).and_return(true)
+ allow(resource).to receive(:environment).and_return("myenv")
+ expect(provider.register_command).to match("--username=myuser --password=mypass --environment=myenv")
+ end
+ end
+ end
+
+ context "when no activation keys, username, or password exist" do
+ it "raises an exception" do
+ allow(resource).to receive(:activation_key).and_return([])
+ allow(resource).to receive(:username).and_return(nil)
+ allow(resource).to receive(:password).and_return(nil)
+
+ expect { provider.register_command }.to raise_error(RuntimeError)
+ end
+ end
+ end
+
+ describe "#registered_with_rhsm?" do
+ let(:cmd) { double("cmd") }
+
+ before do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ end
+
+ context "when the status is Unknown" do
+ it "returns false" do
+ allow(cmd).to receive(:stdout).and_return("Overall Status: Unknown")
+ expect(provider.registered_with_rhsm?).to eq(false)
+ end
+ end
+
+ context "when the status is anything else" do
+ it "returns true" do
+ allow(cmd).to receive(:stdout).and_return("Overall Status: Insufficient")
+ expect(provider.registered_with_rhsm?).to eq(true)
+ end
+ end
+ end
+end
diff --git a/spec/unit/resource/rhsm_repo_spec.rb b/spec/unit/resource/rhsm_repo_spec.rb
new file mode 100644
index 0000000000..97606a03c8
--- /dev/null
+++ b/spec/unit/resource/rhsm_repo_spec.rb
@@ -0,0 +1,59 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmRepo do
+
+ let(:resource) { Chef::Resource::RhsmRepo.new("foo") }
+ let(:provider) { resource.provider_for_action(:enable) }
+
+ it "has a resource name of :rhsm_repo" do
+ expect(resource.resource_name).to eql(:rhsm_repo)
+ end
+
+ it "has a default action of enable" do
+ expect(resource.action).to eql([:enable])
+ end
+
+ it "the repo_name property is the name property" do
+ expect(resource.repo_name).to eql("foo")
+ end
+
+ describe "#repo_enabled?" do
+ let(:cmd) { double("cmd") }
+ let(:output) { "Repo ID: repo123" }
+
+ before do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ allow(cmd).to receive(:stdout).and_return(output)
+ end
+
+ context "when the repo provided matches the output" do
+ it "returns true" do
+ expect(provider.repo_enabled?("repo123")).to eq(true)
+ end
+ end
+
+ context "when the repo provided does not match the output" do
+ it "returns false" do
+ expect(provider.repo_enabled?("differentrepo")).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/unit/resource/rhsm_subscription_spec.rb b/spec/unit/resource/rhsm_subscription_spec.rb
new file mode 100644
index 0000000000..0160624f39
--- /dev/null
+++ b/spec/unit/resource/rhsm_subscription_spec.rb
@@ -0,0 +1,93 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::RhsmSubscription do
+ let(:resource) { Chef::Resource::RhsmSubscription.new("foo") }
+ let(:provider) { resource.provider_for_action(:attach) }
+
+ it "has a resource name of :rhsm_subscription" do
+ expect(resource.resource_name).to eql(:rhsm_subscription)
+ end
+
+ it "has a default action of attach" do
+ expect(resource.action).to eql([:attach])
+ end
+
+ it "the pool_id property is the name property" do
+ expect(resource.pool_id).to eql("foo")
+ end
+
+ describe "#subscription_attached?" do
+ let(:cmd) { double("cmd") }
+ let(:output) { "Pool ID: pool123" }
+
+ before do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ allow(cmd).to receive(:stdout).and_return(output)
+ end
+
+ context "when the pool provided matches the output" do
+ it "returns true" do
+ expect(provider.subscription_attached?("pool123")).to eq(true)
+ end
+ end
+
+ context "when the pool provided does not match the output" do
+ it "returns false" do
+ expect(provider.subscription_attached?("differentpool")).to eq(false)
+ end
+ end
+ end
+
+ describe "#serials_by_pool" do
+ let(:cmd) { double("cmd") }
+ let(:output) do
+ <<~EOL
+ Key1: value1
+ Pool ID: pool1
+ Serial: serial1
+ Key2: value2
+
+ Key1: value1
+ Pool ID: pool2
+ Serial: serial2
+ Key2: value2
+EOL
+ end
+
+ it "parses the output correctly" do
+ allow(Mixlib::ShellOut).to receive(:new).and_return(cmd)
+ allow(cmd).to receive(:run_command)
+ allow(cmd).to receive(:stdout).and_return(output)
+
+ expect(provider.serials_by_pool["pool1"]).to eq("serial1")
+ expect(provider.serials_by_pool["pool2"]).to eq("serial2")
+ end
+ end
+
+ describe "#pool_serial" do
+ let(:serials) { { "pool1" => "serial1", "pool2" => "serial2" } }
+
+ it "returns the serial for a given pool" do
+ allow(provider).to receive(:serials_by_pool).and_return(serials)
+ expect(provider.pool_serial("pool1")).to eq("serial1")
+ end
+ end
+end