summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusername-is-already-taken2 <digitalgaz@hotmail.com>2018-11-22 11:00:42 +0000
committerusername-is-already-taken2 <digitalgaz@hotmail.com>2018-11-23 07:36:57 +0000
commit25bdedeb788069666c8bf19b18dec14be6d8bf63 (patch)
tree8d5b99a413baf5e80aec17c4a70e4d9c3a9bee80
parent4422560c0f4f6c69775ba9c035f4ac86eb56b8db (diff)
parent5c436ac98fd9a5dd78e243616123650217c90419 (diff)
downloadchef-25bdedeb788069666c8bf19b18dec14be6d8bf63.tar.gz
Merge remote-tracking branch 'origin' into gb/windows_timezone
Signed-off-by: username-is-already-taken2 <digitalgaz@hotmail.com>
-rw-r--r--.github/CODEOWNERS9
-rw-r--r--.github/ISSUE_TEMPLATE/BUG_TEMPLATE.md (renamed from .github/ISSUE_TEMPLATE.md)8
-rw-r--r--.github/ISSUE_TEMPLATE/ENHANCEMENT_REQUEST_TEMPLATE.md17
-rw-r--r--.github/ISSUE_TEMPLATE/RESOURCE_REQUEST.md26
-rw-r--r--.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md13
-rw-r--r--CHANGELOG.md75
-rw-r--r--CODE_OF_CONDUCT.md1
-rw-r--r--Gemfile.lock48
-rw-r--r--RELEASE_NOTES.md605
-rw-r--r--VERSION2
-rw-r--r--appveyor.yml31
-rw-r--r--chef-config/lib/chef-config/config.rb10
-rw-r--r--chef-config/lib/chef-config/version.rb2
-rw-r--r--chef-universal-mingw32.gemspec1
-rw-r--r--chef.gemspec2
-rwxr-xr-xci/verify-chef.sh14
-rw-r--r--lib/chef/application/apply.rb10
-rw-r--r--lib/chef/cookbook/cookbook_version_loader.rb111
-rw-r--r--lib/chef/cookbook_loader.rb159
-rw-r--r--lib/chef/dsl/chef_provisioning.rb57
-rw-r--r--lib/chef/dsl/resources.rb8
-rw-r--r--lib/chef/knife/config_list_profiles.rb2
-rw-r--r--lib/chef/knife/cookbook_create.rb29
-rw-r--r--lib/chef/knife/cookbook_test.rb95
-rw-r--r--lib/chef/knife/list.rb2
-rw-r--r--lib/chef/knife/osc_user_create.rb97
-rw-r--r--lib/chef/knife/osc_user_delete.rb51
-rw-r--r--lib/chef/knife/osc_user_edit.rb58
-rw-r--r--lib/chef/knife/osc_user_list.rb47
-rw-r--r--lib/chef/knife/osc_user_reregister.rb64
-rw-r--r--lib/chef/knife/osc_user_show.rb53
-rw-r--r--lib/chef/knife/raw.rb2
-rw-r--r--lib/chef/knife/role_env_run_list_clear.rb2
-rw-r--r--lib/chef/knife/role_env_run_list_remove.rb2
-rw-r--r--lib/chef/knife/role_env_run_list_replace.rb2
-rw-r--r--lib/chef/knife/role_env_run_list_set.rb2
-rw-r--r--lib/chef/knife/role_run_list_clear.rb2
-rw-r--r--lib/chef/knife/role_run_list_remove.rb2
-rw-r--r--lib/chef/knife/role_run_list_replace.rb2
-rw-r--r--lib/chef/knife/role_run_list_set.rb2
-rw-r--r--lib/chef/knife/show.rb2
-rw-r--r--lib/chef/knife/status.rb13
-rw-r--r--lib/chef/knife/upload.rb2
-rw-r--r--lib/chef/knife/user_create.rb109
-rw-r--r--lib/chef/knife/user_delete.rb54
-rw-r--r--lib/chef/knife/user_edit.rb46
-rw-r--r--lib/chef/knife/user_list.rb2
-rw-r--r--lib/chef/knife/user_reregister.rb47
-rw-r--r--lib/chef/knife/user_show.rb33
-rw-r--r--lib/chef/knife/xargs.rb2
-rw-r--r--lib/chef/node/attribute.rb388
-rw-r--r--lib/chef/node/attribute_collections.rb59
-rw-r--r--lib/chef/node/mixin/immutablize_array.rb1
-rw-r--r--lib/chef/node/mixin/mashy_array.rb68
-rw-r--r--lib/chef/platform/rebooter.rb1
-rw-r--r--lib/chef/policy_builder/dynamic.rb2
-rw-r--r--lib/chef/property.rb26
-rw-r--r--lib/chef/provider/apt_repository.rb2
-rw-r--r--lib/chef/provider/execute.rb2
-rw-r--r--lib/chef/provider/osx_profile.rb2
-rw-r--r--lib/chef/provider/package/apt.rb2
-rw-r--r--lib/chef/provider/package/chocolatey.rb2
-rw-r--r--lib/chef/provider/package/freebsd/pkg.rb114
-rw-r--r--lib/chef/provider/package/freebsd/port.rb6
-rw-r--r--lib/chef/provider/package/openbsd.rb2
-rw-r--r--lib/chef/provider/package/yum.rb2
-rw-r--r--lib/chef/provider/package/yum/version.rb4
-rw-r--r--lib/chef/provider/route.rb2
-rw-r--r--lib/chef/provider/script.rb4
-rw-r--r--lib/chef/provider/windows_task.rb25
-rw-r--r--lib/chef/providers.rb1
-rw-r--r--lib/chef/resource.rb19
-rw-r--r--lib/chef/resource/apt_package.rb2
-rw-r--r--lib/chef/resource/apt_preference.rb5
-rw-r--r--lib/chef/resource/apt_repository.rb4
-rw-r--r--lib/chef/resource/apt_update.rb1
-rw-r--r--lib/chef/resource/build_essential.rb2
-rw-r--r--lib/chef/resource/cab_package.rb2
-rw-r--r--lib/chef/resource/chef_gem.rb2
-rw-r--r--lib/chef/resource/chocolatey_config.rb2
-rw-r--r--lib/chef/resource/chocolatey_source.rb2
-rw-r--r--lib/chef/resource/cookbook_file.rb3
-rw-r--r--lib/chef/resource/cron.rb35
-rw-r--r--lib/chef/resource/cron_access.rb2
-rw-r--r--lib/chef/resource/cron_d.rb18
-rw-r--r--lib/chef/resource/directory.rb2
-rw-r--r--lib/chef/resource/dmg_package.rb100
-rw-r--r--lib/chef/resource/execute.rb8
-rw-r--r--lib/chef/resource/file.rb2
-rw-r--r--lib/chef/resource/freebsd_package.rb20
-rw-r--r--lib/chef/resource/homebrew_cask.rb5
-rw-r--r--lib/chef/resource/homebrew_tap.rb4
-rw-r--r--lib/chef/resource/hostname.rb6
-rw-r--r--lib/chef/resource/kernel_module.rb34
-rw-r--r--lib/chef/resource/link.rb4
-rw-r--r--lib/chef/resource/locale.rb1
-rw-r--r--lib/chef/resource/macos_userdefaults.rb3
-rw-r--r--lib/chef/resource/macosx_service.rb4
-rw-r--r--lib/chef/resource/mdadm.rb5
-rw-r--r--lib/chef/resource/mount.rb6
-rw-r--r--lib/chef/resource/ohai.rb4
-rw-r--r--lib/chef/resource/ohai_hint.rb2
-rw-r--r--lib/chef/resource/openssl_dhparam.rb6
-rw-r--r--lib/chef/resource/openssl_ec_private_key.rb6
-rw-r--r--lib/chef/resource/openssl_ec_public_key.rb6
-rw-r--r--lib/chef/resource/openssl_rsa_private_key.rb8
-rw-r--r--lib/chef/resource/openssl_rsa_public_key.rb6
-rw-r--r--lib/chef/resource/openssl_x509_certificate.rb6
-rw-r--r--lib/chef/resource/openssl_x509_crl.rb6
-rw-r--r--lib/chef/resource/openssl_x509_request.rb6
-rw-r--r--lib/chef/resource/package.rb6
-rw-r--r--lib/chef/resource/powershell_package.rb4
-rw-r--r--lib/chef/resource/remote_directory.rb79
-rw-r--r--lib/chef/resource/rhsm_errata.rb2
-rw-r--r--lib/chef/resource/rhsm_errata_level.rb2
-rw-r--r--lib/chef/resource/rhsm_register.rb14
-rw-r--r--lib/chef/resource/rhsm_repo.rb2
-rw-r--r--lib/chef/resource/rhsm_subscription.rb2
-rw-r--r--lib/chef/resource/route.rb38
-rw-r--r--lib/chef/resource/rpm_package.rb2
-rw-r--r--lib/chef/resource/scm.rb2
-rw-r--r--lib/chef/resource/service.rb201
-rw-r--r--lib/chef/resource/ssh_known_hosts_entry.rb4
-rw-r--r--lib/chef/resource/sudo.rb16
-rw-r--r--lib/chef/resource/swap_file.rb2
-rw-r--r--lib/chef/resource/sysctl.rb4
-rw-r--r--lib/chef/resource/systemd_unit.rb30
-rw-r--r--lib/chef/resource/template.rb14
-rw-r--r--lib/chef/resource/timezone.rb18
-rw-r--r--lib/chef/resource/windows_ad_join.rb4
-rw-r--r--lib/chef/resource/windows_auto_run.rb2
-rw-r--r--lib/chef/resource/windows_certificate.rb269
-rw-r--r--lib/chef/resource/windows_env.rb15
-rw-r--r--lib/chef/resource/windows_feature.rb27
-rw-r--r--lib/chef/resource/windows_feature_dism.rb34
-rw-r--r--lib/chef/resource/windows_feature_powershell.rb14
-rw-r--r--lib/chef/resource/windows_firewall_rule.rb204
-rw-r--r--lib/chef/resource/windows_path.rb4
-rw-r--r--lib/chef/resource/windows_printer.rb4
-rw-r--r--lib/chef/resource/windows_printer_port.rb6
-rw-r--r--lib/chef/resource/windows_service.rb15
-rw-r--r--lib/chef/resource/windows_share.rb320
-rw-r--r--lib/chef/resource/windows_task.rb457
-rw-r--r--lib/chef/resource/windows_workgroup.rb61
-rw-r--r--lib/chef/resource/yum_package.rb3
-rw-r--r--lib/chef/resource/yum_repository.rb22
-rw-r--r--lib/chef/resource/zypper_package.rb8
-rw-r--r--lib/chef/resource/zypper_repository.rb3
-rw-r--r--lib/chef/resource_inspector.rb8
-rw-r--r--lib/chef/resources.rb3
-rw-r--r--lib/chef/run_context/cookbook_compiler.rb4
-rw-r--r--lib/chef/version.rb2
-rw-r--r--omnibus/Gemfile.lock46
-rwxr-xr-xomnibus/package-scripts/angrychef/postrm14
-rwxr-xr-xomnibus/package-scripts/angrychef/preinst12
-rwxr-xr-xomnibus/package-scripts/chef-fips/postrm14
-rwxr-xr-xomnibus/package-scripts/chef-fips/preinst12
-rwxr-xr-xomnibus/package-scripts/chef/postrm14
-rwxr-xr-xomnibus/package-scripts/chef/preinst12
-rw-r--r--spec/functional/resource/windows_task_spec.rb39
-rw-r--r--spec/functional/resource/yum_package_spec.rb21
-rw-r--r--spec/integration/client/client_spec.rb20
-rw-r--r--spec/integration/knife/raw_spec.rb18
-rw-r--r--spec/integration/knife/redirection_spec.rb10
-rw-r--r--spec/support/platform_helpers.rb3
-rw-r--r--spec/support/shared/integration/app_server_support.rb4
-rw-r--r--spec/unit/cookbook/cookbook_version_loader_spec.rb4
-rw-r--r--spec/unit/cookbook_loader_spec.rb5
-rw-r--r--spec/unit/knife/cookbook_create_spec.rb42
-rw-r--r--spec/unit/knife/cookbook_test_spec.rb84
-rw-r--r--spec/unit/knife/osc_user_create_spec.rb93
-rw-r--r--spec/unit/knife/osc_user_delete_spec.rb44
-rw-r--r--spec/unit/knife/osc_user_edit_spec.rb52
-rw-r--r--spec/unit/knife/osc_user_reregister_spec.rb58
-rw-r--r--spec/unit/knife/osc_user_show_spec.rb46
-rw-r--r--spec/unit/knife/user_create_spec.rb30
-rw-r--r--spec/unit/knife/user_delete_spec.rb21
-rw-r--r--spec/unit/knife/user_edit_spec.rb18
-rw-r--r--spec/unit/knife/user_reregister_spec.rb18
-rw-r--r--spec/unit/knife/user_show_spec.rb19
-rw-r--r--spec/unit/node/attribute_spec.rb30
-rw-r--r--spec/unit/node/immutable_collections_spec.rb1
-rw-r--r--spec/unit/node/vivid_mash_spec.rb107
-rw-r--r--spec/unit/policy_builder/dynamic_spec.rb12
-rw-r--r--spec/unit/provider/apt_repository_spec.rb6
-rw-r--r--spec/unit/provider/package/freebsd/pkg_spec.rb274
-rw-r--r--spec/unit/provider/package/freebsd/pkgng_spec.rb1
-rw-r--r--spec/unit/provider/package/freebsd/port_spec.rb16
-rw-r--r--spec/unit/provider/package/rpm_spec.rb25
-rw-r--r--spec/unit/provider/package/zypper_spec.rb36
-rw-r--r--spec/unit/resource/chef_gem_spec.rb3
-rw-r--r--spec/unit/resource/freebsd_package_spec.rb28
-rw-r--r--spec/unit/resource/macosx_service.rb (renamed from spec/unit/knife/osc_user_list_spec.rb)28
-rw-r--r--spec/unit/resource/ohai_spec.rb4
-rw-r--r--spec/unit/resource/remote_directory_spec.rb31
-rw-r--r--spec/unit/resource/route_spec.rb9
-rw-r--r--spec/unit/resource/service_spec.rb159
-rw-r--r--spec/unit/resource/windows_certificate.rb76
-rw-r--r--spec/unit/resource/windows_feature.rb4
-rw-r--r--spec/unit/resource/windows_firewall_rule_spec.rb401
-rw-r--r--spec/unit/resource/windows_service_spec.rb43
-rw-r--r--spec/unit/resource/windows_share.rb39
-rw-r--r--spec/unit/resource/windows_workgroup_spec.rb27
-rw-r--r--spec/unit/run_context/cookbook_compiler_spec.rb6
204 files changed, 3951 insertions, 3228 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index b4eac50d28..8029e13382 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,6 +1,7 @@
# Order is important. The last matching pattern has the most precedence.
-* @chef/client-maintainers
-.expeditor/** @chef/jex-team
-README.md @chef/docs-team
-RELEASE_NOTES.md @chef/docs-team
+* @chef/client-maintainers
+.expeditor/** @chef/jex-team
+README.md @chef/docs-team
+RELEASE_NOTES.md @chef/docs-team
+.github/ISSUE_TEMPLATE/** @chef/docs-team
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/BUG_TEMPLATE.md
index c6f0984993..7d9433c10f 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE/BUG_TEMPLATE.md
@@ -1,4 +1,10 @@
-<!---
+---
+name: 🐛 Bug Report
+about: If something isn't working as expected 🤔.
+
+---
+
+<!---
!!!!!! NOTE: CHEF CLIENT BUGS ONLY !!!!!!
This issue tracker is for the code contained within this repo -- `chef-client`, base `knife` functionality (not
diff --git a/.github/ISSUE_TEMPLATE/ENHANCEMENT_REQUEST_TEMPLATE.md b/.github/ISSUE_TEMPLATE/ENHANCEMENT_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000000..0e06843554
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/ENHANCEMENT_REQUEST_TEMPLATE.md
@@ -0,0 +1,17 @@
+---
+name: 🚀 Enhancement Request
+about: I have a suggestion (and may want to implement it 🙂)!
+
+---
+
+### Describe the Enhancement:
+<!--- What you are trying to achieve that you can't? -->
+
+### Describe the Need:
+<!--- What kind of user do you believe would utilize this enhancement, and how many users might want this functionality -->
+
+### Current Alternative
+<!--- Is there a current alternative that you can utilize to workaround the lack of this enhancement -->
+
+### Can We Help You Implement This?:
+<!--- The best way to ensure your enhancement is built is to help implement the enhancement yourself. If you're interested in helping out we'd love to give you a hand to make this possible. Let us know if there's something you need. -->
diff --git a/.github/ISSUE_TEMPLATE/RESOURCE_REQUEST.md b/.github/ISSUE_TEMPLATE/RESOURCE_REQUEST.md
new file mode 100644
index 0000000000..c94713f0e4
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/RESOURCE_REQUEST.md
@@ -0,0 +1,26 @@
+---
+name: 💪 Resource Request
+about: I have a suggestion for a new resource in Chef (and may want to implement it 🙌)!
+
+---
+
+### Core Chef Resource Checklist
+
+Before suggesting a resource for inclusion please make sure your suggestion meets these criteria for resources built into Chef:
+ - [ ] Automates an operating system component that ships by default on systems such as authentication, raid, disk partitions, firewalls, containers, or virtualization systems.
+ - [ ] Does not attempt automate 3rd party applications such as database, web, or application servers, which are best suited for cookbooks due to their fast moving nature.
+
+### Describe the resource:
+<!--- Tell us about the resource -->
+
+### Why should this be included out of the box?:
+<!--- Why do you believe this is best suited to be included in the chef-client vs. a cookbook? -->
+
+### What operating systems would it run on?
+<!--- Is this a general purpose resource that would run on every operating systems or is it specific to an OS such as Linux, macOS, or Windows? -->
+
+### Current cookbook implementation:
+<!--- Is there currently a cookbook that ships with this resource? If so please let us know. We'll need full permission from the authors and a compatible license in order to move a resource from a cookbook. -->
+
+### Can We Help You Implement This?:
+<!--- The best way to move a resource into Chef is to help move it yourself. If you're interested in helping out we'd love to give you a hand to make this possible. Let us know if there's something you need. -->
diff --git a/.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md b/.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md
new file mode 100644
index 0000000000..f506318876
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md
@@ -0,0 +1,13 @@
+---
+name: 🤗 Support Question
+about: If you have a question 💬, please check out our Slack!
+
+---
+
+We use GitHub issues to track bugs and feature requests. If you need help please post to our Mailing List or join the Chef Community Slack.
+
+ * Chef Community Slack at http://community-slack.chef.io/.
+ * Chef Mailing List https://discourse.chef.io/
+
+
+ Support issues opened here will be closed and redirected to Slack or Discourse.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d2f08e9c4..b95f155d01 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,84 @@
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
-<!-- latest_release 15.0.8 -->
-## [v15.0.8](https://github.com/chef/chef/tree/v15.0.8) (2018-10-27)
+<!-- latest_release 15.0.83 -->
+## [v15.0.83](https://github.com/chef/chef/tree/v15.0.83) (2018-11-20)
#### Merged Pull Requests
-- add GEMFILE_MOD to pin ohai to github master [#7796](https://github.com/chef/chef/pull/7796) ([lamont-granquist](https://github.com/lamont-granquist))
+- need -rf to remove dirs [#7966](https://github.com/chef/chef/pull/7966) ([lamont-granquist](https://github.com/lamont-granquist))
<!-- latest_release -->
<!-- release_rollup -->
### Changes since latest stable release
#### Merged Pull Requests
+- need -rf to remove dirs [#7966](https://github.com/chef/chef/pull/7966) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.83 -->
+- wipe the installer direction before installation [#7964](https://github.com/chef/chef/pull/7964) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.82 -->
+- windows_share: Accounts to be revoked should be provided as an individually quoted string array [#7959](https://github.com/chef/chef/pull/7959) ([stuartpreston](https://github.com/stuartpreston)) <!-- 15.0.81 -->
+- windows_share: Fix idempotency by removing the &quot;everyone&quot; access [#7956](https://github.com/chef/chef/pull/7956) ([tas50](https://github.com/tas50)) <!-- 15.0.80 -->
+- Chef-15: switch default of allow_downgrade to true [#7953](https://github.com/chef/chef/pull/7953) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.79 -->
+- Chef-15: require instead of load libraries [#7954](https://github.com/chef/chef/pull/7954) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.78 -->
+- Allow Integers for all group / owner properties [#7948](https://github.com/chef/chef/pull/7948) ([tas50](https://github.com/tas50)) <!-- 15.0.77 -->
+- Remove unused yum_timeout and yum_lock_timeout configs [#7909](https://github.com/chef/chef/pull/7909) ([tas50](https://github.com/tas50)) <!-- 15.0.76 -->
+- windows_workgroup: Coerce the provided reboot property and add more tests [#7916](https://github.com/chef/chef/pull/7916) ([tas50](https://github.com/tas50)) <!-- 15.0.75 -->
+- Convert service resource to use properties [#7946](https://github.com/chef/chef/pull/7946) ([tas50](https://github.com/tas50)) <!-- 15.0.74 -->
+- Replace several uses of attribute with property in resources [#7943](https://github.com/chef/chef/pull/7943) ([tas50](https://github.com/tas50)) <!-- 15.0.73 -->
+- Fully convert remote_directory to use properties [#7947](https://github.com/chef/chef/pull/7947) ([tas50](https://github.com/tas50)) <!-- 15.0.72 -->
+- windows_certificate: Add testing of the defaults and allowed properties [#7917](https://github.com/chef/chef/pull/7917) ([tas50](https://github.com/tas50)) <!-- 15.0.71 -->
+- Require chef-zero 14.0.11 or later to resolve Rack gem CVEs [#7940](https://github.com/chef/chef/pull/7940) ([tas50](https://github.com/tas50)) <!-- 15.0.70 -->
+- Add additional resource description fields [#7938](https://github.com/chef/chef/pull/7938) ([tas50](https://github.com/tas50)) <!-- 15.0.69 -->
+- Improve resource descriptions for documentation [#7929](https://github.com/chef/chef/pull/7929) ([tas50](https://github.com/tas50)) <!-- 15.0.68 -->
+- windows_feature_dism: support installed deleted features [#7905](https://github.com/chef/chef/pull/7905) ([kapilchouhan99](https://github.com/kapilchouhan99)) <!-- 15.0.67 -->
+- use --no-tty during apt-keys fro gpg - fixes #7913 [#7914](https://github.com/chef/chef/pull/7914) ([EugenMayer](https://github.com/EugenMayer)) <!-- 15.0.66 -->
+- Update Cheffish to 14.0.4 [#7936](https://github.com/chef/chef/pull/7936) ([tas50](https://github.com/tas50)) <!-- 15.0.65 -->
+- Replace usage of win_friendly_path helper in windows_certificate [#7927](https://github.com/chef/chef/pull/7927) ([tas50](https://github.com/tas50)) <!-- 15.0.64 -->
+- Update inspec-core to 3.0.46 [#7924](https://github.com/chef/chef/pull/7924) ([tas50](https://github.com/tas50)) <!-- 15.0.63 -->
+- windows_feature: Move provider logic into the default of the install_method property [#7912](https://github.com/chef/chef/pull/7912) ([tas50](https://github.com/tas50)) <!-- 15.0.61 -->
+- Always run policy_file if a policy_file or policy_group exists [#7910](https://github.com/chef/chef/pull/7910) ([tas50](https://github.com/tas50)) <!-- 15.0.60 -->
+- Update deps to bring in the new ca-certs [#7897](https://github.com/chef/chef/pull/7897) ([tas50](https://github.com/tas50)) <!-- 15.0.59 -->
+- Add nillability to attribute deep merging [#7892](https://github.com/chef/chef/pull/7892) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.58 -->
+- Make sure we define windows_task resource on *nix systems [#7903](https://github.com/chef/chef/pull/7903) ([tas50](https://github.com/tas50)) <!-- 15.0.56 -->
+- windows_ad_join: Switch to UPN format usernames for use with AD cmdlets [#7895](https://github.com/chef/chef/pull/7895) ([stuartpreston](https://github.com/stuartpreston)) <!-- 15.0.55 -->
+- Fix the knife integration spec timeouts [#7896](https://github.com/chef/chef/pull/7896) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.54 -->
+- fix whitespace in node attributes [ci skip] [#7890](https://github.com/chef/chef/pull/7890) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.53 -->
+- add tests for yum version with package_source bug [#7886](https://github.com/chef/chef/pull/7886) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.52 -->
+- Remove Chef provisioning lazy loading [#7866](https://github.com/chef/chef/pull/7866) ([tas50](https://github.com/tas50)) <!-- 15.0.51 -->
+- Update more descriptions and tweak default handling in chef-resource-inspector [#7884](https://github.com/chef/chef/pull/7884) ([tas50](https://github.com/tas50)) <!-- 15.0.50 -->
+- Allow passing multiple ports in windows_firewall [#7879](https://github.com/chef/chef/pull/7879) ([tas50](https://github.com/tas50)) <!-- 15.0.49 -->
+- Add additional descriptions to resource and update others [#7881](https://github.com/chef/chef/pull/7881) ([tas50](https://github.com/tas50)) <!-- 15.0.48 -->
+- resource inspector: don&#39;t convert nil to &quot;nil&quot; in default values [#7880](https://github.com/chef/chef/pull/7880) ([tas50](https://github.com/tas50)) <!-- 15.0.47 -->
+- Defer running initramfs_command until end of run [#7871](https://github.com/chef/chef/pull/7871) ([tomdoherty](https://github.com/tomdoherty)) <!-- 15.0.45 -->
+- Fully remove knife cookbook create command [#7852](https://github.com/chef/chef/pull/7852) ([tas50](https://github.com/tas50)) <!-- 15.0.42 -->
+- Add more validation_messages to properties [#7867](https://github.com/chef/chef/pull/7867) ([tas50](https://github.com/tas50)) <!-- 15.0.41 -->
+- Make knife command banners consistent [#7869](https://github.com/chef/chef/pull/7869) ([tas50](https://github.com/tas50)) <!-- 15.0.40 -->
+- Add windows_firewall_rule [#7842](https://github.com/chef/chef/pull/7842) ([Happycoil](https://github.com/Happycoil)) <!-- 15.0.39 -->
+- Improve resource descriptions for resource documentation automation [#7808](https://github.com/chef/chef/pull/7808) ([tas50](https://github.com/tas50)) <!-- 15.0.38 -->
+- Remove the remaining OSC 11 knife user commands [#7868](https://github.com/chef/chef/pull/7868) ([tas50](https://github.com/tas50)) <!-- 15.0.37 -->
+- Remove knife user support for open source Chef Server &lt; 12 [#7841](https://github.com/chef/chef/pull/7841) ([tas50](https://github.com/tas50)) <!-- 15.0.36 -->
+- Add additional github issue templates [#7859](https://github.com/chef/chef/pull/7859) ([tas50](https://github.com/tas50)) <!-- 15.0.35 -->
+- Chef 15 node attribute array fixes [#7840](https://github.com/chef/chef/pull/7840) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.34 -->
+- Remove the check for nil code property in the script provider [#7855](https://github.com/chef/chef/pull/7855) ([tas50](https://github.com/tas50)) <!-- 15.0.33 -->
+- powershell_package doc update [#7857](https://github.com/chef/chef/pull/7857) ([Happycoil](https://github.com/Happycoil)) <!-- 15.0.32 -->
+- Set http_disable_auth_on_redirect to true [#7856](https://github.com/chef/chef/pull/7856) ([tas50](https://github.com/tas50)) <!-- 15.0.31 -->
+- Bump inspec-core to 3.0.25 [#7853](https://github.com/chef/chef/pull/7853) ([chef-ci](https://github.com/chef-ci)) <!-- 15.0.30 -->
+- Remove knife cookbook test feature [#7323](https://github.com/chef/chef/pull/7323) ([tas50](https://github.com/tas50)) <!-- 15.0.29 -->
+- Added property `description` on windows_task resource [#7777](https://github.com/chef/chef/pull/7777) ([kapilchouhan99](https://github.com/kapilchouhan99)) <!-- 15.0.28 -->
+- Remove the deprecated ohai_name property from the ohai resource [#7787](https://github.com/chef/chef/pull/7787) ([tas50](https://github.com/tas50)) <!-- 15.0.27 -->
+- Remove deprecated knife status --hide-healthy flag [#7791](https://github.com/chef/chef/pull/7791) ([tas50](https://github.com/tas50)) <!-- 15.0.26 -->
+- Update win32-taskscheduler to 2.0.1 [#7843](https://github.com/chef/chef/pull/7843) ([tas50](https://github.com/tas50)) <!-- 15.0.24 -->
+- Handle `interactive_enabled` property in windows_task resource [#7814](https://github.com/chef/chef/pull/7814) ([Nimesh-Msys](https://github.com/Nimesh-Msys)) <!-- 15.0.23 -->
+- Fix chef-apply crash for reboot [#7720](https://github.com/chef/chef/pull/7720) ([dheerajd-msys](https://github.com/dheerajd-msys)) <!-- 15.0.22 -->
+- Remove preview resource from windows_certificate &amp; windows_share [#7818](https://github.com/chef/chef/pull/7818) ([tas50](https://github.com/tas50)) <!-- 15.0.21 -->
+- Bump win32-certstore to 0.1.11 [#7823](https://github.com/chef/chef/pull/7823) ([tas50](https://github.com/tas50)) <!-- 15.0.20 -->
+- More cookbook loader cleanup and documentation [#7820](https://github.com/chef/chef/pull/7820) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.19 -->
+- Fix testing / installing on SLES 15 [#7819](https://github.com/chef/chef/pull/7819) ([tas50](https://github.com/tas50)) <!-- 15.0.18 -->
+- Update win32-certstore to include a license [#7822](https://github.com/chef/chef/pull/7822) ([tas50](https://github.com/tas50)) <!-- 15.0.17 -->
+- Add windows_certificate and windows_share resources [#7731](https://github.com/chef/chef/pull/7731) ([tas50](https://github.com/tas50)) <!-- 15.0.16 -->
+- Remove unused route resource properties [#7240](https://github.com/chef/chef/pull/7240) ([tas50](https://github.com/tas50)) <!-- 15.0.15 -->
+- Fix inspector to properly handle defaults that are symbols [#7813](https://github.com/chef/chef/pull/7813) ([tas50](https://github.com/tas50)) <!-- 15.0.14 -->
+- Refactor Cookbook loader logic now that we don&#39;t support merging [#7794](https://github.com/chef/chef/pull/7794) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.13 -->
+- Remove deprecated support for FreeBSD pkg provider [#7789](https://github.com/chef/chef/pull/7789) ([tas50](https://github.com/tas50)) <!-- 15.0.12 -->
+- Multiple fixes to dmg_package [#7802](https://github.com/chef/chef/pull/7802) ([tas50](https://github.com/tas50)) <!-- 15.0.11 -->
+- Allow passing array to supports in mount again [#7803](https://github.com/chef/chef/pull/7803) ([tas50](https://github.com/tas50)) <!-- 15.0.10 -->
+- Require mixin::shellout where we use it [#7798](https://github.com/chef/chef/pull/7798) ([tas50](https://github.com/tas50)) <!-- 15.0.9 -->
- add GEMFILE_MOD to pin ohai to github master [#7796](https://github.com/chef/chef/pull/7796) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.8 -->
- shell_out auto-timeout still needs to be restricted to only providers [#7793](https://github.com/chef/chef/pull/7793) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.7 -->
- Remove cookbook merging/shadowing from the cookbooker loader [#7792](https://github.com/chef/chef/pull/7792) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 15.0.6 -->
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000..980c1341a4
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1 @@
+Please refer to the Chef Community Code of Conduct at https://www.chef.io/code-of-conduct/
diff --git a/Gemfile.lock b/Gemfile.lock
index 3bb6385a5c..6170c34af3 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -8,10 +8,10 @@ GIT
GIT
remote: https://github.com/chef/ohai.git
- revision: 3759aeff5ff3c999fd99ffef44f6d00ad3fd0135
+ revision: a946ff969ae335b163a1766901ccd960ad6dc4eb
branch: master
specs:
- ohai (15.0.2)
+ ohai (15.0.7)
chef-config (>= 12.8, < 16)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
@@ -27,11 +27,11 @@ GIT
PATH
remote: .
specs:
- chef (15.0.8)
+ chef (15.0.83)
addressable
bundler (>= 1.10)
- chef-config (= 15.0.8)
- chef-zero (>= 13.0)
+ chef-config (= 15.0.83)
+ chef-zero (>= 14.0.11)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
ffi (~> 1.9, >= 1.9.25)
@@ -57,11 +57,11 @@ PATH
specinfra (~> 2.10)
syslog-logger (~> 1.6)
uuidtools (~> 2.1.5)
- chef (15.0.8-universal-mingw32)
+ chef (15.0.83-universal-mingw32)
addressable
bundler (>= 1.10)
- chef-config (= 15.0.8)
- chef-zero (>= 13.0)
+ chef-config (= 15.0.83)
+ chef-zero (>= 14.0.11)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
ffi (~> 1.9, >= 1.9.25)
@@ -89,6 +89,7 @@ PATH
syslog-logger (~> 1.6)
uuidtools (~> 2.1.5)
win32-api (~> 1.5.3)
+ win32-certstore (>= 0.1.8)
win32-dir (~> 0.5.0)
win32-event (~> 0.6.1)
win32-eventlog (= 0.6.3)
@@ -103,7 +104,7 @@ PATH
PATH
remote: chef-config
specs:
- chef-config (15.0.8)
+ chef-config (15.0.83)
addressable
fuzzyurl
mixlib-config (>= 2.2.12, < 3.0)
@@ -124,13 +125,13 @@ GEM
builder (3.2.3)
byebug (10.0.2)
chef-vault (3.4.3)
- chef-zero (14.0.6)
+ chef-zero (14.0.11)
ffi-yajl (~> 2.2)
hashie (>= 2.0, < 4.0)
mixlib-log (~> 2.0)
- rack (~> 2.0)
+ rack (~> 2.0, >= 2.0.6)
uuidtools (~> 2.1)
- cheffish (14.0.1)
+ cheffish (14.0.4)
chef-zero (~> 14.0)
net-ssh
coderay (1.1.2)
@@ -166,7 +167,7 @@ GEM
highline (1.7.10)
htmlentities (4.3.4)
iniparse (1.4.4)
- inspec-core (3.0.12)
+ inspec-core (3.0.46)
addressable (~> 2.4)
faraday (>= 0.9.0)
hashie (~> 3.4)
@@ -185,14 +186,14 @@ GEM
sslshake (~> 1.2)
thor (~> 0.20)
tomlrb (~> 1.2)
- train-core (~> 1.5, >= 1.5.4)
+ train-core (~> 1.5, >= 1.5.6)
ipaddress (0.8.3)
iso8601 (0.12.1)
json (2.1.0)
launchy (2.4.3)
addressable (~> 2.3)
libyajl2 (1.2.0)
- method_source (0.9.0)
+ method_source (0.9.2)
mixlib-archive (0.4.18)
mixlib-log
mixlib-archive (0.4.18-universal-mingw32)
@@ -225,13 +226,13 @@ GEM
octokit (4.13.0)
sawyer (~> 0.8.0, >= 0.5.3)
parallel (1.12.1)
- parser (2.5.1.2)
+ parser (2.5.3.0)
ast (~> 2.4.0)
parslet (1.8.2)
plist (3.4.0)
powerpack (0.1.2)
proxifier (1.0.3)
- pry (0.11.3)
+ pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-byebug (3.6.0)
@@ -240,13 +241,13 @@ GEM
pry-remote (0.1.8)
pry (~> 0.9)
slop (~> 3.0)
- pry-stack_explorer (0.4.9.2)
+ pry-stack_explorer (0.4.9.3)
binding_of_caller (>= 0.7)
pry (>= 0.9.11)
pusher-client (0.6.2)
json
websocket (~> 1.0)
- rack (2.0.5)
+ rack (2.0.6)
rainbow (3.0.0)
rake (12.3.0)
rb-readline (0.5.5)
@@ -306,9 +307,9 @@ GEM
structured_warnings (0.3.0)
syslog-logger (1.6.8)
systemu (2.6.5)
- thor (0.20.0)
+ thor (0.20.3)
tomlrb (1.2.7)
- train-core (1.5.4)
+ train-core (1.5.6)
json (>= 1.8, < 3.0)
mixlib-shellout (~> 2.0)
travis (1.8.9)
@@ -330,6 +331,9 @@ GEM
hashdiff
websocket (1.2.8)
win32-api (1.5.3-universal-mingw32)
+ win32-certstore (0.1.11)
+ ffi
+ mixlib-shellout
win32-dir (0.5.1)
ffi (>= 1.0.0)
win32-event (0.6.3)
@@ -347,7 +351,7 @@ GEM
win32-service (1.0.1)
ffi
ffi-win32-extensions
- win32-taskscheduler (2.0.0)
+ win32-taskscheduler (2.0.1)
ffi
structured_warnings
windows-api (0.4.4)
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 1dce31400b..a4aca19c26 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -4,6 +4,159 @@ This file holds "in progress" release notes for the current release under develo
Chef 15 release notes will be added here as development progresses.
+## Breaking Changes
+
+### Package provider allow_downgrade is now true by default
+
+We reversed the default behavior to `allow_downgrade true` for our package providers. To override this setting to refuse downgrades, use the `allow_downgrade —false` flag. This behavior change will mostly affect users of the rpm and zypper package providers.
+
+```
+package "foo" do
+ version "1.2.3"
+end
+```
+
+That code should now be read as asserting that the package `foo` must be version `1.2.3` after that resource is run.
+
+```
+package "foo" do
+ allow_downgrade false
+ version "1.2.3"
+end
+```
+
+That code is now what is necessary to specify that `foo` must be version `1.2.3` or higher. Note that the yum provider supports syntax like `package "foo > 1.2.3"` which should be used and is preferred over using allow_downgrade.
+
+### Node Attributes deep merge nil values
+
+Writing a nil to a precedence level in the node object now acts like any other value and can be used to override values back to nil.
+
+For example:
+
+```
+chef (15.0.53)> node.default["foo"] = "bar"
+ => "bar"
+chef (15.0.53)> node.override["foo"] = nil
+ => nil
+chef (15.0.53)> node["foo"]
+ => nil
+```
+
+In prior versions of chef-client the nil set in the override level would be completely ignored and the value of `node["foo"]` would have
+been "bar".
+
+### http_disable_auth_on_redirect now enabled
+
+The Chef config ``http_disable_auth_on_redirect`` has been changed from `false` to `true`. In Chef 16 this config option will be removed alltogether and Chef will always disable auth on redirect.
+
+### knife cookbook test removal
+
+The ``knife cookbook test`` command has been removed. This command would often report non-functional cookbook as functional and has been superceded by functionality in other testing tools such as ``cookstyle``, ``foodcritic``, and ``chefspec``.
+
+### ohai resource's ohai_name property removal
+
+The ohai resource contained a non-functional ohai_name property, which has been removed.
+
+### knife status --hide-healthy flag removal
+
+The ``knife status --hide-healthy`` flag has been removed. Users should run ``knife status --hide-by-mins MINS`` instead.
+
+### Cookbook shadowing in Chef Solo Legacy Mode Removed
+
+Previously if a user provided multiple cookbook path's to Chef Solo that contained cookbooks with the same name, Chef would combine these into a single cookbook. This merging of two cookbooks often caused unexpected outcomes and has been removed.
+
+### Removal of unused Route properties
+
+The route resource contained multiple unused properties that have been removed. If you previously set ``networking``, ``networking_ipv6``, ``hostname``, ``domainname``, or ``domain`` they would be ignored. In Chef 15 setting these properties will throw an error.
+
+### FreeBSD pkg provider removal
+
+Support for the FreeBSD ``pkg`` package system in the ``freebsd_package`` resource has been removed. FreeBSD 10 replaced the ``pkg`` system with ``pkg-ng`` system so this only impacts users of EOL FreeBSD releases.
+
+### require_recipe removal
+
+The legacy ``require_recipe`` method in recipes has been removed. This method was replaced with ``include_recipe`` in the Chef 10 era, and a FoodCritic rule has been warning to update cookbooks for multiple years.
+
+### Legacy shell_out methods removed
+
+In Chef 14 many of the more obscure ``shell_out`` methods used in LWRPs and custom resources were combined into the standard ``shell_out`` and ``shell_out!`` methods. The legacy methods were infrequently and Chef 14/Foodcritic both contained deprecation warnings for these methods. The following methods will now throw an error: ``shell_out_compact``, ``shell_out_compact!``, ``shell_out_compact_timeout``, ``shell_out_compact_timeout!``, ``shell_out_with_systems_locale``, ``shell_out_with_systems_locale!``,
+
+### knife bootstrap --identity_file removal
+
+The ``knife bootstrap --identity_file`` flag has been removed. This flag was deprecated in Chef 12 and users should now use the ``--ssh-identity-file`` flag instead.
+
+### knife user support for Chef Server < 12 removed
+
+The `knife user` command no longer supports open source Chef Server version prior to 12.
+
+### Node attributes array bugfix
+
+Chef 15 includes a bugfix for incorrect node attribute behavior with a rare usage of arrays that may impact users that depended on the incorrect behavior.
+
+Previous setting an attribute like this:
+
+```
+node.default["foo"] = []
+node.default["foo"] << { "bar" => "baz }
+```
+
+Would result in a Hash instead of a VividMash inserted into the
+AttrArray, so that:
+
+```
+node.default["foo"][0]["bar"] # gives the correct result
+node.default["foo"][0][:bar] # does not work due to the sub-Hash not
+ # converting keys
+```
+
+The new behavior uses a Mash so that the attributes will work as expected.
+
+# Chef Client Release Notes 14.7:
+
+## New Resources
+
+### windows_firewall_rule
+
+Use the `windows_firewall_rule` resource create or delete Windows Firewall rules.
+
+See the [windows_firewall_rule](https://docs.chef.io/resource_windows_firewall_rule.html) documentation for more information.
+
+Thank you [Schuberg Philis](https://schubergphilis.com/) for transferring us the [windows_firewall cookbook](https://supermarket.chef.io/cookbooks/windows_firewall) and to [@Happycoil](https://github.com/Happycoil) for porting it to chef-client with a signifcant refactoring.
+
+### windows_share
+
+Use the `windows_share` resource create or delete Windows file shares.
+
+See the [windows_share](https://docs.chef.io/resource_windows_share.html) documentation for more information.
+
+### windows_certificate
+
+Use the `windows_certificate` resource add, remove, or verify certificates in the system or user certificate stores.
+
+See the [windows_certificate](https://docs.chef.io/resource_windows_certificate.html) documentation for more information.
+
+## Updated Resources
+
+### dmg_package
+
+The dmg_package resource has been refactored to improve idempotency and properly support accepting a DMG's EULA with the `accept_eula` property.
+
+### kernel_module
+
+Kernel_module now only runs the `initramfs` update once per Chef run to greatly speed up chef-client runs when multiple kernel_module resources are used. Thank you [@tomdoherty](https://github.com/tomdoherty) for this improvement.
+
+### mount
+
+The `supports` property once again allows passing supports data as an array. This matches the behavior present in Chef 12.
+
+### timezone
+
+macOS support has been added to the timezone resource.
+
+### windows_task
+
+A regression in Chef 14.6’s windows_task resource which resulted in tasks being created with the "Run only when user is logged on" option being set when created with a specific user other than SYSTEM, has been resolved.
+
# Chef Client Release Notes 14.6:
## Smaller Package and Install Size
@@ -73,11 +226,11 @@ Chef is now tested against macOS Mojave, and packages are now available at downl
### Filesystem Plugin on AIX and Solaris
-AIX and Solaris now ship with a filesystem2 plugin that updates the filesystem data to match that of Linux, macOS, amd BSD hosts. This new data structure makes accessing filesystem data in recipes easier and especially improves the layout and depth of data on ZFS filesystems. In Chef 15 (April 2019) we will begin wrting this same format of data to the existing `node['filesystem']` namespace. In Chef 16 (April 2020) we will remove the `node['filesystem2']` namspace, completing the transition to the new format. Thank you [@jaymzh](https://github.com/jaymzh) for continuing the updates to our filesystem plugins with this change.
+AIX and Solaris now ship with a filesystem2 plugin that updates the filesystem data to match that of Linux, macOS, and BSD hosts. This new data structure makes accessing filesystem data in recipes easier and especially improves the layout and depth of data on ZFS filesystems. In Chef 15 (April 2019) we will begin wrting this same format of data to the existing `node['filesystem']` namespace. In Chef 16 (April 2020) we will remove the `node['filesystem2']` namespace, completing the transition to the new format. Thank you [@jaymzh](https://github.com/jaymzh) for continuing the updates to our filesystem plugins with this change.
### macOS Improvements
-The system_profile plugin has been improved to skip over uncessary data, which reduces macOS node sizes on the Chef Server. Additionally the CPU plugin has been updated to limit what sysctl values it polls, which prevents hanging on some system configurations.
+The system_profile plugin has been improved to skip over unnecessary data, which reduces macOS node sizes on the Chef Server. Additionally the CPU plugin has been updated to limit what sysctl values it polls, which prevents hanging on some system configurations.
### SLES 15 Detection
@@ -660,7 +813,7 @@ Use the swap_file resource to create or delete swap files on Linux systems, and
### sysctl
-Use the sysctl resource to set kernel parameters using the sysctl command line tool and configuration files in the system's `sysctl.d` directory. Configuration files managed by this resource are named 99-chef-KEYNAME.conf. If an existing value was already set for the value it will be backed up to the node and restored if the :remove action is used later. This resource was ported from the `sysctl` community cookbook.
+Use the sysctl resource to set or remove kernel parameters using the sysctl command line tool and configuration files in the system's `sysctl.d` directory. Configuration files managed by this resource are named 99-chef-KEYNAME.conf. If an existing value was already set for the value it will be backed up to the node and restored if the :remove action is used later. This resource was ported from the `sysctl` community cookbook.
`Note`: This resource no longer backs up existing key values to the node when changing values as we have done in the sysctl cookbook previously. The resource has also been renamed from `sysctl_param` to `sysctl` with backwards compatibility for the previous name.
@@ -996,6 +1149,225 @@ optional_plugins in the client.rb file:
optional_plugins [ "lspci", "passwd" ]
```
+# Chef Client Release Notes 13.12
+
+## Smaller Package and Install Size
+
+We trimmed unnecessary installation files, greatly reducing the sizes of both Chef packages and on disk installations. MacOS/Linux/FreeBSD packages are ~50% smaller and Windows are ~12% smaller. Chef 13 is now smaller than a legacy Chef 10 package.
+
+## macOS Mojave (10.14)
+
+Chef is now tested against macOS Mojave and packages are now available at downloads.chef.io.
+
+## SUSE Linux Enterprise Server 15
+
+- Ohai now properly detects SLES 15
+- The Chef package will no longer remove symlinks to chef-client and ohai when upgrading on SLES 15
+
+## Updated Chef-Vault
+
+Updating chef-vault to 3.4.2 resolved multiple bugs.
+
+## Faster Windows Installations
+
+Improved Windows installation speed by skipping unnecessary steps when Windows Installer 5.0 or later is available.
+
+## Ohai Release Notes 13.12
+
+### macOS Improvements
+
+- sysctl commands have been modified to gather only the bare minimum required data, which prevents sysctl hanging in some scenarios
+- Extra data has been removed from the system_profile plugin, reducing the amount of data stored on the chef-server for each node
+
+## New Deprecations
+
+### system_profile Ohai plugin removal
+
+The system_profile plugin will be removed from Chef/Ohai 15 in April, 2019. This plugin incorrectly returns data on modern Mac systems. Further, the hardware plugin returns the same data in a more readily consumable format. Removing this plugin reduces the speed of the Ohai return by ~3 seconds and also greatly reduces the node object size on the Chef server
+
+### ohai_name property in ohai resource
+
+The ``ohai`` resource's unused ``ohai_name`` property has been deprecated. This will be removed in Chef 15.0.
+
+## Security Updates
+
+### Ruby 2.4.5
+
+Ruby has been updated to from 2.4.4 to 2.4.5 to resolve multiple CVEs as well as bugs:
+- [CVE-2018-16396](https://www.ruby-lang.org/en/news/2018/10/17/not-propagated-taint-flag-in-some-formats-of-pack-cve-2018-16396/)
+- [CVE-2018-16395](https://www.ruby-lang.org/en/news/2018/10/17/openssl-x509-name-equality-check-does-not-work-correctly-cve-2018-16395/)
+
+# Chef Client Release Notes 13.11
+
+### Sensitive Properties on Windows
+
+- `windows_service` no longer logs potentially sensitive information when a service is setup
+- `windows_package` now respects the `sensitive` property to avoid logging sensitive data in the event of a package installation failure
+
+### Other Fixes
+
+- `remote_directory` now properly loads files in the root of a cookbook's `files` directory
+- `osx_profile` now uses the full path the profiles CLI tool to avoid running other binaries of the same name in a users path
+- `package` resources that don't support the `allow_downgrade` property will no longer fail
+- `knife bootstrap windows` error messages have been improved
+
+## Security Updates
+
+### OpenSSL
+
+- OpenSSL has been updated to 1.0.2p to resolve [CVE-2018-0732](https://nvd.nist.gov/vuln/detail/CVE-2018-0732) and [CVE-2018-0737](https://nvd.nist.gov/vuln/detail/CVE-2018-0737)
+
+### Rubyzip
+
+- Updated Rubyzip to 1.2.2 to resolve [CVE-2018-1000544](https://nvd.nist.gov/vuln/detail/CVE-2018-1000544)
+
+# Chef Client Release Notes 13.10
+
+## Bugfixes
+
+- Resolves a duplicate logging getting created when redirecting stdout
+- Using --recipe-url with a local file on Windows no longer fails
+- Service resource no longer throws Ruby deprecation warnings on Windows
+
+## Ohai 13.10 Improvements
+
+- Correctly identify the platform_version on the final release of Amazon Linux 2.0
+- Detect nodes with the DMI data of "OpenStack Compute" as being OpenStack nodes
+
+## Security Updates
+
+### ffi Gem
+
+- CVE-2018-1000201: DLL loading issue which can be hijacked on Windows OS
+
+# Chef Client Release Notes 13.9.X:
+
+## Security Updates
+
+Ruby has been updated to 2.4.4
+
+- CVE-2017-17742: HTTP response splitting in WEBrick
+- CVE-2018-6914: Unintentional file and directory creation with directory traversal in tempfile and tmpdir
+- CVE-2018-8777: DoS by large request in WEBrick
+- CVE-2018-8778: Buffer under-read in String#unpack
+- CVE-2018-8779: Unintentional socket creation by poisoned NUL byte in UNIXServer and UNIXSocket
+- CVE-2018-8780: Unintentional directory traversal by poisoned NUL byte in Dir
+- Multiple vulnerabilities in RubyGems
+
+Nokogiri has been updated to 1.8.2
+
+- [MRI] Behavior in libxml2 has been reverted which caused CVE-2018-8048 (loofah gem), CVE-2018-3740 (sanitize gem), and CVE-2018-3741 (rails-html-sanitizer gem).
+
+OpenSSL has been updated to 1.0.2o
+
+- CVE-2018-0739: Constructed ASN.1 types with a recursive definition could exceed the stack.
+
+## Platform Updates
+
+As Debian 7 is now end of life we will no longer produce Debian 7 chef-client packages.
+
+## Ifconfig on Ubuntu 18.04
+
+Incompatibilities with Ubuntu 18.04 in the ifconfig resource have been resolved.
+
+## Ohai Updated to 13.9.2
+
+### Virtualization detection on AWS
+
+Ohai now detects the virtualization hypervisor `amazonec2` when running on Amazon's new C5/M5 instances.
+
+### Configurable DMI Whitelist
+
+The whitelist of DMI IDs is now user configurable using the `additional_dmi_ids` configuration setting, which takes an Array.
+
+### Filesystem2 on BSD
+
+The Filesystem2 functionality has been backported to BSD systems to provide a consistent filesystem format.
+
+# Chef Client Release Notes 13.9.1:
+
+## Platform Additions
+
+Enable Ubuntu-18.04 and Debian-9 tested chef-client packages.
+
+# Chef Client Release Notes 13.9:
+
+- On Windows, the installer now correctly re-extracts files during repair mode
+- The mount resource will now not create duplicate entries when the device type differs
+- Ensure we don't request every remote file when running with lazy loading enabled
+- Don't crash when getting the access rights for Windows system accounts
+
+## Custom Resource Improvements
+
+We've expanded the DSL for custom resources with new functionality to better document your resources and help users with errors and upgrades. Many resources in Chef itself are now using this new functionality, and you'll see more updated to take advantage of this it in the future.
+
+### Deprecations in Cookbook Resources
+
+Chef 13 provides new primitives that allow you to deprecate resources or properties with the same functionality used for deprecations in Chef Client resources. This allows you make breaking changes to enterprise or community cookbooks with friendly notifications to downstream cookbook consumers directly in the Chef run.
+
+Deprecate the foo_bar resource in a cookbook:
+
+```ruby
+deprecated "The foo_bar resource has been deprecated and will be removed in the next major release of this cookbook scheduled for 12/25/2018!"
+
+property :thing, String, name_property: true
+
+action :create do
+ # you'd probably have some actual chef code here
+end
+```
+
+Deprecate the thing2 property in a resource
+
+```ruby
+property :thing2, String, deprecated: 'The thing2 property has been deprecated and will be removed in the next major release of this cookbook scheduled for 12/25/2018!'
+```
+
+Rename a property with a deprecation warning for users of the old property name
+
+```ruby
+deprecated_property_alias 'thing2', 'the_second_thing', 'The thing2 property was renamed the_second_thing in the 2.0 release of this cookbook. Please update your cookbooks to use the new property name.'
+```
+
+### validation_message
+
+Validation messages allow you give the user a friendly error message when any validation on a property fails.
+
+Provide a friendly message when a regex fails:
+
+```ruby
+property :repo_name, String, regex: [/^[^\/]+$/], validation_message: "The repo_name property cannot contain a forward slash '/'",
+```
+
+### Resource Documentation
+
+You can now include documentation that describes how a resource is to be used. Expect this data to be consumed by Chef and other tooling in future releases.
+
+A resource which includes description and introduced values in the resource, actions, and properties:
+
+```ruby
+description 'The apparmor_policy resource is used to add or remove policy files from a cookbook file'
+introduced '14.1'
+
+property :source_cookbook, String,
+ description: 'The cookbook to source the policy file from'
+property :source_filename, String,
+ description: 'The name of the source file if it differs from the apparmor.d file being created'
+
+action :add do
+ description 'Adds an apparmor policy'
+
+ # you'd probably have some actual chef code here
+end
+```
+
+# Ohai Release Notes 13.9:
+
+- Fix uptime parsing on AIX
+- Fix Softlayer cloud detection
+- Use the current Azure metadata endpoint
+- Correctly detect macOS guests on VMware and VirtualBox
+
# Chef Client Release Notes 13.8:
## Revert attributes changes from 13.7
@@ -1875,3 +2247,230 @@ The implementation switched to `shell_out_with_systems_locale` to match `execute
Chef Client will only exit with exit codes defined in RFC 062\. This allows other tooling to respond to how a Chef run completes. Attempting to exit Chef Client with an unsupported exit code (either via `Chef::Application.fatal!` or `Chef::Application.exit!`) will result in an exit code of 1 (GENERIC_FAILURE) and a warning in the event log.
When Chef Client is running as a forked process on unix systems, the standardized exit codes are used by the child process. To actually have Chef Client return the standard exit code, `client_fork false` will need to be set in Chef Client's configuration file.
+
+# Chef Client Release Notes 12.22:
+
+## Security Updates
+
+### Ruby
+
+Ruby has been updated to 2.3.6 to resolve CVE-2017-17405
+
+### LibXML2
+
+Libxml2 has been updated to 2.9.7 to resolve CVE-2017-15412
+
+## Ohai 8.26.1
+
+### EC2 detection on C5/M5
+
+Ohai now provides EC2 metadata configuration information on the new C5/M5 instance types running on Amazon's new hypervisor.
+
+### LsPci Plugin
+
+The new LsPci plugin provides a node[:pci] hash with information about the PCI bus based on lspci. Only runs on Linux.
+
+### Docker Detection
+
+The virtualization plugin has been updated to properly detect when running on Docker CE
+
+# Chef Client Release Notes 12.21:
+
+## Security Fixes
+
+This release of Chef Client contains Ruby 2.3.5, fixing 4 CVEs:
+
+ * CVE-2017-0898
+ * CVE-2017-10784
+ * CVE-2017-14033
+ * CVE-2017-14064
+
+It also contains a new version of Rubygems, fixing 4 CVEs:
+
+ * CVE-2017-0899
+ * CVE-2017-0900
+ * CVE-2017-0901
+ * CVE-2017-0902
+
+This release also contains a new version of zlib, fixing 4
+CVEs:
+
+ * [CVE-2016-9840](https://www.cvedetails.com/cve/CVE-2016-9840/)
+ * [CVE-2016-9841](https://www.cvedetails.com/cve/CVE-2016-9841/)
+ * [CVE-2016-9842](https://www.cvedetails.com/cve/CVE-2016-9842/)
+ * [CVE-2016-9843](https://www.cvedetails.com/cve/CVE-2016-9843/)
+
+## On Debian based systems, correctly prefer Systemd to Upstart
+
+On Debian systems, packages that support systemd will often ship both an
+old style init script and a systemd unit file. When this happened, Chef
+would incorrectly choose Upstart rather than Systemd as the service
+provider. We now pick Systemd.
+
+## Handle the supports pseudo-property more gracefully
+
+Chef 13 removed the `supports` property from core resources. However,
+many cookbooks also have a property named support, and Chef 12 was
+incorrectly giving a deprecation notice in that case, preventing users
+from properly testing their cookbooks for upgrades.
+
+## Don't crash when we downgrade from Chef 13 to Chef 12
+
+On systems where Chef 13 had been run, Chef 12 would crash as the
+on disk cookbook format has changed. Chef 12 now correctly ignores the
+unexpected files.
+
+## Provide better system information when Chef crashes
+
+When Chef crashes, the output now includes details about the platform
+and version of Chef that was running, so that a bug report has more
+detail from the off.
+
+# Chef Client Release Notes 12.19:
+
+## Highlighted enhancements for this release:
+
+- Systemd unit files are now verified before being installed.
+- Added support for windows alternate user identity in execute resources.
+- Added ed25519 key support for for ssh connections.
+
+### Windows alternate user identity execute support
+
+The `execute` resource and similar resources such as `script`, `batch`, and `powershell_script` now support the specification of credentials on Windows so that the resulting process is created with the security identity that corresponds to those credentials.
+
+**Note**: When Chef is running as a service, this feature requires that the user that Chef runs as has 'SeAssignPrimaryTokenPrivilege' (aka 'SE_ASSIGNPRIMARYTOKEN_NAME') user right. By default only LocalSystem and NetworkService have this right when running as a service. This is necessary even if the user is an Administrator.
+
+This right bacn be added and checked in a recipe using this example:
+
+```ruby
+# Add 'SeAssignPrimaryTokenPrivilege' for the user
+Chef::ReservedNames::Win32::Security.add_account_right('<user>', 'SeAssignPrimaryTokenPrivilege')
+
+# Check if the user has 'SeAssignPrimaryTokenPrivilege' rights
+Chef::ReservedNames::Win32::Security.get_account_right('<user>').include?('SeAssignPrimaryTokenPrivilege')
+```
+
+#### Properties
+
+The following properties are new or updated for the `execute`, `script`, `batch`, and `powershell_script` resources and any resources derived from them:
+
+- `user`<br>
+ **Ruby types:** String<br>
+ The user name of the user identity with which to launch the new process. Default value: `nil`. The user name may optionally be specified with a domain, i.e. `domain\user` or `user@my.dns.domain.com` via Universal Principal Name (UPN) format. It can also be specified without a domain simply as `user` if the domain is instead specified using the `domain` attribute. On Windows only, if this property is specified, the `password` property **must** be specified.
+
+- `password`<br>
+ **Ruby types** String<br>
+ _Windows only:_ The password of the user specified by the `user` property. Default value: `nil`. This property is mandatory if `user` is specified on Windows and may only be specified if `user` is specified. The `sensitive` property for this resource will automatically be set to `true` if `password` is specified.
+
+- `domain`<br>
+ **Ruby types** String<br>
+ _Windows only:_ The domain of the user user specified by the `user` property. Default value: `nil`. If not specified, the user name and password specified by the `user` and `password` properties will be used to resolve that user against the domain in which the system running Chef client is joined, or if that system is not joined to a domain it will resolve the user as a local account on that system. An alternative way to specify the domain is to leave this property unspecified and specify the domain as part of the `user` property.
+
+#### Usage
+
+The following examples explain how alternate user identity properties can be used in the execute resources:
+
+```ruby
+powershell_script 'create powershell-test file' do
+ code <<-EOH
+ $stream = [System.IO.StreamWriter] "#{Chef::Config[:file_cache_path]}/powershell-test.txt"
+ $stream.WriteLine("In #{Chef::Config[:file_cache_path]}...word.")
+ $stream.close()
+ EOH
+ user 'username'
+ password 'password'
+end
+
+execute 'mkdir test_dir' do
+ cwd Chef::Config[:file_cache_path]
+ domain "domain-name"
+ user "user"
+ password "password"
+end
+
+script 'create test_dir' do
+ interpreter "bash"
+ code "mkdir test_dir"
+ cwd Chef::Config[:file_cache_path]
+ user "domain-name\\username"
+ password "password"
+end
+
+batch 'create test_dir' do
+ code "mkdir test_dir"
+ cwd Chef::Config[:file_cache_path]
+ user "username@domain-name"
+ password "password"
+end
+```
+
+## Highlighted bug fixes for this release:
+
+- Ensure that the Windows Administrator group can access the chef-solo nodes directory
+- When loading a cookbook in Chef Solo, use `metadata.json` in preference to `metadata.rb`
+
+## Deprecation Notice
+
+- As of version 12.19, chef client will no longer be build or tested on the Cisco NX-OS and IOS XR platforms.
+
+# Ohai Release Notes 8.23:
+
+## Cumulus Linux Platform
+
+Cumulus Linux will now be detected as platform `cumulus` instead of `debian` and the `platform_version` will be properly set to the Cumulus Linux release.
+
+## Virtualization Detection
+
+Windows / Linux / BSD guests running on the Veertu hypervisors will now be detected
+
+Windows guests running on Xen and Hyper-V hypervisors will now be detected
+
+## New Sysconf Plugin
+
+A new plugin parses the output of the sysconf command to provide information on the underlying system.
+
+## AWS Account ID
+
+The EC2 plugin now fetches the AWS Account ID in addition to previous instance metadata
+
+## GCC Detection
+
+GCC detection has been improved to collect additional information, and to not prompt for the installation of Xcode on macOS systems
+
+## New deprecations introduced in this release:
+
+### Ohai::Config removed
+
+- **Deprecation ID**: OHAI-1
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_legacy_config.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### sigar gem based plugins removed
+
+- **Deprecation ID**: OHAI-2
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_sigar_plugins.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### run_command and popen4 helper methods removed
+
+- **Deprecation ID**: OHAI-3
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_run_command_helpers.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### libvirt plugin attributes moved
+
+- **Deprecation ID**: OHAI-4
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_libvirt_plugin.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### Windows CPU plugin attribute changes
+
+- **Deprecation ID**: OHAI-5
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_windows_cpu.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### DigitalOcean plugin attribute changes
+
+- **Deprecation ID**: OHAI-6
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_digitalocean.html>
+- **Expected Removal**: Ohai 13 (April 2017)
diff --git a/VERSION b/VERSION
index 3e26b8fe14..5c3cbd6701 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-15.0.8 \ No newline at end of file
+15.0.83 \ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
index 378574103f..e5ad88b8a3 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,7 +5,12 @@ platform:
- x64
cache:
-- vendor/bundle
+ - vendor/bundle
+
+configuration:
+ - integration
+ - functional
+ - unit
environment:
matrix:
@@ -41,6 +46,7 @@ install:
- SET BUNDLE_WITHOUT=server:docgen:maintenance:pry:travis:integration:ci
- bundle config --local path vendor/bundle # use the cache we define above
- bundle install || bundle install || bundle install
+ - SET SPEC_OPTS=--format progress
build: off
@@ -50,6 +56,23 @@ before_test:
- bundler --version
- bundle env
-test_script:
- - SET SPEC_OPTS=--format progress
- - bundle exec rake spec
+for:
+ -
+ matrix:
+ only:
+ - configuration: integration
+ build_script:
+ - bundle exec rake spec:integration
+ -
+ matrix:
+ only:
+ - configuration: functional
+ build_script:
+ - bundle exec rake spec:functional
+ -
+ matrix:
+ only:
+ - configuration: unit
+ build_script:
+ - bundle exec rake spec:unit
+ - bundle exec rake component_specs
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb
index 2976e27322..6150bbfea9 100644
--- a/chef-config/lib/chef-config/config.rb
+++ b/chef-config/lib/chef-config/config.rb
@@ -358,7 +358,7 @@ module ChefConfig
# Whether or not to send the Authorization header again on http redirects.
# As per the plan in https://github.com/chef/chef/pull/7006, this will be
# False in Chef 14, True in Chef 15, and will be removed entirely in Chef 16.
- default :http_disable_auth_on_redirect, false
+ default :http_disable_auth_on_redirect, true
default :interval, nil
default :once, nil
@@ -436,8 +436,6 @@ module ChefConfig
end
default :rest_timeout, 300
- default :yum_timeout, 900
- default :yum_lock_timeout, 30
default :solo, false
# Are we running in old Chef Solo legacy mode?
@@ -491,12 +489,6 @@ module ChefConfig
default :named_run_list, nil
- # During initial development, users were required to set `use_policyfile true`
- # in `client.rb` to opt-in to policyfile use. Chef Client now examines
- # configuration, node json, and the stored node to determine if policyfile
- # usage is desired. This flag is still honored if set, but is unnecessary.
- default :use_policyfile, false
-
# Policyfiles can be used in a native mode (default) or compatibility mode.
# Native mode requires Chef Server 12.1 (it can be enabled via feature flag
# on some prior versions). In native mode, policies and associated
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index 35a4987251..f407773702 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 = "15.0.8".freeze
+ VERSION = "15.0.83".freeze
end
#
diff --git a/chef-universal-mingw32.gemspec b/chef-universal-mingw32.gemspec
index f663153159..7e1a9d1551 100644
--- a/chef-universal-mingw32.gemspec
+++ b/chef-universal-mingw32.gemspec
@@ -16,6 +16,7 @@ gemspec.add_dependency "windows-api", "~> 0.4.4"
gemspec.add_dependency "wmi-lite", "~> 1.0"
gemspec.add_dependency "win32-taskscheduler", "~> 2.0"
gemspec.add_dependency "iso8601", "~> 0.12.1"
+gemspec.add_dependency "win32-certstore", ">= 0.1.8"
gemspec.extensions << "ext/win32-eventlog/Rakefile"
gemspec.files += Dir.glob("{distro,ext}/**/*")
diff --git a/chef.gemspec b/chef.gemspec
index 1db824c927..c787e00580 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -33,7 +33,7 @@ Gem::Specification.new do |s|
s.add_dependency "erubis", "~> 2.7"
s.add_dependency "diff-lcs", "~> 1.2", ">= 1.2.4"
- s.add_dependency "chef-zero", ">= 13.0"
+ s.add_dependency "chef-zero", ">= 14.0.11"
s.add_dependency "plist", "~> 3.2"
s.add_dependency "iniparse", "~> 1.4"
diff --git a/ci/verify-chef.sh b/ci/verify-chef.sh
index 3db37a5cf6..b6dafa33e4 100755
--- a/ci/verify-chef.sh
+++ b/ci/verify-chef.sh
@@ -2,6 +2,20 @@
set -evx
+# Our tests hammer YUM pretty hard and the EL6 testers get corrupted
+# after some period of time. Rebuilding the RPM database clears
+# up the underlying corruption. We'll do this each test run just to
+# be safe.
+if [ -f /etc/redhat-release ]; then
+ major_version=`sed 's/^.\+ release \([0-9]\+\).*/\1/' /etc/redhat-release`
+ if [ "$major_version" -lt "7" ]; then
+ sudo rm -rf /var/lib/rpm/__db*
+ sudo db_verify /var/lib/rpm/Packages
+ sudo rpm --rebuilddb
+ sudo yum clean all
+ fi
+fi
+
# Set up a custom tmpdir, and clean it up before and after the tests
TMPDIR="${TMPDIR:-/tmp}/cheftest"
export TMPDIR
diff --git a/lib/chef/application/apply.rb b/lib/chef/application/apply.rb
index 7325d89e1e..5b697703d7 100644
--- a/lib/chef/application/apply.rb
+++ b/lib/chef/application/apply.rb
@@ -191,10 +191,12 @@ class Chef::Application::Apply < Chef::Application
recipe, run_context = get_recipe_and_run_context
recipe.instance_eval(@recipe_text, @recipe_filename, 1)
runner = Chef::Runner.new(run_context)
- begin
- runner.converge
- ensure
- @recipe_fh.close
+ catch(:end_client_run_early) do
+ begin
+ runner.converge
+ ensure
+ @recipe_fh.close
+ end
end
Chef::Platform::Rebooter.reboot_if_needed!(runner)
end
diff --git a/lib/chef/cookbook/cookbook_version_loader.rb b/lib/chef/cookbook/cookbook_version_loader.rb
index c864c30505..96bc4aa303 100644
--- a/lib/chef/cookbook/cookbook_version_loader.rb
+++ b/lib/chef/cookbook/cookbook_version_loader.rb
@@ -7,12 +7,21 @@ require "find"
class Chef
class Cookbook
+ # This class is only used drectly from the Chef::CookbookLoader and from chef-fs,
+ # so it only affects legacy-mode chef-client runs and knife. It is not used by
+ # server or zolo/zero modes.
+ #
+ # This seems to be mostly a glorified factory method for creating CookbookVersion
+ # objects now, with creating Metadata objects bolted onto the side? It used
+ # to be also responsible for the merging of multiple objects when creating
+ # shadowed/merged cookbook versions from multiple sources. It also handles
+ # Chefignore files.
+ #
class CookbookVersionLoader
UPLOADED_COOKBOOK_VERSION_FILE = ".uploaded-cookbook-version.json".freeze
attr_reader :cookbook_settings
- attr_reader :cookbook_paths
attr_reader :frozen
attr_reader :uploaded_cookbook_version_file
@@ -25,13 +34,11 @@ class Chef
def initialize(path, chefignore = nil)
@cookbook_path = File.expand_path( path ) # cookbook_path from which this was loaded
- # We keep a list of all cookbook paths that have been merged in
- @cookbook_paths = [ cookbook_path ]
@inferred_cookbook_name = File.basename( path )
@chefignore = chefignore
@metadata = nil
- @relative_path = /#{Regexp.escape(@cookbook_path)}\/(.+)$/
+ @relative_path = /#{Regexp.escape(cookbook_path)}\/(.+)$/
@metadata_loaded = false
@cookbook_settings = {
all_files: {},
@@ -68,53 +75,22 @@ class Chef
if empty?
Chef::Log.warn "Found a directory #{cookbook_name} in the cookbook path, but it contains no cookbook files. skipping."
end
- @cookbook_settings
+ cookbook_settings
end
alias :load_cookbooks :load
- def metadata_filenames
- return @metadata_filenames unless @metadata_filenames.empty?
- if File.exists?(File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE))
- @uploaded_cookbook_version_file = File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE)
- end
-
- if File.exists?(File.join(cookbook_path, "metadata.json"))
- @metadata_filenames << File.join(cookbook_path, "metadata.json")
- elsif File.exists?(File.join(cookbook_path, "metadata.rb"))
- @metadata_filenames << File.join(cookbook_path, "metadata.rb")
- elsif @uploaded_cookbook_version_file
- @metadata_filenames << @uploaded_cookbook_version_file
- end
-
- # Set frozen based on .uploaded-cookbook-version.json
- set_frozen
- @metadata_filenames
- end
-
def cookbook_version
return nil if empty?
- Chef::CookbookVersion.new(cookbook_name, *cookbook_paths).tap do |c|
+ Chef::CookbookVersion.new(cookbook_name, cookbook_path).tap do |c|
c.all_files = cookbook_settings[:all_files].values
c.metadata = metadata
- c.freeze_version if @frozen
+ c.freeze_version if frozen
end
end
- def cookbook_name
- # The `name` attribute is now required in metadata, so
- # inferred_cookbook_name generally should not be used. Per CHEF-2923,
- # we have to not raise errors in cookbook metadata immediately, so that
- # users can still `knife cookbook upload some-cookbook` when an
- # unrelated cookbook has an error in its metadata. This situation
- # could prevent us from reading the `name` attribute from the metadata
- # entirely, but the name is used as a hash key in CookbookLoader, so we
- # fall back to the inferred name here.
- (metadata.name || @inferred_cookbook_name).to_sym
- end
-
# Generates the Cookbook::Metadata object
def metadata
return @metadata unless @metadata.nil?
@@ -125,7 +101,7 @@ class Chef
case metadata_file
when /\.rb$/
apply_ruby_metadata(metadata_file)
- when @uploaded_cookbook_version_file
+ when uploaded_cookbook_version_file
apply_json_cookbook_version_metadata(metadata_file)
when /\.json$/
apply_json_metadata(metadata_file)
@@ -146,13 +122,46 @@ class Chef
@metadata
end
+ def cookbook_name
+ # The `name` attribute is now required in metadata, so
+ # inferred_cookbook_name generally should not be used. Per CHEF-2923,
+ # we have to not raise errors in cookbook metadata immediately, so that
+ # users can still `knife cookbook upload some-cookbook` when an
+ # unrelated cookbook has an error in its metadata. This situation
+ # could prevent us from reading the `name` attribute from the metadata
+ # entirely, but the name is used as a hash key in CookbookLoader, so we
+ # fall back to the inferred name here.
+ (metadata.name || inferred_cookbook_name).to_sym
+ end
+
+ private
+
+ def metadata_filenames
+ return @metadata_filenames unless @metadata_filenames.empty?
+ if File.exists?(File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE))
+ @uploaded_cookbook_version_file = File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE)
+ end
+
+ if File.exists?(File.join(cookbook_path, "metadata.json"))
+ @metadata_filenames << File.join(cookbook_path, "metadata.json")
+ elsif File.exists?(File.join(cookbook_path, "metadata.rb"))
+ @metadata_filenames << File.join(cookbook_path, "metadata.rb")
+ elsif uploaded_cookbook_version_file
+ @metadata_filenames << uploaded_cookbook_version_file
+ end
+
+ # Set frozen based on .uploaded-cookbook-version.json
+ set_frozen
+ @metadata_filenames
+ end
+
def raise_metadata_error!
- raise @metadata_error unless @metadata_error.nil?
+ raise metadata_error unless metadata_error.nil?
# Metadata won't be valid if the cookbook is empty. If the cookbook is
# actually empty, a metadata error here would be misleading, so don't
# raise it (if called by #load!, a different error is raised).
if !empty? && !metadata.valid?
- message = "Cookbook loaded at path(s) [#{@cookbook_paths.join(', ')}] has invalid metadata: #{metadata.errors.join('; ')}"
+ message = "Cookbook loaded at path [#{cookbook_path}] has invalid metadata: #{metadata.errors.join('; ')}"
raise Exceptions::MetadataNotValid, message
end
false
@@ -162,18 +171,6 @@ class Chef
cookbook_settings.values.all? { |files_hash| files_hash.empty? } && metadata_filenames.size == 0
end
- def merge!(other_cookbook_loader)
- other_cookbook_settings = other_cookbook_loader.cookbook_settings
- cookbook_settings.each do |file_type, file_list|
- file_list.merge!(other_cookbook_settings[file_type])
- end
- metadata_filenames.concat(other_cookbook_loader.metadata_filenames)
- @cookbook_paths += other_cookbook_loader.cookbook_paths
- @frozen = true if other_cookbook_loader.frozen
- @metadata = nil # reset metadata so it gets reloaded and all metadata files applied.
- self
- end
-
def chefignore
@chefignore ||= Chefignore.new(File.basename(cookbook_path))
end
@@ -223,14 +220,14 @@ class Chef
def apply_ruby_metadata(file)
@metadata.from_file(file)
rescue Chef::Exceptions::JSON::ParseError
- Chef::Log.error("Error evaluating metadata.rb for #{@inferred_cookbook_name} in " + file)
+ Chef::Log.error("Error evaluating metadata.rb for #{inferred_cookbook_name} in " + file)
raise
end
def apply_json_metadata(file)
@metadata.from_json(IO.read(file))
rescue Chef::Exceptions::JSON::ParseError
- Chef::Log.error("Couldn't parse cookbook metadata JSON for #{@inferred_cookbook_name} in " + file)
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #{inferred_cookbook_name} in " + file)
raise
end
@@ -247,7 +244,7 @@ class Chef
# metadata contains a name key.
@metadata.name(data["cookbook_name"]) unless data["metadata"].key?("name")
rescue Chef::Exceptions::JSON::ParseError
- Chef::Log.error("Couldn't parse cookbook metadata JSON for #{@inferred_cookbook_name} in " + file)
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #{inferred_cookbook_name} in " + file)
raise
end
@@ -257,7 +254,7 @@ class Chef
data = Chef::JSONCompat.parse(IO.read(uploaded_cookbook_version_file))
@frozen = data["frozen?"]
rescue Chef::Exceptions::JSON::ParseError
- Chef::Log.error("Couldn't parse cookbook metadata JSON for #{@inferred_cookbook_name} in #{uploaded_cookbook_version_file}")
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #{inferred_cookbook_name} in #{uploaded_cookbook_version_file}")
raise
end
end
diff --git a/lib/chef/cookbook_loader.rb b/lib/chef/cookbook_loader.rb
index 322de539f1..1a7dec8b03 100644
--- a/lib/chef/cookbook_loader.rb
+++ b/lib/chef/cookbook_loader.rb
@@ -25,75 +25,83 @@ require "chef/cookbook_version"
require "chef/cookbook/chefignore"
require "chef/cookbook/metadata"
-#
-# CookbookLoader class loads the cookbooks lazily as read
-#
class Chef
+ # This class is used by knife, cheffs and legacy chef-solo modes. It is not used by the server mode
+ # of chef-client or zolo/zero modes.
+ #
+ # This class implements orchestration around producing a single cookbook_version for a cookbook or
+ # loading a Mash of all cookbook_versions, using the cookbook_version_loader class, and doing
+ # lazy-access and memoization to only load each cookbook once on demand.
+ #
+ # This implements a key-value style each which makes it appear to be a Hash of String => CookbookVersion
+ # pairs where the String is the cookbook name. The use of Enumerable combined with the Hash-style
+ # each is likely not entirely sane.
+ #
+ # This object is also passed and injected into the CookbookCollection object where it is converted
+ # to a Mash that looks almost exactly like the cookbook_by_name Mash in this object.
+ #
class CookbookLoader
+ # @return [Array<String>] the array of repo paths containing cookbook dirs
+ attr_reader :repo_paths
- attr_reader :cookbooks_by_name
- attr_reader :merged_cookbooks
- attr_reader :cookbook_paths
- attr_reader :metadata
-
+ # XXX: this is highly questionable combined with the Hash-style each method
include Enumerable
+ # @param repo_paths [Array<String>] the array of repo paths containing cookbook dirs
def initialize(*repo_paths)
- repo_paths = repo_paths.flatten
+ @repo_paths = repo_paths.flatten.map { |p| File.expand_path(p) }
raise ArgumentError, "You must specify at least one cookbook repo path" if repo_paths.empty?
- @cookbooks_by_name = Mash.new
- @loaded_cookbooks = {}
- @metadata = Mash.new
- @chefignores = {}
- @repo_paths = repo_paths.map do |repo_path|
- File.expand_path(repo_path)
- end
+ end
+
+ # The primary function of this class is to build this Mash mapping cookbook names as a string to
+ # the CookbookVersion objects for them. Callers must call "load_cookbooks" first.
+ #
+ # @return [Mash<String, Chef::CookbookVersion>]
+ def cookbooks_by_name
+ @cookbooks_by_name ||= Mash.new
+ end
- @preloaded_cookbooks = false
- @loaders_by_name = {}
+ # This class also builds a mapping of cookbook names to their Metadata objects. Callers must call
+ # "load_cookbooks" first.
+ #
+ # @return [Mash<String, Chef::Cookbook::Metadata>]
+ def metadata
+ @metadata ||= Mash.new
end
+ # Loads all cookbooks across all repo_paths
+ #
+ # @return [Mash<String, Chef::CookbookVersion>] the cookbooks_by_name Mash
def load_cookbooks
- preload_cookbooks
- @loaders_by_name.each_key do |cookbook_name|
+ cookbook_version_loaders.each_key do |cookbook_name|
load_cookbook(cookbook_name)
end
- @cookbooks_by_name
+ cookbooks_by_name
end
+ # Loads a single cookbook by its name.
+ #
+ # @param [String]
+ # @return [Chef::CookbookVersion]
def load_cookbook(cookbook_name)
- preload_cookbooks
-
- return @cookbooks_by_name[cookbook_name] if @cookbooks_by_name.key?(cookbook_name)
-
- return nil unless @loaders_by_name.key?(cookbook_name.to_s)
-
- cookbook_loaders_for(cookbook_name).each do |loader|
- loader.load
+ unless cookbook_version_loaders.key?(cookbook_name)
+ raise Exceptions::CookbookNotFoundInRepo, "Cannot find a cookbook named #{cookbook_name}; did you forget to add metadata to a cookbook? (https://docs.chef.io/config_rb_metadata.html)"
+ end
- next if loader.empty?
+ return cookbooks_by_name[cookbook_name] if cookbooks_by_name.key?(cookbook_name)
- if @loaded_cookbooks.key?(cookbook_name)
- raise Chef::Exceptions::CookbookMergingError, "Cookbook merging is no longer supported, the cookbook named #{cookbook_name} can only appear once in the cookbook_path"
- end
+ loader = cookbook_version_loaders[cookbook_name]
- @loaded_cookbooks[cookbook_name] = loader
- end
+ loader.load
- if @loaded_cookbooks.key?(cookbook_name)
- cookbook_version = @loaded_cookbooks[cookbook_name].cookbook_version
- @cookbooks_by_name[cookbook_name] = cookbook_version
- @metadata[cookbook_name] = cookbook_version.metadata
- end
- @cookbooks_by_name[cookbook_name]
+ cookbook_version = loader.cookbook_version
+ cookbooks_by_name[cookbook_name] = cookbook_version
+ metadata[cookbook_name] = cookbook_version.metadata
+ cookbook_version
end
def [](cookbook)
- if @cookbooks_by_name.key?(cookbook.to_sym) || load_cookbook(cookbook.to_sym)
- @cookbooks_by_name[cookbook.to_sym]
- else
- raise Exceptions::CookbookNotFoundInRepo, "Cannot find a cookbook named #{cookbook}; did you forget to add metadata to a cookbook? (https://docs.chef.io/config_rb_metadata.html)"
- end
+ load_cookbook(cookbook)
end
alias :fetch :[]
@@ -106,8 +114,8 @@ class Chef
alias :key? :has_key?
def each
- @cookbooks_by_name.keys.sort_by(&:to_s).each do |cname|
- yield(cname, @cookbooks_by_name[cname])
+ cookbooks_by_name.keys.sort_by(&:to_s).each do |cname|
+ yield(cname, cookbooks_by_name[cname])
end
end
@@ -120,32 +128,25 @@ class Chef
end
def cookbook_names
- @cookbooks_by_name.keys.sort
+ cookbooks_by_name.keys.sort
end
def values
- @cookbooks_by_name.values
+ cookbooks_by_name.values
end
alias :cookbooks :values
private
- def preload_cookbooks
- return false if @preloaded_cookbooks
-
- all_directories_in_repo_paths.each do |cookbook_path|
- preload_cookbook(cookbook_path)
- end
- @preloaded_cookbooks = true
- true
- end
-
- def preload_cookbook(cookbook_path)
- repo_path = File.dirname(cookbook_path)
+ # Helper method to lazily create and remember the chefignore object
+ # for a given repo_path.
+ #
+ # @param [String] repo_path the full path to the cookbook directory of the repo
+ # @return [Chef::Cookbook::Chefignore] the chefignore object for the repo_path
+ def chefignore(repo_path)
+ @chefignores ||= {}
@chefignores[repo_path] ||= Cookbook::Chefignore.new(repo_path)
- loader = Cookbook::CookbookVersionLoader.new(cookbook_path, @chefignores[repo_path])
- add_cookbook_loader(loader)
end
def all_directories_in_repo_paths
@@ -156,23 +157,29 @@ class Chef
def all_files_in_repo_paths
@all_files_in_repo_paths ||=
begin
- @repo_paths.inject([]) do |all_children, repo_path|
+ repo_paths.inject([]) do |all_children, repo_path|
all_children + Dir[File.join(Chef::Util::PathHelper.escape_glob_dir(repo_path), "*")]
end
end
end
- def add_cookbook_loader(loader)
- cookbook_name = loader.cookbook_name
-
- @loaders_by_name[cookbook_name.to_s] ||= []
- @loaders_by_name[cookbook_name.to_s] << loader
- loader
- end
-
- def cookbook_loaders_for(cookbook_name)
- @loaders_by_name[cookbook_name.to_s]
+ # This method creates a Mash of the CookbookVersionLoaders for each cookbook.
+ #
+ # @return [Mash<String, Cookbook::CookbookVersionLoader>]
+ def cookbook_version_loaders
+ @cookbook_version_loaders ||=
+ begin
+ mash = Mash.new
+ all_directories_in_repo_paths.each do |cookbook_path|
+ loader = Cookbook::CookbookVersionLoader.new(cookbook_path, chefignore(File.dirname(cookbook_path)))
+ cookbook_name = loader.cookbook_name
+ if mash.key?(cookbook_name)
+ raise Chef::Exceptions::CookbookMergingError, "Cookbook merging is no longer supported, the cookbook named #{cookbook_name} can only appear once in the cookbook_path"
+ end
+ mash[cookbook_name] = loader
+ end
+ mash
+ end
end
-
end
end
diff --git a/lib/chef/dsl/chef_provisioning.rb b/lib/chef/dsl/chef_provisioning.rb
deleted file mode 100644
index a91d297d02..0000000000
--- a/lib/chef/dsl/chef_provisioning.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Author:: John Keiser (<jkeiser@chef.io>)
-# Copyright:: Copyright 2015-2016, 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
- module DSL
- # Lazy activation for the chef-provisioning gem. Specifically, we set up methods for
- # each resource and DSL method in chef-provisioning which, when invoked, will
- # require 'chef-provisioning' (which will define the actual method) and then call the
- # method chef-provisioning defined.
- module ChefProvisioning
- %w{
- add_machine_options
- current_image_options
- current_machine_options
- load_balancer
- machine_batch
- machine_execute
- machine_file
- machine_image
- machine
- with_driver
- with_image_options
- with_machine_options
- }.each do |method_name|
- eval(<<-EOM, binding, __FILE__, __LINE__ + 1)
- def #{method_name}(*args, &block)
- Chef::DSL::ChefProvisioning.load_chef_provisioning
- self.#{method_name}(*args, &block)
- end
- EOM
- end
-
- def self.load_chef_provisioning
- # Remove all chef-provisioning methods; they will be added back in by chef-provisioning
- public_instance_methods(false).each do |method_name|
- remove_method(method_name)
- end
- require "chef/provisioning"
- end
- end
- end
-end
diff --git a/lib/chef/dsl/resources.rb b/lib/chef/dsl/resources.rb
index 638e626ae2..9010edc5f7 100644
--- a/lib/chef/dsl/resources.rb
+++ b/lib/chef/dsl/resources.rb
@@ -1,6 +1,6 @@
#
# Author:: John Keiser <jkeiser@chef.io>
-# Copyright:: Copyright 2015-2017, Chef Software Inc.
+# Copyright:: Copyright 2015-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,7 +16,6 @@
# limitations under the License.
require "chef/dsl/cheffish"
-require "chef/dsl/chef_provisioning"
class Chef
module DSL
@@ -27,10 +26,9 @@ class Chef
#
# @api private
module Resources
- # Include the lazy loaders for cheffish and chef-provisioning, so that the
- # resource DSL is there but the gems aren't activated yet.
+ # Include the lazy loader for cheffish, so that the
+ # resource DSL is there but the gem isn't activated yet.
include Chef::DSL::Cheffish
- include Chef::DSL::ChefProvisioning
def self.add_resource_dsl(dsl_name)
module_eval(<<-EOM, __FILE__, __LINE__ + 1)
diff --git a/lib/chef/knife/config_list_profiles.rb b/lib/chef/knife/config_list_profiles.rb
index 8e46aef14b..b767e9dd42 100644
--- a/lib/chef/knife/config_list_profiles.rb
+++ b/lib/chef/knife/config_list_profiles.rb
@@ -21,7 +21,7 @@ require "chef/workstation_config_loader"
class Chef
class Knife
class ConfigListProfiles < Knife
- banner "knife config list-profiles"
+ banner "knife config list-profiles (options)"
option :ignore_knife_rb,
short: "-i",
diff --git a/lib/chef/knife/cookbook_create.rb b/lib/chef/knife/cookbook_create.rb
deleted file mode 100644
index 6122fd52d3..0000000000
--- a/lib/chef/knife/cookbook_create.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Author:: Nuo Yan (<nuo@chef.io>)
-# Copyright:: Copyright 2009-2016, 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/knife"
-
-class Chef
- class Knife
- class CookbookCreate < Knife
- def run
- Chef::Log.fatal("knife cookbook create has been removed. Please use `chef generate cookbook` from the ChefDK")
- end
- end
- end
-end
diff --git a/lib/chef/knife/cookbook_test.rb b/lib/chef/knife/cookbook_test.rb
deleted file mode 100644
index 2f600bf964..0000000000
--- a/lib/chef/knife/cookbook_test.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@chef.io>)
-# Author:: Matthew Kent (<mkent@magoazul.com>)
-# Copyright:: Copyright 2009-2018, Chef Software Inc.
-# Copyright:: Copyright 2010-2016, Matthew Kent
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/knife"
-
-class Chef
- class Knife
- class CookbookTest < Knife
-
- deps do
- require "chef/cookbook_loader"
- require "chef/cookbook/syntax_check"
- end
-
- banner "knife cookbook test [COOKBOOKS...] (options)"
-
- option :cookbook_path,
- short: "-o PATH:PATH",
- long: "--cookbook-path PATH:PATH",
- description: "A colon-separated path to look for cookbooks in",
- proc: lambda { |o| o.split(":") }
-
- option :all,
- short: "-a",
- long: "--all",
- description: "Test all cookbooks, rather than just a single cookbook"
-
- def run
- ui.warn("DEPRECATED: Please use ChefSpec or Cookstyle to syntax-check cookbooks.")
- config[:cookbook_path] ||= Chef::Config[:cookbook_path]
-
- checked_a_cookbook = false
- if config[:all]
- cl = cookbook_loader
- cl.load_cookbooks
- cl.each_key do |key|
- checked_a_cookbook = true
- test_cookbook(key)
- end
- else
- @name_args.each do |cb|
- ui.info "checking #{cb}"
- next unless cookbook_loader.cookbook_exists?(cb)
- checked_a_cookbook = true
- test_cookbook(cb)
- end
- end
- unless checked_a_cookbook
- ui.warn("No cookbooks to test in #{Array(config[:cookbook_path]).join(',')} - is your cookbook path misconfigured?")
- end
- end
-
- def test_cookbook(cookbook)
- ui.info("Running syntax check on #{cookbook}")
- Array(config[:cookbook_path]).reverse_each do |path|
- syntax_checker = Chef::Cookbook::SyntaxCheck.for_cookbook(cookbook, path)
- test_ruby(syntax_checker)
- test_templates(syntax_checker)
- end
- end
-
- def test_ruby(syntax_checker)
- ui.info("Validating ruby files")
- exit(1) unless syntax_checker.validate_ruby_files
- end
-
- def test_templates(syntax_checker)
- ui.info("Validating templates")
- exit(1) unless syntax_checker.validate_templates
- end
-
- def cookbook_loader
- @cookbook_loader ||= Chef::CookbookLoader.new(config[:cookbook_path])
- end
-
- end
- end
-end
diff --git a/lib/chef/knife/list.rb b/lib/chef/knife/list.rb
index 9452478ddb..5d95790a26 100644
--- a/lib/chef/knife/list.rb
+++ b/lib/chef/knife/list.rb
@@ -19,7 +19,7 @@ require "chef/chef_fs/knife"
class Chef
class Knife
class List < Chef::ChefFS::Knife
- banner "knife list [-dfR1p] [PATTERN1 ... PATTERNn]"
+ banner "knife list [-dfR1p] [PATTERN1 ... PATTERNn] (options)"
category "path-based"
diff --git a/lib/chef/knife/osc_user_create.rb b/lib/chef/knife/osc_user_create.rb
deleted file mode 100644
index 97da785098..0000000000
--- a/lib/chef/knife/osc_user_create.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-2016, 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/knife"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_create.rb.
-class Chef
- class Knife
- class OscUserCreate < Knife
-
- deps do
- require "chef/user"
- require "chef/json_compat"
- end
-
- option :file,
- short: "-f FILE",
- long: "--file FILE",
- description: "Write the private key to a file."
-
- option :admin,
- short: "-a",
- long: "--admin",
- description: "Create the user as an admin.",
- boolean: true
-
- option :user_password,
- short: "-p PASSWORD",
- long: "--password PASSWORD",
- description: "Password for newly created user.",
- default: ""
-
- option :user_key,
- long: "--user-key FILENAME",
- description: "Public key for newly created user. By default a key will be created for you."
-
- banner "knife osc_user create USER (options)"
-
- def run
- @user_name = @name_args[0]
-
- if @user_name.nil?
- show_usage
- ui.fatal("You must specify a user name")
- exit 1
- end
-
- if config[:user_password].length == 0
- show_usage
- ui.fatal("You must specify a non-blank password")
- exit 1
- end
-
- user = Chef::User.new
- user.name(@user_name)
- user.admin(config[:admin])
- user.password config[:user_password]
-
- if config[:user_key]
- user.public_key File.read(File.expand_path(config[:user_key]))
- end
-
- output = edit_hash(user)
- user = Chef::User.from_hash(output).create
-
- ui.info("Created #{user}")
- if user.private_key
- if config[:file]
- File.open(config[:file], "w") do |f|
- f.print(user.private_key)
- end
- else
- ui.msg user.private_key
- end
- end
- end
- end
- end
-end
diff --git a/lib/chef/knife/osc_user_delete.rb b/lib/chef/knife/osc_user_delete.rb
deleted file mode 100644
index 51abc1c668..0000000000
--- a/lib/chef/knife/osc_user_delete.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-2016, 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/knife"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in the user_delete.rb.
-
-class Chef
- class Knife
- class OscUserDelete < Knife
-
- deps do
- require "chef/user"
- require "chef/json_compat"
- end
-
- banner "knife osc_user delete USER (options)"
-
- def run
- @user_name = @name_args[0]
-
- if @user_name.nil?
- show_usage
- ui.fatal("You must specify a user name")
- exit 1
- end
-
- delete_object(Chef::User, @user_name)
- end
-
- end
- end
-end
diff --git a/lib/chef/knife/osc_user_edit.rb b/lib/chef/knife/osc_user_edit.rb
deleted file mode 100644
index dad90199f5..0000000000
--- a/lib/chef/knife/osc_user_edit.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-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/knife"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_edit.rb.
-
-class Chef
- class Knife
- class OscUserEdit < Knife
-
- deps do
- require "chef/user"
- require "chef/json_compat"
- end
-
- banner "knife osc_user edit USER (options)"
-
- def run
- @user_name = @name_args[0]
-
- if @user_name.nil?
- show_usage
- ui.fatal("You must specify a user name")
- exit 1
- end
-
- original_user = Chef::User.load(@user_name).to_h
- edited_user = edit_hash(original_user)
- if original_user != edited_user
- user = Chef::User.from_hash(edited_user)
- user.update
- ui.msg("Saved #{user}.")
- else
- ui.msg("User unchanged, not saving.")
- end
- end
- end
- end
-end
diff --git a/lib/chef/knife/osc_user_list.rb b/lib/chef/knife/osc_user_list.rb
deleted file mode 100644
index 3e22bbb1c4..0000000000
--- a/lib/chef/knife/osc_user_list.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-2016, 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/knife"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_list.rb.
-
-class Chef
- class Knife
- class OscUserList < Knife
-
- deps do
- require "chef/user"
- require "chef/json_compat"
- end
-
- banner "knife osc_user list (options)"
-
- option :with_uri,
- short: "-w",
- long: "--with-uri",
- description: "Show corresponding URIs."
-
- def run
- output(format_list_for_display(Chef::User.list))
- end
- end
- end
-end
diff --git a/lib/chef/knife/osc_user_reregister.rb b/lib/chef/knife/osc_user_reregister.rb
deleted file mode 100644
index 4e4a575222..0000000000
--- a/lib/chef/knife/osc_user_reregister.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-2016, 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/knife"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_reregister.rb.
-
-class Chef
- class Knife
- class OscUserReregister < Knife
-
- deps do
- require "chef/user"
- require "chef/json_compat"
- end
-
- banner "knife osc_user reregister USER (options)"
-
- option :file,
- short: "-f FILE",
- long: "--file FILE",
- description: "Write the private key to a file."
-
- def run
- @user_name = @name_args[0]
-
- if @user_name.nil?
- show_usage
- ui.fatal("You must specify a user name")
- exit 1
- end
-
- user = Chef::User.load(@user_name).reregister
- Chef::Log.trace("Updated user data: #{user.inspect}")
- key = user.private_key
- if config[:file]
- File.open(config[:file], "w") do |f|
- f.print(key)
- end
- else
- ui.msg key
- end
- end
- end
- end
-end
diff --git a/lib/chef/knife/osc_user_show.rb b/lib/chef/knife/osc_user_show.rb
deleted file mode 100644
index 5350837ad3..0000000000
--- a/lib/chef/knife/osc_user_show.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2009-2016, 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/knife"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_show.rb.
-
-class Chef
- class Knife
- class OscUserShow < Knife
-
- include Knife::Core::MultiAttributeReturnOption
-
- deps do
- require "chef/user"
- require "chef/json_compat"
- end
-
- banner "knife osc_user show USER (options)"
-
- def run
- @user_name = @name_args[0]
-
- if @user_name.nil?
- show_usage
- ui.fatal("You must specify a user name")
- exit 1
- end
-
- user = Chef::User.load(@user_name)
- output(format_for_display(user))
- end
- end
- end
-end
diff --git a/lib/chef/knife/raw.rb b/lib/chef/knife/raw.rb
index 5658420c3e..a544dcbfdd 100644
--- a/lib/chef/knife/raw.rb
+++ b/lib/chef/knife/raw.rb
@@ -20,7 +20,7 @@ require "chef/http"
class Chef
class Knife
class Raw < Chef::Knife
- banner "knife raw REQUEST_PATH"
+ banner "knife raw REQUEST_PATH (options)"
deps do
require "chef/json_compat"
diff --git a/lib/chef/knife/role_env_run_list_clear.rb b/lib/chef/knife/role_env_run_list_clear.rb
index d9dc96c87d..ecc41347eb 100644
--- a/lib/chef/knife/role_env_run_list_clear.rb
+++ b/lib/chef/knife/role_env_run_list_clear.rb
@@ -28,7 +28,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife role env_run_list clear [ROLE] [ENVIRONMENT]"
+ banner "knife role env_run_list clear [ROLE] [ENVIRONMENT] (options)"
def clear_env_run_list(role, environment)
nlist = []
role.env_run_lists_add(environment => nlist)
diff --git a/lib/chef/knife/role_env_run_list_remove.rb b/lib/chef/knife/role_env_run_list_remove.rb
index f31f40b58a..9b627a00fc 100644
--- a/lib/chef/knife/role_env_run_list_remove.rb
+++ b/lib/chef/knife/role_env_run_list_remove.rb
@@ -27,7 +27,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife role env_run_list remove [ROLE] [ENVIRONMENT] [ENTRIES]"
+ banner "knife role env_run_list remove [ROLE] [ENVIRONMENT] [ENTRIES] (options)"
def remove_from_env_run_list(role, environment, item_to_remove)
nlist = []
diff --git a/lib/chef/knife/role_env_run_list_replace.rb b/lib/chef/knife/role_env_run_list_replace.rb
index e4b6179b65..f4e4dfec66 100644
--- a/lib/chef/knife/role_env_run_list_replace.rb
+++ b/lib/chef/knife/role_env_run_list_replace.rb
@@ -28,7 +28,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife role env_run_list replace [ROLE] [ENVIRONMENT] [OLD_ENTRY] [NEW_ENTRY] "
+ banner "knife role env_run_list replace [ROLE] [ENVIRONMENT] [OLD_ENTRY] [NEW_ENTRY] (options)"
def replace_in_env_run_list(role, environment, old_entry, new_entry)
nlist = []
diff --git a/lib/chef/knife/role_env_run_list_set.rb b/lib/chef/knife/role_env_run_list_set.rb
index f53616e151..fd8afd6652 100644
--- a/lib/chef/knife/role_env_run_list_set.rb
+++ b/lib/chef/knife/role_env_run_list_set.rb
@@ -28,7 +28,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife role env_run_list set [ROLE] [ENVIRONMENT] [ENTRIES]"
+ banner "knife role env_run_list set [ROLE] [ENVIRONMENT] [ENTRIES] (optionss)"
# Clears out any existing env_run_list_items and sets them to the
# specified entries
diff --git a/lib/chef/knife/role_run_list_clear.rb b/lib/chef/knife/role_run_list_clear.rb
index 81678d39ef..a3fde43875 100644
--- a/lib/chef/knife/role_run_list_clear.rb
+++ b/lib/chef/knife/role_run_list_clear.rb
@@ -28,7 +28,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife role run_list clear [ROLE]"
+ banner "knife role run_list clear [ROLE] (options)"
def clear_env_run_list(role, environment)
nlist = []
role.env_run_lists_add(environment => nlist)
diff --git a/lib/chef/knife/role_run_list_remove.rb b/lib/chef/knife/role_run_list_remove.rb
index 8aaf408a61..39e935605e 100644
--- a/lib/chef/knife/role_run_list_remove.rb
+++ b/lib/chef/knife/role_run_list_remove.rb
@@ -26,7 +26,7 @@ class Chef
require "chef/role"
end
- banner "knife role run_list remove [ROLE] [ENTRY]"
+ banner "knife role run_list remove [ROLE] [ENTRY] (options)"
def remove_from_env_run_list(role, environment, item_to_remove)
nlist = []
diff --git a/lib/chef/knife/role_run_list_replace.rb b/lib/chef/knife/role_run_list_replace.rb
index 64b5790d9d..bb93661548 100644
--- a/lib/chef/knife/role_run_list_replace.rb
+++ b/lib/chef/knife/role_run_list_replace.rb
@@ -28,7 +28,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife role run_list replace [ROLE] [OLD_ENTRY] [NEW_ENTRY] "
+ banner "knife role run_list replace [ROLE] [OLD_ENTRY] [NEW_ENTRY] (options)"
def replace_in_env_run_list(role, environment, old_entry, new_entry)
nlist = []
diff --git a/lib/chef/knife/role_run_list_set.rb b/lib/chef/knife/role_run_list_set.rb
index 87ba3efb1f..d424bad7e6 100644
--- a/lib/chef/knife/role_run_list_set.rb
+++ b/lib/chef/knife/role_run_list_set.rb
@@ -27,7 +27,7 @@ class Chef
require "chef/role"
end
- banner "knife role run_list set [ROLE] [ENTRIES]"
+ banner "knife role run_list set [ROLE] [ENTRIES] (options)"
# Clears out any existing env_run_list_items and sets them to the
# specified entries
diff --git a/lib/chef/knife/show.rb b/lib/chef/knife/show.rb
index e31a2c1b0c..10a1d521e3 100644
--- a/lib/chef/knife/show.rb
+++ b/lib/chef/knife/show.rb
@@ -19,7 +19,7 @@ require "chef/chef_fs/knife"
class Chef
class Knife
class Show < Chef::ChefFS::Knife
- banner "knife show [PATTERN1 ... PATTERNn]"
+ banner "knife show [PATTERN1 ... PATTERNn] (options)"
category "path-based"
diff --git a/lib/chef/knife/status.rb b/lib/chef/knife/status.rb
index 18bf987aa3..471c47b9f9 100644
--- a/lib/chef/knife/status.rb
+++ b/lib/chef/knife/status.rb
@@ -41,11 +41,6 @@ class Chef
long: "--sort-reverse",
description: "Sort the status list by last run time descending"
- option :hide_healthy,
- short: "-H",
- long: "--hide-healthy",
- description: "Hide nodes that have run chef in the last hour. [DEPRECATED] Use --hide-by-mins MINS instead"
-
option :hide_by_mins,
long: "--hide-by-mins MINS",
description: "Hide nodes that have run chef in the last MINS minutes"
@@ -71,14 +66,6 @@ class Chef
append_to_query(@name_args[0]) if @name_args[0]
append_to_query("chef_environment:#{config[:environment]}") if config[:environment]
- if config[:hide_healthy]
- ui.warn("-H / --hide-healthy is deprecated and will be removed in Chef 15. Use --hide-by-mins MINS instead")
- time = Time.now.to_i
- # AND NOT is not valid lucene syntax, so don't use append_to_query
- @query << " " unless @query.empty?
- @query << "NOT ohai_time:[#{(time - 60 * 60)} TO #{time}]"
- end
-
if config[:hide_by_mins]
hidemins = config[:hide_by_mins].to_i
time = Time.now.to_i
diff --git a/lib/chef/knife/upload.rb b/lib/chef/knife/upload.rb
index 9b651ae867..25dcd81004 100644
--- a/lib/chef/knife/upload.rb
+++ b/lib/chef/knife/upload.rb
@@ -19,7 +19,7 @@ require "chef/chef_fs/knife"
class Chef
class Knife
class Upload < Chef::ChefFS::Knife
- banner "knife upload PATTERNS"
+ banner "knife upload PATTERNS (options)"
category "path-based"
diff --git a/lib/chef/knife/user_create.rb b/lib/chef/knife/user_create.rb
index 3553e4db44..6a4a123ad8 100644
--- a/lib/chef/knife/user_create.rb
+++ b/lib/chef/knife/user_create.rb
@@ -18,7 +18,6 @@
#
require "chef/knife"
-require "chef/knife/osc_user_create"
class Chef
class Knife
@@ -45,18 +44,6 @@ class Chef
description: "API V1 (Chef Server 12.1+) only. Prevent server from generating a default key pair for you. Cannot be passed with --user-key.",
boolean: true
- option :admin,
- short: "-a",
- long: "--admin",
- description: "DEPRECATED: Open Source Chef 11 only. Create the user as an admin.",
- boolean: true
-
- option :user_password,
- short: "-p PASSWORD",
- long: "--password PASSWORD",
- description: "DEPRECATED: Open Source Chef 11 only. Password for newly created user.",
- default: ""
-
banner "knife user create USERNAME DISPLAY_NAME FIRST_NAME LAST_NAME EMAIL PASSWORD (options)"
def user
@@ -67,82 +54,50 @@ class Chef
Chef::UserV1.from_hash(hash).create
end
- def osc_11_warning
- <<~EOF
- IF YOU ARE USING CHEF SERVER 12+, PLEASE FOLLOW THE INSTRUCTIONS UNDER knife user create --help.
- You only passed a single argument to knife user create.
- For backwards compatibility, when only a single argument is passed,
- knife user create assumes you want Open Source 11 Server user creation.
- knife user create for Open Source 11 Server is being deprecated.
- Open Source 11 Server user commands now live under the knife osc_user namespace.
- For backwards compatibility, we will forward this request to knife osc_user create.
- If you are using an Open Source 11 Server, please use that command to avoid this warning.
- NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
- in Chef 15 which will be released April 2019.
-EOF
- end
-
- def run_osc_11_user_create
- # run osc_user_create with our input
- ARGV.delete("user")
- ARGV.unshift("osc_user")
- Chef::Knife.run(ARGV, Chef::Application::Knife.options)
- end
-
def run
- # DEPRECATION NOTE
- # Remove this if statement and corrosponding code post OSC 11 support.
- #
- # If only 1 arg is passed, assume OSC 11 case.
- if @name_args.length == 1
- ui.warn(osc_11_warning)
- run_osc_11_user_create
- else # EC / CS 12 user create
+ test_mandatory_field(@name_args[0], "username")
+ user.username @name_args[0]
- test_mandatory_field(@name_args[0], "username")
- user.username @name_args[0]
+ test_mandatory_field(@name_args[1], "display name")
+ user.display_name @name_args[1]
- test_mandatory_field(@name_args[1], "display name")
- user.display_name @name_args[1]
+ test_mandatory_field(@name_args[2], "first name")
+ user.first_name @name_args[2]
- test_mandatory_field(@name_args[2], "first name")
- user.first_name @name_args[2]
+ test_mandatory_field(@name_args[3], "last name")
+ user.last_name @name_args[3]
- test_mandatory_field(@name_args[3], "last name")
- user.last_name @name_args[3]
+ test_mandatory_field(@name_args[4], "email")
+ user.email @name_args[4]
- test_mandatory_field(@name_args[4], "email")
- user.email @name_args[4]
+ test_mandatory_field(@name_args[5], "password")
+ user.password @name_args[5]
- test_mandatory_field(@name_args[5], "password")
- user.password @name_args[5]
+ if config[:user_key] && config[:prevent_keygen]
+ show_usage
+ ui.fatal("You cannot pass --user-key and --prevent-keygen")
+ exit 1
+ end
- if config[:user_key] && config[:prevent_keygen]
- show_usage
- ui.fatal("You cannot pass --user-key and --prevent-keygen")
- exit 1
- end
+ if !config[:prevent_keygen] && !config[:user_key]
+ user.create_key(true)
+ end
- if !config[:prevent_keygen] && !config[:user_key]
- user.create_key(true)
- end
+ if config[:user_key]
+ user.public_key File.read(File.expand_path(config[:user_key]))
+ end
- if config[:user_key]
- user.public_key File.read(File.expand_path(config[:user_key]))
- end
+ output = edit_hash(user)
+ final_user = create_user_from_hash(output)
- output = edit_hash(user)
- final_user = create_user_from_hash(output)
-
- ui.info("Created #{user}")
- if final_user.private_key
- if config[:file]
- File.open(config[:file], "w") do |f|
- f.print(final_user.private_key)
- end
- else
- ui.msg final_user.private_key
+ ui.info("Created #{user}")
+ if final_user.private_key
+ if config[:file]
+ File.open(config[:file], "w") do |f|
+ f.print(final_user.private_key)
end
+ else
+ ui.msg final_user.private_key
end
end
end
diff --git a/lib/chef/knife/user_delete.rb b/lib/chef/knife/user_delete.rb
index 38122975c7..2638d2cce3 100644
--- a/lib/chef/knife/user_delete.rb
+++ b/lib/chef/knife/user_delete.rb
@@ -28,42 +28,6 @@ class Chef
banner "knife user delete USER (options)"
- def osc_11_warning
- <<~EOF
- The Chef Server you are using does not support the username field.
- This means it is an Open Source 11 Server.
- knife user delete for Open Source 11 Server is being deprecated.
- Open Source 11 Server user commands now live under the knife osc_user namespace.
- For backwards compatibility, we will forward this request to knife osc_user delete.
- If you are using an Open Source 11 Server, please use that command to avoid this warning.
- NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
- in Chef 15 which will be released April 2019.
-EOF
- end
-
- def run_osc_11_user_delete
- # run osc_user_delete with our input
- ARGV.delete("user")
- ARGV.unshift("osc_user")
- Chef::Knife.run(ARGV, Chef::Application::Knife.options)
- end
-
- # DEPRECATION NOTE
- # Delete this override method after OSC 11 support is dropped
- def delete_object(user_name)
- confirm("Do you really want to delete #{user_name}")
-
- if Kernel.block_given?
- object = block.call
- else
- object = Chef::UserV1.load(user_name)
- object.destroy
- end
-
- output(format_for_display(object)) if config[:print_after]
- msg("Deleted #{user_name}")
- end
-
def run
@user_name = @name_args[0]
@@ -73,23 +37,7 @@ EOF
exit 1
end
- # DEPRECATION NOTE
- #
- # Below is modification of Chef::Knife.delete_object to detect OSC 11 server.
- # When OSC 11 is deprecated, simply delete all this and go back to:
- #
- # delete_object(Chef::UserV1, @user_name)
- #
- # Also delete our override of delete_object above
- object = Chef::UserV1.load(@user_name)
-
- # OSC 11 case
- if object.username.nil?
- ui.warn(osc_11_warning)
- run_osc_11_user_delete
- else # proceed with EC / CS delete
- delete_object(@user_name)
- end
+ delete_object(Chef::UserV1, @user_name)
end
end
end
diff --git a/lib/chef/knife/user_edit.rb b/lib/chef/knife/user_edit.rb
index eb6d74c470..a039525001 100644
--- a/lib/chef/knife/user_edit.rb
+++ b/lib/chef/knife/user_edit.rb
@@ -28,26 +28,6 @@ class Chef
banner "knife user edit USER (options)"
- def osc_11_warning
- <<~EOF
- The Chef Server you are using does not support the username field.
- This means it is an Open Source 11 Server.
- knife user edit for Open Source 11 Server is being deprecated.
- Open Source 11 Server user commands now live under the knife oc_user namespace.
- For backwards compatibility, we will forward this request to knife osc_user edit.
- If you are using an Open Source 11 Server, please use that command to avoid this warning.
- NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
- in Chef 15 which will be released April 2019.
-EOF
- end
-
- def run_osc_11_user_edit
- # run osc_user_create with our input
- ARGV.delete("user")
- ARGV.unshift("osc_user")
- Chef::Knife.run(ARGV, Chef::Application::Knife.options)
- end
-
def run
@user_name = @name_args[0]
@@ -57,24 +37,14 @@ EOF
exit 1
end
- original_user = Chef::UserV1.load(@user_name).to_h
- # DEPRECATION NOTE
- # Remove this if statement and corrosponding code post OSC 11 support.
- #
- # if username is nil, we are in the OSC 11 case,
- # forward to deprecated command
- if original_user["username"].nil?
- ui.warn(osc_11_warning)
- run_osc_11_user_edit
- else # EC / CS 12 user create
- edited_user = edit_hash(original_user)
- if original_user != edited_user
- user = Chef::UserV1.from_hash(edited_user)
- user.update
- ui.msg("Saved #{user}.")
- else
- ui.msg("User unchanged, not saving.")
- end
+ original_user = Chef::UserV1.load(@user_name).to_hash
+ edited_user = edit_hash(original_user)
+ if original_user != edited_user
+ user = Chef::UserV1.from_hash(edited_user)
+ user.update
+ ui.msg("Saved #{user}.")
+ else
+ ui.msg("User unchanged, not saving.")
end
end
end
diff --git a/lib/chef/knife/user_list.rb b/lib/chef/knife/user_list.rb
index c1c0fa5109..31758ce117 100644
--- a/lib/chef/knife/user_list.rb
+++ b/lib/chef/knife/user_list.rb
@@ -18,8 +18,6 @@
require "chef/knife"
-# NOTE: only knife user command that is backwards compatible with OSC 11,
-# so no deprecation warnings are necessary.
class Chef
class Knife
class UserList < Knife
diff --git a/lib/chef/knife/user_reregister.rb b/lib/chef/knife/user_reregister.rb
index 97840cadf3..3c63c32f29 100644
--- a/lib/chef/knife/user_reregister.rb
+++ b/lib/chef/knife/user_reregister.rb
@@ -28,26 +28,6 @@ class Chef
banner "knife user reregister USER (options)"
- def osc_11_warning
- <<~EOF
- The Chef Server you are using does not support the username field.
- This means it is an Open Source 11 Server.
- knife user reregister for Open Source 11 Server is being deprecated.
- Open Source 11 Server user commands now live under the knife osc_user namespace.
- For backwards compatibility, we will forward this request to knife osc_user reregister.
- If you are using an Open Source 11 Server, please use that command to avoid this warning.
- NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
- in Chef 15 which will be released April 2019.
-EOF
- end
-
- def run_osc_11_user_reregister
- # run osc_user_edit with our input
- ARGV.delete("user")
- ARGV.unshift("osc_user")
- Chef::Knife.run(ARGV, Chef::Application::Knife.options)
- end
-
option :file,
short: "-f FILE",
long: "--file FILE",
@@ -63,26 +43,15 @@ EOF
end
user = Chef::UserV1.load(@user_name)
-
- # DEPRECATION NOTE
- # Remove this if statement and corrosponding code post OSC 11 support.
- #
- # if username is nil, we are in the OSC 11 case,
- # forward to deprecated command
- if user.username.nil?
- ui.warn(osc_11_warning)
- run_osc_11_user_reregister
- else # EC / CS 12 case
- user.reregister
- Chef::Log.trace("Updated user data: #{user.inspect}")
- key = user.private_key
- if config[:file]
- File.open(config[:file], "w") do |f|
- f.print(key)
- end
- else
- ui.msg key
+ user.reregister
+ Chef::Log.trace("Updated user data: #{user.inspect}")
+ key = user.private_key
+ if config[:file]
+ File.open(config[:file], "w") do |f|
+ f.print(key)
end
+ else
+ ui.msg key
end
end
end
diff --git a/lib/chef/knife/user_show.rb b/lib/chef/knife/user_show.rb
index 544d420346..a27549aea7 100644
--- a/lib/chef/knife/user_show.rb
+++ b/lib/chef/knife/user_show.rb
@@ -30,26 +30,6 @@ class Chef
banner "knife user show USER (options)"
- def osc_11_warning
- <<~EOF
- The Chef Server you are using does not support the username field.
- This means it is an Open Source 11 Server.
- knife user show for Open Source 11 Server is being deprecated.
- Open Source 11 Server user commands now live under the knife osc_user namespace.
- For backwards compatibility, we will forward this request to knife osc_user show.
- If you are using an Open Source 11 Server, please use that command to avoid this warning.
- NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
- in Chef 15 which will be released April 2019.
-EOF
- end
-
- def run_osc_11_user_show
- # run osc_user_edit with our input
- ARGV.delete("user")
- ARGV.unshift("osc_user")
- Chef::Knife.run(ARGV, Chef::Application::Knife.options)
- end
-
def run
@user_name = @name_args[0]
@@ -60,18 +40,7 @@ EOF
end
user = Chef::UserV1.load(@user_name)
-
- # DEPRECATION NOTE
- # Remove this if statement and corrosponding code post OSC 11 support.
- #
- # if username is nil, we are in the OSC 11 case,
- # forward to deprecated command
- if user.username.nil?
- ui.warn(osc_11_warning)
- run_osc_11_user_show
- else
- output(format_for_display(user))
- end
+ output(format_for_display(user))
end
end
diff --git a/lib/chef/knife/xargs.rb b/lib/chef/knife/xargs.rb
index a5ced3eea8..ae5851f465 100644
--- a/lib/chef/knife/xargs.rb
+++ b/lib/chef/knife/xargs.rb
@@ -19,7 +19,7 @@ require "chef/chef_fs/knife"
class Chef
class Knife
class Xargs < Chef::ChefFS::Knife
- banner "knife xargs [COMMAND]"
+ banner "knife xargs [COMMAND] (options)"
category "path-based"
diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb
index 05b625dd02..c5731b65a0 100644
--- a/lib/chef/node/attribute.rb
+++ b/lib/chef/node/attribute.rb
@@ -78,113 +78,117 @@ class Chef
:@force_override,
].freeze
- [:all?,
- :any?,
- :assoc,
- :chunk,
- :collect,
- :collect_concat,
- :compare_by_identity,
- :compare_by_identity?,
- :count,
- :cycle,
- :detect,
- :drop,
- :drop_while,
- :each,
- :each_cons,
- :each_entry,
- :each_key,
- :each_pair,
- :each_slice,
- :each_value,
- :each_with_index,
- :each_with_object,
- :empty?,
- :entries,
- :except,
- :fetch,
- :find,
- :find_all,
- :find_index,
- :first,
- :flat_map,
- :flatten,
- :grep,
- :group_by,
- :has_value?,
- :include?,
- :index,
- :inject,
- :invert,
- :key,
- :keys,
- :length,
- :map,
- :max,
- :max_by,
- :merge,
- :min,
- :min_by,
- :minmax,
- :minmax_by,
- :none?,
- :one?,
- :partition,
- :rassoc,
- :reduce,
- :reject,
- :reverse_each,
- :select,
- :size,
- :slice_before,
- :sort,
- :sort_by,
- :store,
- :symbolize_keys,
- :take,
- :take_while,
- :to_a,
- :to_h,
- :to_hash,
- :to_set,
- :value?,
- :values,
- :values_at,
- :zip].each do |delegated_method|
- define_method(delegated_method) do |*args, &block|
- merged_attributes.send(delegated_method, *args, &block)
- end
- end
-
- # return the cookbook level default attribute component
+ ENUM_METHODS = [
+ :all?,
+ :any?,
+ :assoc,
+ :chunk,
+ :collect,
+ :collect_concat,
+ :compare_by_identity,
+ :compare_by_identity?,
+ :count,
+ :cycle,
+ :detect,
+ :drop,
+ :drop_while,
+ :each,
+ :each_cons,
+ :each_entry,
+ :each_key,
+ :each_pair,
+ :each_slice,
+ :each_value,
+ :each_with_index,
+ :each_with_object,
+ :empty?,
+ :entries,
+ :except,
+ :fetch,
+ :find,
+ :find_all,
+ :find_index,
+ :first,
+ :flat_map,
+ :flatten,
+ :grep,
+ :group_by,
+ :has_value?,
+ :include?,
+ :index,
+ :inject,
+ :invert,
+ :key,
+ :keys,
+ :length,
+ :map,
+ :max,
+ :max_by,
+ :merge,
+ :min,
+ :min_by,
+ :minmax,
+ :minmax_by,
+ :none?,
+ :one?,
+ :partition,
+ :rassoc,
+ :reduce,
+ :reject,
+ :reverse_each,
+ :select,
+ :size,
+ :slice_before,
+ :sort,
+ :sort_by,
+ :store,
+ :symbolize_keys,
+ :take,
+ :take_while,
+ :to_a,
+ :to_h,
+ :to_hash,
+ :to_set,
+ :value?,
+ :values,
+ :values_at,
+ :zip,
+ ].freeze
+
+ ENUM_METHODS.each do |delegated_method|
+ define_method(delegated_method) do |*args, &block|
+ merged_attributes.send(delegated_method, *args, &block)
+ end
+ end
+
+ # return the cookbook level default attribute component
attr_reader :default
- # return the role level default attribute component
+ # return the role level default attribute component
attr_reader :role_default
- # return the environment level default attribute component
+ # return the environment level default attribute component
attr_reader :env_default
- # return the force_default level attribute component
+ # return the force_default level attribute component
attr_reader :force_default
- # return the "normal" level attribute component
+ # return the "normal" level attribute component
attr_reader :normal
- # return the cookbook level override attribute component
+ # return the cookbook level override attribute component
attr_reader :override
- # return the role level override attribute component
+ # return the role level override attribute component
attr_reader :role_override
- # return the enviroment level override attribute component
+ # return the enviroment level override attribute component
attr_reader :env_override
- # return the force override level attribute component
+ # return the force override level attribute component
attr_reader :force_override
- # return the automatic level attribute component
+ # return the automatic level attribute component
attr_reader :automatic
def initialize(normal, default, override, automatic, node = nil)
@@ -205,15 +209,15 @@ class Chef
super(nil, self, node, :merged)
end
- # Debug what's going on with an attribute. +args+ is a path spec to the
- # attribute you're interested in. For example, to debug where the value
- # of `node[:network][:default_interface]` is coming from, use:
- # debug_value(:network, :default_interface).
- # The return value is an Array of Arrays. The Arrays
- # are pairs of `["precedence_level", value]`, where precedence level is
- # the component, such as role default, normal, etc. and value is the
- # attribute value set at that precedence level. If there is no value at
- # that precedence level, +value+ will be the symbol +:not_present+.
+ # Debug what's going on with an attribute. +args+ is a path spec to the
+ # attribute you're interested in. For example, to debug where the value
+ # of `node[:network][:default_interface]` is coming from, use:
+ # debug_value(:network, :default_interface).
+ # The return value is an Array of Arrays. The Arrays
+ # are pairs of `["precedence_level", value]`, where precedence level is
+ # the component, such as role default, normal, etc. and value is the
+ # attribute value set at that precedence level. If there is no value at
+ # that precedence level, +value+ will be the symbol +:not_present+.
def debug_value(*args)
COMPONENTS.map do |component|
value =
@@ -226,49 +230,49 @@ class Chef
end
end
- # Set the cookbook level default attribute component to +new_data+.
+ # Set the cookbook level default attribute component to +new_data+.
def default=(new_data)
reset
@default = VividMash.new(new_data, self, __node__, :default)
end
- # Set the role level default attribute component to +new_data+
+ # Set the role level default attribute component to +new_data+
def role_default=(new_data)
reset
@role_default = VividMash.new(new_data, self, __node__, :role_default)
end
- # Set the environment level default attribute component to +new_data+
+ # Set the environment level default attribute component to +new_data+
def env_default=(new_data)
reset
@env_default = VividMash.new(new_data, self, __node__, :env_default)
end
- # Set the force_default (+default!+) level attributes to +new_data+
+ # Set the force_default (+default!+) level attributes to +new_data+
def force_default=(new_data)
reset
@force_default = VividMash.new(new_data, self, __node__, :force_default)
end
- # Set the normal level attribute component to +new_data+
+ # Set the normal level attribute component to +new_data+
def normal=(new_data)
reset
@normal = VividMash.new(new_data, self, __node__, :normal)
end
- # Set the cookbook level override attribute component to +new_data+
+ # Set the cookbook level override attribute component to +new_data+
def override=(new_data)
reset
@override = VividMash.new(new_data, self, __node__, :override)
end
- # Set the role level override attribute component to +new_data+
+ # Set the role level override attribute component to +new_data+
def role_override=(new_data)
reset
@role_override = VividMash.new(new_data, self, __node__, :role_override)
end
- # Set the environment level override attribute component to +new_data+
+ # Set the environment level override attribute component to +new_data+
def env_override=(new_data)
reset
@env_override = VividMash.new(new_data, self, __node__, :env_override)
@@ -284,11 +288,11 @@ class Chef
@automatic = VividMash.new(new_data, self, __node__, :automatic)
end
- #
- # Deleting attributes
- #
+ #
+ # Deleting attributes
+ #
- # clears attributes from all precedence levels
+ # clears attributes from all precedence levels
def rm(*args)
with_deep_merged_return_value(self, *args) do
rm_default(*args)
@@ -297,11 +301,11 @@ class Chef
end
end
- # clears attributes from all default precedence levels
- #
- # similar to: force_default!['foo']['bar'].delete('baz')
- # - does not autovivify
- # - does not trainwreck if interior keys do not exist
+ # clears attributes from all default precedence levels
+ #
+ # similar to: force_default!['foo']['bar'].delete('baz')
+ # - does not autovivify
+ # - does not trainwreck if interior keys do not exist
def rm_default(*args)
with_deep_merged_return_value(combined_default, *args) do
default.unlink(*args)
@@ -311,20 +315,20 @@ class Chef
end
end
- # clears attributes from normal precedence
- #
- # equivalent to: normal!['foo']['bar'].delete('baz')
- # - does not autovivify
- # - does not trainwreck if interior keys do not exist
+ # clears attributes from normal precedence
+ #
+ # equivalent to: normal!['foo']['bar'].delete('baz')
+ # - does not autovivify
+ # - does not trainwreck if interior keys do not exist
def rm_normal(*args)
normal.unlink(*args)
end
- # clears attributes from all override precedence levels
- #
- # equivalent to: force_override!['foo']['bar'].delete('baz')
- # - does not autovivify
- # - does not trainwreck if interior keys do not exist
+ # clears attributes from all override precedence levels
+ #
+ # equivalent to: force_override!['foo']['bar'].delete('baz')
+ # - does not autovivify
+ # - does not trainwreck if interior keys do not exist
def rm_override(*args)
with_deep_merged_return_value(combined_override, *args) do
override.unlink(*args)
@@ -344,37 +348,37 @@ class Chef
private :with_deep_merged_return_value
- #
- # Replacing attributes without merging
- #
+ #
+ # Replacing attributes without merging
+ #
- # sets default attributes without merging
- #
- # - this API autovivifies (and cannot trainwreck)
+ # sets default attributes without merging
+ #
+ # - this API autovivifies (and cannot trainwreck)
def default!(*args)
return Decorator::Unchain.new(self, :default!) unless args.length > 0
write(:default, *args)
end
- # sets normal attributes without merging
- #
- # - this API autovivifies (and cannot trainwreck)
+ # sets normal attributes without merging
+ #
+ # - this API autovivifies (and cannot trainwreck)
def normal!(*args)
return Decorator::Unchain.new(self, :normal!) unless args.length > 0
write(:normal, *args)
end
- # sets override attributes without merging
- #
- # - this API autovivifies (and cannot trainwreck)
+ # sets override attributes without merging
+ #
+ # - this API autovivifies (and cannot trainwreck)
def override!(*args)
return Decorator::Unchain.new(self, :override!) unless args.length > 0
write(:override, *args)
end
- # clears from all default precedence levels and then sets force_default
- #
- # - this API autovivifies (and cannot trainwreck)
+ # clears from all default precedence levels and then sets force_default
+ #
+ # - this API autovivifies (and cannot trainwreck)
def force_default!(*args)
return Decorator::Unchain.new(self, :force_default!) unless args.length > 0
value = args.pop
@@ -382,7 +386,7 @@ class Chef
write(:force_default, *args, value)
end
- # clears from all override precedence levels and then sets force_override
+ # clears from all override precedence levels and then sets force_override
def force_override!(*args)
return Decorator::Unchain.new(self, :force_override!) unless args.length > 0
value = args.pop
@@ -390,24 +394,25 @@ class Chef
write(:force_override, *args, value)
end
- #
- # Accessing merged attributes.
- #
- # Note that merged_attributes('foo', 'bar', 'baz') can be called to compute only the
- # deep merge of node['foo']['bar']['baz'], but in practice we currently always compute
- # all of node['foo'] even if the user only requires node['foo']['bar']['baz'].
- #
-
+ #
+ # Accessing merged attributes.
+ #
+ # Note that merged_attributes('foo', 'bar', 'baz') can be called to compute only the
+ # deep merge of node['foo']['bar']['baz'], but in practice we currently always compute
+ # all of node['foo'] even if the user only requires node['foo']['bar']['baz'].
+ #
def merged_attributes(*path)
merge_all(path)
end
def combined_override(*path)
- merge_overrides(path)
+ ret = merge_overrides(path)
+ ret == NIL ? nil : ret
end
def combined_default(*path)
- merge_defaults(path)
+ ret = merge_defaults(path)
+ ret == NIL ? nil : ret
end
def normal_unless(*args)
@@ -430,7 +435,8 @@ class Chef
instance_variable_get(component_ivar).key?(key)
end
end
- # method-style access to attributes (has to come after the prepended ImmutablizeHash)
+
+ # method-style access to attributes (has to come after the prepended ImmutablizeHash)
def read(*path)
merged_attributes.read(*path)
@@ -479,16 +485,16 @@ class Chef
private
- # Helper method for merge_all/merge_defaults/merge_overrides.
- #
- # apply_path(thing, [ "foo", "bar", "baz" ]) = thing["foo"]["bar"]["baz"]
- #
- # The path value can be nil in which case the whole component is returned.
- #
- # It returns nil (does not raise an exception) if it walks off the end of an Mash/Hash/Array, it does not
- # raise any TypeError if it attempts to apply a hash key to an Integer/String/TrueClass, and just returns
- # nil in that case.
- #
+ # Helper method for merge_all/merge_defaults/merge_overrides.
+ #
+ # apply_path(thing, [ "foo", "bar", "baz" ]) = thing["foo"]["bar"]["baz"]
+ #
+ # The path value can be nil in which case the whole component is returned.
+ #
+ # It returns nil (does not raise an exception) if it walks off the end of an Mash/Hash/Array, it does not
+ # raise any TypeError if it attempts to apply a hash key to an Integer/String/TrueClass, and just returns
+ # nil in that case.
+ #
def apply_path(component, path)
path ||= []
path.inject(component) do |val, path_arg|
@@ -501,28 +507,28 @@ class Chef
# Hash-like thing (must check has_key? first to protect against Autovivification)
val[path_arg]
else
- nil
+ NIL
end
else
- nil
+ NIL
end
end
end
- # For elements like Fixnums, true, nil...
+ # For elements like Fixnums, true, nil...
def safe_dup(e)
e.dup
rescue TypeError
e
end
- # Deep merge all attribute levels using hash-only merging between different precidence
- # levels (so override arrays completely replace arrays set at any default level).
- #
- # The path allows for selectively deep-merging a subtree of the node object.
- #
- # @param path [Array] Array of args to method chain to descend into the node object
- # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
+ # Deep merge all attribute levels using hash-only merging between different precidence
+ # levels (so override arrays completely replace arrays set at any default level).
+ #
+ # The path allows for selectively deep-merging a subtree of the node object.
+ #
+ # @param path [Array] Array of args to method chain to descend into the node object
+ # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
def merge_all(path)
components = [
merge_defaults(path),
@@ -537,35 +543,35 @@ class Chef
ret == NIL ? nil : ret
end
- # Deep merge the default attribute levels with array merging.
- #
- # The path allows for selectively deep-merging a subtree of the node object.
- #
- # @param path [Array] Array of args to method chain to descend into the node object
- # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
+ # Deep merge the default attribute levels with array merging.
+ #
+ # The path allows for selectively deep-merging a subtree of the node object.
+ #
+ # @param path [Array] Array of args to method chain to descend into the node object
+ # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
def merge_defaults(path)
ret = DEFAULT_COMPONENTS.inject(NIL) do |merged, component_ivar|
component_value = apply_path(instance_variable_get(component_ivar), path)
deep_merge!(merged, component_value)
end
- ret == NIL ? nil : ret
+ ret
end
- # Deep merge the override attribute levels with array merging.
- #
- # The path allows for selectively deep-merging a subtree of the node object.
- #
- # @param path [Array] Array of args to method chain to descend into the node object
- # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
+ # Deep merge the override attribute levels with array merging.
+ #
+ # The path allows for selectively deep-merging a subtree of the node object.
+ #
+ # @param path [Array] Array of args to method chain to descend into the node object
+ # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
def merge_overrides(path)
ret = OVERRIDE_COMPONENTS.inject(NIL) do |merged, component_ivar|
component_value = apply_path(instance_variable_get(component_ivar), path)
deep_merge!(merged, component_value)
end
- ret == NIL ? nil : ret
+ ret
end
- # needed for __path__
+ # needed for __path__
def convert_key(key)
key.kind_of?(Symbol) ? key.to_s : key
end
@@ -592,8 +598,8 @@ class Chef
elsif merge_onto.kind_of?(Array) && merge_with.kind_of?(Array)
merge_onto |= merge_with
- # If merge_with is nil, don't replace merge_onto
- elsif merge_with.nil?
+ # If merge_with is NIL, don't replace merge_onto
+ elsif merge_with == NIL
merge_onto
# In all other cases, replace merge_onto with merge_with
@@ -625,8 +631,8 @@ class Chef
end
merge_onto
- # If merge_with is nil, don't replace merge_onto
- elsif merge_with.nil?
+ # If merge_with is NIL, don't replace merge_onto
+ elsif merge_with == NIL
merge_onto
# In all other cases, replace merge_onto with merge_with
diff --git a/lib/chef/node/attribute_collections.rb b/lib/chef/node/attribute_collections.rb
index f62eceb646..382ecfba91 100644
--- a/lib/chef/node/attribute_collections.rb
+++ b/lib/chef/node/attribute_collections.rb
@@ -18,6 +18,9 @@
require "chef/node/common_api"
require "chef/node/mixin/state_tracking"
+require "chef/node/mixin/immutablize_array"
+require "chef/node/mixin/immutablize_hash"
+require "chef/node/mixin/mashy_array"
class Chef
class Node
@@ -26,36 +29,9 @@ class Chef
# "root" (Chef::Node::Attribute) object, and will trigger a cache
# invalidation on that object when mutated.
class AttrArray < Array
- MUTATOR_METHODS = [
- :<<,
- :[]=,
- :clear,
- :collect!,
- :compact!,
- :default=,
- :default_proc=,
- :delete_at,
- :delete_if,
- :fill,
- :flatten!,
- :insert,
- :keep_if,
- :map!,
- :merge!,
- :pop,
- :push,
- :update,
- :reject!,
- :reverse!,
- :replace,
- :select!,
- :shift,
- :slice!,
- :sort!,
- :sort_by!,
- :uniq!,
- :unshift,
- ].freeze
+ include Chef::Node::Mixin::MashyArray
+
+ MUTATOR_METHODS = Chef::Node::Mixin::ImmutablizeArray::DISALLOWED_MUTATOR_METHODS
# For all of the methods that may mutate an Array, we override them to
# also invalidate the cached merged_attributes on the root
@@ -130,27 +106,11 @@ class Chef
# Methods that mutate a VividMash. Each of them is overridden so that it
# also invalidates the cached merged_attributes on the root Attribute
# object.
- MUTATOR_METHODS = [
- :clear,
- :delete_if,
- :keep_if,
- :merge!,
- :update,
- :reject!,
- :replace,
- :select!,
- :shift,
- ].freeze
+ MUTATOR_METHODS = Chef::Node::Mixin::ImmutablizeHash::DISALLOWED_MUTATOR_METHODS - [ :write, :write!, :unlink, :unlink! ]
# For all of the mutating methods on Mash, override them so that they
# also invalidate the cached `merged_attributes` on the root Attribute
# object.
-
- def delete(key, &block)
- send_reset_cache(__path__, key)
- super
- end
-
MUTATOR_METHODS.each do |mutator|
define_method(mutator) do |*args, &block|
send_reset_cache
@@ -158,6 +118,11 @@ class Chef
end
end
+ def delete(key, &block)
+ send_reset_cache(__path__, key)
+ super
+ end
+
def initialize(data = {})
super(data)
end
diff --git a/lib/chef/node/mixin/immutablize_array.rb b/lib/chef/node/mixin/immutablize_array.rb
index 000a088410..b5e0993cfa 100644
--- a/lib/chef/node/mixin/immutablize_array.rb
+++ b/lib/chef/node/mixin/immutablize_array.rb
@@ -159,7 +159,6 @@ class Chef
:sort_by!,
:uniq!,
:unshift,
- :update,
].freeze
# Redefine all of the methods that mutate a Hash to raise an error when called.
diff --git a/lib/chef/node/mixin/mashy_array.rb b/lib/chef/node/mixin/mashy_array.rb
new file mode 100644
index 0000000000..31506c5bbf
--- /dev/null
+++ b/lib/chef/node/mixin/mashy_array.rb
@@ -0,0 +1,68 @@
+#--
+# Copyright:: Copyright 2016-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 Node
+ module Mixin
+ # missing methods for Arrays similar to Chef::Mash methods that call
+ # convert_value correctly.
+ module MashyArray
+ def <<(obj)
+ super(convert_value(obj))
+ end
+
+ def []=(*keys, value)
+ super(*keys, convert_value(value))
+ end
+
+ def push(*objs)
+ objs = objs.map { |obj| convert_value(obj) }
+ super(*objs)
+ end
+
+ def unshift(*objs)
+ objs = objs.map { |obj| convert_value(obj) }
+ super(*objs)
+ end
+
+ def insert(index, *objs)
+ objs = objs.map { |obj| convert_value(obj) }
+ super(index, *objs)
+ end
+
+ def collect!(&block)
+ super
+ map! { |x| convert_value(x) }
+ end
+
+ def map!(&block)
+ super
+ super { |x| convert_value(x) }
+ end
+
+ def fill(*args, &block)
+ super
+ map! { |x| convert_value(x) }
+ end
+
+ def replace(obj)
+ super(convert_value(obj))
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/platform/rebooter.rb b/lib/chef/platform/rebooter.rb
index 430d175869..1551836bca 100644
--- a/lib/chef/platform/rebooter.rb
+++ b/lib/chef/platform/rebooter.rb
@@ -20,6 +20,7 @@ require "chef/dsl/reboot_pending"
require "chef/log"
require "chef/platform"
require "chef/application/exit_code"
+require "chef/mixin/shell_out"
class Chef
class Platform
diff --git a/lib/chef/policy_builder/dynamic.rb b/lib/chef/policy_builder/dynamic.rb
index 84021ea611..8ce4f25bfa 100644
--- a/lib/chef/policy_builder/dynamic.rb
+++ b/lib/chef/policy_builder/dynamic.rb
@@ -173,7 +173,7 @@ class Chef
end
def policyfile_set_in_config?
- config[:use_policyfile] || config[:policy_name] || config[:policy_group]
+ config[:policy_name] || config[:policy_group]
end
def policyfile_compat_mode_config?
diff --git a/lib/chef/property.rb b/lib/chef/property.rb
index 0d7b0f06cf..aee3080dc0 100644
--- a/lib/chef/property.rb
+++ b/lib/chef/property.rb
@@ -103,6 +103,10 @@ class Chef
# be run in the context of the instance (and able to access other
# properties) and cached. If not, the value will be frozen with Object#freeze
# to prevent users from modifying it in an instance.
+ # @option options [String] :default_description The description of the default value
+ # used in docs. Particularly useful when a default is computed or lazily eval'd.
+ # @option options [Boolean] :skip_docs This property should not be included in any
+ # documentation output
# @option options [Proc] :coerce A proc which will be called to
# transform the user input to canonical form. The value is passed in,
# and the transformed value returned as output. Lazy values will *not*
@@ -230,6 +234,15 @@ class Chef
end
#
+ # A desciption of the default value of this property.
+ #
+ # @return [String]
+ #
+ def default_description
+ options[:default_description]
+ end
+
+ #
# Whether this is part of the resource's natural identity or not.
#
# @return [Boolean]
@@ -278,6 +291,17 @@ class Chef
end
#
+ # Whether this property should be skipped for documentation purposes.
+ #
+ # Defaults to false.
+ #
+ # @return [Boolean]
+ #
+ def skip_docs?
+ options.fetch(:skip_docs, false)
+ end
+
+ #
# Whether this property is sensitive or not.
#
# Defaults to false.
@@ -295,7 +319,7 @@ class Chef
#
def validation_options
@validation_options ||= options.reject do |k, v|
- [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive, :description, :introduced, :deprecated].include?(k)
+ [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive, :description, :introduced, :deprecated, :default_description, :skip_docs].include?(k)
end
end
diff --git a/lib/chef/provider/apt_repository.rb b/lib/chef/provider/apt_repository.rb
index 2062ac5a42..45cc40508c 100644
--- a/lib/chef/provider/apt_repository.rb
+++ b/lib/chef/provider/apt_repository.rb
@@ -225,7 +225,7 @@ class Chef
#
# @return [String] the full apt-key command to run
def keyserver_install_cmd(key, keyserver)
- cmd = "apt-key adv --recv"
+ cmd = "apt-key adv --no-tty --recv"
cmd << " --keyserver-options http-proxy=#{new_resource.key_proxy}" if new_resource.key_proxy
cmd << " --keyserver "
cmd << if keyserver.start_with?("hkp://")
diff --git a/lib/chef/provider/execute.rb b/lib/chef/provider/execute.rb
index 1b97dbf464..02db7cb593 100644
--- a/lib/chef/provider/execute.rb
+++ b/lib/chef/provider/execute.rb
@@ -37,7 +37,7 @@ class Chef
def define_resource_requirements
if creates && creates_relative? && !cwd
# FIXME? move this onto the resource?
- raise Chef::Exceptions::Execute, "Please either specify a full path for the creates attribute, or specify a cwd property to the #{new_resource} resource"
+ raise Chef::Exceptions::Execute, "Please either specify a full path for the creates property, or specify a cwd property to the #{new_resource} resource"
end
end
diff --git a/lib/chef/provider/osx_profile.rb b/lib/chef/provider/osx_profile.rb
index 531d822334..7a2f8ced20 100644
--- a/lib/chef/provider/osx_profile.rb
+++ b/lib/chef/provider/osx_profile.rb
@@ -68,7 +68,7 @@ class Chef
!@new_profile_identifier.end_with?(".mobileconfig") &&
/^\w+(?:(\.| )\w+)+$/.match(@new_profile_identifier)
end
- a.failure_message RuntimeError, "when removing using the identifier attribute, it must match the profile identifier"
+ a.failure_message RuntimeError, "when removing using the identifier property, it must match the profile identifier"
else
new_profile_name = new_resource.profile_name
a.assertion do
diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb
index f245e481a3..bfb24e502d 100644
--- a/lib/chef/provider/package/apt.rb
+++ b/lib/chef/provider/package/apt.rb
@@ -44,7 +44,7 @@ class Chef
requirements.assert(:all_actions) do |a|
a.assertion { !new_resource.source }
- a.failure_message(Chef::Exceptions::Package, "apt package provider cannot handle source attribute. Use dpkg provider instead")
+ a.failure_message(Chef::Exceptions::Package, "apt package provider cannot handle source property. Use dpkg provider instead")
end
end
diff --git a/lib/chef/provider/package/chocolatey.rb b/lib/chef/provider/package/chocolatey.rb
index eb27b23408..4c35d13a07 100644
--- a/lib/chef/provider/package/chocolatey.rb
+++ b/lib/chef/provider/package/chocolatey.rb
@@ -54,7 +54,7 @@ EOS
# The check that Chocolatey is installed is in #choco_exe.
- # Chocolatey source attribute points to an alternate feed
+ # Chocolatey source property points to an alternate feed
# and not a package specific alternate source like other providers
# so we want to assert candidates exist for the alternate source
requirements.assert(:upgrade, :install) do |a|
diff --git a/lib/chef/provider/package/freebsd/pkg.rb b/lib/chef/provider/package/freebsd/pkg.rb
deleted file mode 100644
index c847ae5658..0000000000
--- a/lib/chef/provider/package/freebsd/pkg.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-#
-# Authors:: Bryan McLellan (btm@loftninjas.org)
-# Matthew Landauer (matthew@openaustralia.org)
-# Richard Manyanza (liseki@nyikacraftsmen.com)
-# Copyright:: Copyright 2009-2016, Bryan McLellan, Matthew Landauer
-# Copyright:: Copyright 2014-2016, Richard Manyanza
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/provider/package/freebsd/base"
-require "chef/util/path_helper"
-
-class Chef
- class Provider
- class Package
- module Freebsd
- class Pkg < Base
- include PortsHelper
-
- def install_package(name, version)
- unless current_resource.version
- case new_resource.source
- when /^http/, /^ftp/
- if new_resource.source =~ /\/$/
- shell_out!("pkg_add", "-r", package_name, env: { "PACKAGESITE" => new_resource.source, "LC_ALL" => nil }).status
- else
- shell_out!("pkg_add", "-r", package_name, env: { "PACKAGEROOT" => new_resource.source, "LC_ALL" => nil }).status
- end
- logger.trace("#{new_resource} installed from: #{new_resource.source}")
-
- when /^\//
- shell_out!("pkg_add", file_candidate_version_path, env: { "PKG_PATH" => new_resource.source, "LC_ALL" => nil }).status
- logger.trace("#{new_resource} installed from: #{new_resource.source}")
-
- else
- shell_out!("pkg_add", "-r", latest_link_name, env: nil).status
- end
- end
- end
-
- def remove_package(name, version)
- shell_out!("pkg_delete", "#{package_name}-#{version || current_resource.version}", env: nil).status
- end
-
- # The name of the package (without the version number) as understood by pkg_add and pkg_info.
- def package_name
- if supports_ports?
- if makefile_variable_value("PKGNAME", port_path) =~ /^(.+)-[^-]+$/
- $1
- else
- raise Chef::Exceptions::Package, "Unexpected form for PKGNAME variable in #{port_path}/Makefile"
- end
- else
- new_resource.package_name
- end
- end
-
- def latest_link_name
- makefile_variable_value("LATEST_LINK", port_path)
- end
-
- def current_installed_version
- pkg_info = shell_out!("pkg_info", "-E", "#{package_name}*", env: nil, returns: [0, 1])
- pkg_info.stdout[/^#{Regexp.escape(package_name)}-(.+)/, 1]
- end
-
- def candidate_version
- case new_resource.source
- when /^http/, /^ftp/
- repo_candidate_version
- when /^\//
- file_candidate_version
- else
- ports_candidate_version
- end
- end
-
- def file_candidate_version_path
- Dir[Chef::Util::PathHelper.escape_glob_dir("#{new_resource.source}/#{current_resource.package_name}") + "*"][-1].to_s
- end
-
- def file_candidate_version
- file_candidate_version_path.split(/-/).last.split(/.tbz/).first
- end
-
- def repo_candidate_version
- "0.0.0"
- end
-
- def ports_candidate_version
- makefile_variable_value("PORTVERSION", port_path)
- end
-
- def port_path
- port_dir new_resource.package_name
- end
-
- end
- end
- end
- end
-end
diff --git a/lib/chef/provider/package/freebsd/port.rb b/lib/chef/provider/package/freebsd/port.rb
index 7a46bbaf97..e3174f7d8d 100644
--- a/lib/chef/provider/package/freebsd/port.rb
+++ b/lib/chef/provider/package/freebsd/port.rb
@@ -34,11 +34,7 @@ class Chef
end
def current_installed_version
- pkg_info = if new_resource.supports_pkgng?
- shell_out!("pkg", "info", new_resource.package_name, env: nil, returns: [0, 70])
- else
- shell_out!("pkg_info", "-E", "#{new_resource.package_name}*", env: nil, returns: [0, 1])
- end
+ pkg_info = shell_out!("pkg", "info", new_resource.package_name, env: nil, returns: [0, 70])
pkg_info.stdout[/^#{Regexp.escape(new_resource.package_name)}-(.+)/, 1]
end
diff --git a/lib/chef/provider/package/openbsd.rb b/lib/chef/provider/package/openbsd.rb
index 3408aef944..0332423e7c 100644
--- a/lib/chef/provider/package/openbsd.rb
+++ b/lib/chef/provider/package/openbsd.rb
@@ -53,7 +53,7 @@ class Chef
# Below are incomplete/missing features for this package provider
requirements.assert(:all_actions) do |a|
a.assertion { !new_resource.source }
- a.failure_message(Chef::Exceptions::Package, "The openbsd package provider does not support the source attribute")
+ a.failure_message(Chef::Exceptions::Package, "The openbsd package provider does not support the source property")
end
requirements.assert(:all_actions) do |a|
a.assertion do
diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb
index e991e4541e..ad045c77e6 100644
--- a/lib/chef/provider/package/yum.rb
+++ b/lib/chef/provider/package/yum.rb
@@ -96,7 +96,7 @@ class Chef
name = av.name # resolve the name via the available/candidate version
- iv = python_helper.package_query(:whatinstalled, name)
+ iv = python_helper.package_query(:whatinstalled, av.name_with_arch)
method = "install"
diff --git a/lib/chef/provider/package/yum/version.rb b/lib/chef/provider/package/yum/version.rb
index b19f52fe09..6ff59009f9 100644
--- a/lib/chef/provider/package/yum/version.rb
+++ b/lib/chef/provider/package/yum/version.rb
@@ -40,6 +40,10 @@ class Chef
"#{version}.#{arch}" unless version.nil?
end
+ def name_with_arch
+ "#{name}.#{arch}" unless name.nil?
+ end
+
def matches_name_and_arch?(other)
other.version == version && other.arch == arch
end
diff --git a/lib/chef/provider/route.rb b/lib/chef/provider/route.rb
index 58a65edb81..b8af9e55b8 100644
--- a/lib/chef/provider/route.rb
+++ b/lib/chef/provider/route.rb
@@ -158,9 +158,9 @@ class Chef
end
def generate_config
- conf = {}
case node[:platform_family]
when "rhel", "amazon", "fedora"
+ conf = {}
# walk the collection
run_context.resource_collection.each do |resource|
next unless resource.is_a? Chef::Resource::Route
diff --git a/lib/chef/provider/script.rb b/lib/chef/provider/script.rb
index 444eac54ac..b54965be45 100644
--- a/lib/chef/provider/script.rb
+++ b/lib/chef/provider/script.rb
@@ -49,10 +49,6 @@ class Chef
def load_current_resource
super
- # @todo Chef-15: change this to an exception
- if code.nil?
- logger.warn "#{new_resource}: No code attribute was given, resource does nothing, this behavior is deprecated and will be removed in Chef 15 (April 2019)"
- end
end
def action_run
diff --git a/lib/chef/provider/windows_task.rb b/lib/chef/provider/windows_task.rb
index cd8e07e24c..0d77d8c939 100644
--- a/lib/chef/provider/windows_task.rb
+++ b/lib/chef/provider/windows_task.rb
@@ -135,10 +135,10 @@ class Chef
converge_by("#{new_resource} task created") do
task = TaskScheduler.new
if new_resource.frequency == :none
- task.new_work_item(new_resource.task_name, {}, { user: new_resource.user, password: new_resource.password })
+ task.new_work_item(new_resource.task_name, {}, { user: new_resource.user, password: new_resource.password, interactive: new_resource.interactive_enabled })
task.activate(new_resource.task_name)
else
- task.new_work_item(new_resource.task_name, trigger, { user: new_resource.user, password: new_resource.password })
+ task.new_work_item(new_resource.task_name, trigger, { user: new_resource.user, password: new_resource.password, interactive: new_resource.interactive_enabled })
end
task.application_name = new_resource.command
task.parameters = new_resource.command_arguments if new_resource.command_arguments
@@ -147,6 +147,7 @@ class Chef
task.configure_principals(principal_settings)
task.set_account_information(new_resource.user, new_resource.password)
task.creator = new_resource.user
+ task.description = new_resource.description unless new_resource.description.nil?
task.activate(new_resource.task_name)
end
end
@@ -252,6 +253,7 @@ class Chef
task.trigger = trigger unless new_resource.frequency == :none
task.configure_settings(config_settings)
task.creator = new_resource.user
+ task.description = new_resource.description unless new_resource.description.nil?
task.configure_principals(principal_settings)
end
end
@@ -329,6 +331,7 @@ class Chef
if new_resource.frequency == :none
flag = (task.account_information != new_resource.user ||
task.application_name != new_resource.command ||
+ description_needs_update?(task) ||
task.parameters != new_resource.command_arguments.to_s ||
task.principals[:run_level] != run_level ||
task.settings[:disallow_start_if_on_batteries] != new_resource.disallow_start_if_on_batteries ||
@@ -349,8 +352,9 @@ class Chef
current_task_trigger[:type] != new_task_trigger[:type] ||
current_task_trigger[:random_minutes_interval].to_i != new_task_trigger[:random_minutes_interval].to_i ||
current_task_trigger[:minutes_interval].to_i != new_task_trigger[:minutes_interval].to_i ||
- task.account_information != new_resource.user ||
+ task.account_information.to_s.casecmp(new_resource.user.to_s) != 0 ||
task.application_name != new_resource.command ||
+ description_needs_update?(task) ||
task.parameters != new_resource.command_arguments.to_s ||
task.working_directory != new_resource.cwd.to_s ||
task.principals[:logon_type] != logon_type ||
@@ -567,16 +571,25 @@ class Chef
settings
end
+ def description_needs_update?(task)
+ task.description != new_resource.description unless new_resource.description.nil?
+ end
+
def logon_type
# Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383566(v=vs.85).aspx
# if nothing is passed as logon_type the TASK_LOGON_SERVICE_ACCOUNT is getting set as default so using that for comparision.
- user_id = new_resource.user
+ user_id = new_resource.user.to_s
+ password = new_resource.password.to_s
if Chef::ReservedNames::Win32::Security::SID.service_account_user?(user_id)
TaskScheduler::TASK_LOGON_SERVICE_ACCOUNT
elsif Chef::ReservedNames::Win32::Security::SID.group_user?(user_id)
TaskScheduler::TASK_LOGON_GROUP
- elsif !new_resource.password.to_s.empty? # password is present
- TaskScheduler::TASK_LOGON_PASSWORD
+ elsif !user_id.empty? && !password.empty?
+ if new_resource.interactive_enabled
+ TaskScheduler::TASK_LOGON_INTERACTIVE_TOKEN
+ else
+ TaskScheduler::TASK_LOGON_PASSWORD
+ end
else
TaskScheduler::TASK_LOGON_INTERACTIVE_TOKEN
end
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index cd265b0618..ac2462c0ca 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -66,7 +66,6 @@ require "chef/provider/package/chocolatey"
require "chef/provider/package/dpkg"
require "chef/provider/package/dnf"
require "chef/provider/package/freebsd/port"
-require "chef/provider/package/freebsd/pkg"
require "chef/provider/package/freebsd/pkgng"
require "chef/provider/package/homebrew"
require "chef/provider/package/ips"
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 5222dc7286..c857d76c02 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -131,6 +131,7 @@ class Chef
@only_if = []
@source_line = nil
@deprecated = false
+ @skip_docs = false
# We would like to raise an error when the user gives us a guard
# interpreter and a ruby_block to the guard. In order to achieve this
# we need to understand when the user overrides the default guard
@@ -1183,8 +1184,8 @@ class Chef
# Internal Resource Interface (for Chef)
#
- FORBIDDEN_IVARS = [:@run_context, :@logger, :@not_if, :@only_if, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message, :@deprecated].freeze
- HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@logger, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message, :@deprecated].freeze
+ FORBIDDEN_IVARS = [:@run_context, :@logger, :@not_if, :@only_if, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message, :@deprecated, :@default_description, :@skip_docs].freeze
+ HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@logger, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message, :@deprecated, :@default_description, :@skip_docs].freeze
include Chef::Mixin::ConvertToClassName
extend Chef::Mixin::ConvertToClassName
@@ -1448,6 +1449,20 @@ class Chef
@deprecated
end
+ def self.skip_docs(skip_docs = "NOT_PASSED")
+ if skip_docs != "NOT_PASSED"
+ @skip_docs = skip_docs
+ end
+ @skip_docs
+ end
+
+ def self.default_description(default_description = "NOT_PASSED")
+ if default_description != "NOT_PASSED"
+ @default_description = default_description
+ end
+ @default_description
+ end
+
#
# The cookbook in which this Resource was defined (if any).
#
diff --git a/lib/chef/resource/apt_package.rb b/lib/chef/resource/apt_package.rb
index 3f4a36489d..e55d37fcc8 100644
--- a/lib/chef/resource/apt_package.rb
+++ b/lib/chef/resource/apt_package.rb
@@ -32,7 +32,7 @@ class Chef
property :overwrite_config_files, [TrueClass, FalseClass],
introduced: "14.0",
- description: "Overwrite existing config files with those in the package if prompted by apt.",
+ description: "Overwrite existing configuration files with those supplied by the package, if prompted by APT.",
default: false
end
diff --git a/lib/chef/resource/apt_preference.rb b/lib/chef/resource/apt_preference.rb
index 0169fb73c2..caa0f01305 100644
--- a/lib/chef/resource/apt_preference.rb
+++ b/lib/chef/resource/apt_preference.rb
@@ -30,8 +30,9 @@ class Chef
property :package_name, String,
name_property: true,
- description: "The name of the package.",
- regex: [/^([a-z]|[A-Z]|[0-9]|_|-|\.|\*|\+)+$/]
+ description: "An optional property to set the package name if it differs from the resource block's name.",
+ regex: [/^([a-z]|[A-Z]|[0-9]|_|-|\.|\*|\+)+$/],
+ validation_message: "The provided package name is not valid. Package names can only contain alphanumeric characters as well as _, -, +, or *!"
property :glob, String,
description: "Pin by glob() expression or with regular expressions surrounded by /."
diff --git a/lib/chef/resource/apt_repository.rb b/lib/chef/resource/apt_repository.rb
index 7ff337ec7c..145b515a41 100644
--- a/lib/chef/resource/apt_repository.rb
+++ b/lib/chef/resource/apt_repository.rb
@@ -34,7 +34,7 @@ class Chef
# to allow that so don't refactor this however tempting it is
property :repo_name, String,
regex: [/^[^\/]+$/],
- description: "The name of the repository to configure, if it differs from the name of the resource block. The value of this setting must not contain spaces.",
+ description: "An optional property to set the repository name if it differs from the resource block's name. The value of this setting must not contain spaces.",
validation_message: "repo_name property cannot contain a forward slash '/'",
introduced: "14.1", name_property: true
@@ -43,7 +43,7 @@ class Chef
property :distribution, [ String, nil, FalseClass ],
description: "Usually a distribution's codename, such as trusty, xenial or bionic. Default value: the codename of the node's distro.",
- default: lazy { node["lsb"]["codename"] }
+ default: lazy { node["lsb"]["codename"] }, default_description: "The LSB codename of the host such as 'bionic'."
property :components, Array,
description: "Package groupings, such as 'main' and 'stable'.",
diff --git a/lib/chef/resource/apt_update.rb b/lib/chef/resource/apt_update.rb
index 04a9407813..680806bc26 100644
--- a/lib/chef/resource/apt_update.rb
+++ b/lib/chef/resource/apt_update.rb
@@ -29,6 +29,7 @@ class Chef
# allow bare apt_update with no name
property :name, String, default: ""
+
property :frequency, Integer,
description: "Determines how frequently (in seconds) APT repository updates are made. Use this property when the :periodic action is specified.",
default: 86_400
diff --git a/lib/chef/resource/build_essential.rb b/lib/chef/resource/build_essential.rb
index 99722b14ed..d9d75fb83b 100644
--- a/lib/chef/resource/build_essential.rb
+++ b/lib/chef/resource/build_essential.rb
@@ -30,7 +30,7 @@ class Chef
property :compile_time, [TrueClass, FalseClass],
description: "Install the build essential packages at compile time.",
- default: false
+ default: false, desired_state: false
action :install do
diff --git a/lib/chef/resource/cab_package.rb b/lib/chef/resource/cab_package.rb
index a90ddc6891..501a0dfa26 100644
--- a/lib/chef/resource/cab_package.rb
+++ b/lib/chef/resource/cab_package.rb
@@ -39,7 +39,7 @@ class Chef
uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false)
end
end),
- default: lazy { |r| r.package_name }
+ default: lazy { |r| r.package_name }, default_description: "The package name."
end
end
end
diff --git a/lib/chef/resource/chef_gem.rb b/lib/chef/resource/chef_gem.rb
index 0a1b2ef736..6758a0c753 100644
--- a/lib/chef/resource/chef_gem.rb
+++ b/lib/chef/resource/chef_gem.rb
@@ -36,7 +36,7 @@ class Chef
class ChefGem < Chef::Resource::Package::GemPackage
resource_name :chef_gem
- property :gem_binary, default: "#{RbConfig::CONFIG['bindir']}/gem",
+ property :gem_binary, default: "#{RbConfig::CONFIG['bindir']}/gem", default_description: "Chef's built-in gem binary.",
description: "The path of a gem binary to use for the installation. By default, the same version of Ruby that is used by the chef-client will be installed.",
callbacks: {
"The chef_gem resource is restricted to the current gem environment, use gem_package to install to other environments." => proc { |v| v == "#{RbConfig::CONFIG['bindir']}/gem" },
diff --git a/lib/chef/resource/chocolatey_config.rb b/lib/chef/resource/chocolatey_config.rb
index 84c91e0167..d742c6e37a 100644
--- a/lib/chef/resource/chocolatey_config.rb
+++ b/lib/chef/resource/chocolatey_config.rb
@@ -23,7 +23,7 @@ class Chef
introduced "14.3"
property :config_key, String, name_property: true,
- description: "The name of the config. The resource's name will be used if this isn't provided."
+ description: "An optional property to set the config key name if it differs from the resource block's name."
property :value, String,
description: "The value to set."
diff --git a/lib/chef/resource/chocolatey_source.rb b/lib/chef/resource/chocolatey_source.rb
index 05f8848117..ce0287a67c 100644
--- a/lib/chef/resource/chocolatey_source.rb
+++ b/lib/chef/resource/chocolatey_source.rb
@@ -23,7 +23,7 @@ class Chef
introduced "14.3"
property :source_name, String, name_property: true,
- description: "The name of the source to add. The resource's name will be used if this isn't provided."
+ description: "An optional property to set the source name if it differs from the resource block's name."
property :source, String,
description: "The source URL."
diff --git a/lib/chef/resource/cookbook_file.rb b/lib/chef/resource/cookbook_file.rb
index 0caa9d0553..c96e794469 100644
--- a/lib/chef/resource/cookbook_file.rb
+++ b/lib/chef/resource/cookbook_file.rb
@@ -36,7 +36,8 @@ class Chef
default: lazy { ::File.basename(name) }
property :cookbook, String,
- description: "The cookbook in which a file is located (if it is not located in the current cookbook)."
+ description: "The cookbook in which a file is located (if it is not located in the current cookbook).",
+ desired_state: false
default_action :create
end
diff --git a/lib/chef/resource/cron.rb b/lib/chef/resource/cron.rb
index 57cc483c8a..7e9f3022a7 100644
--- a/lib/chef/resource/cron.rb
+++ b/lib/chef/resource/cron.rb
@@ -134,14 +134,33 @@ class Chef
)
end
- property :time, Symbol, equal_to: Chef::Provider::Cron::SPECIAL_TIME_VALUES
- property :mailto, String
- property :path, String
- property :home, String
- property :shell, String
- property :command, String, identity: true
- property :user, String, default: "root"
- property :environment, Hash, default: lazy { Hash.new }
+ property :time, Symbol,
+ description: "A time interval. Possible values: :annually, :daily, :hourly, :midnight, :monthly, :reboot, :weekly, or :yearly.",
+ equal_to: Chef::Provider::Cron::SPECIAL_TIME_VALUES
+
+ property :mailto, String,
+ description: "Set the MAILTO environment variable."
+
+ property :path, String,
+ description: "Set the PATH environment variable."
+
+ property :home, String,
+ description: "Set the HOME environment variable."
+
+ property :shell, String,
+ description: "Set the SHELL environment variable."
+
+ property :command, String,
+ description: "The command to be run, or the path to a file that contains the command to be run.",
+ identity: true
+
+ property :user, String,
+ description: "The name of the user that runs the command. If the user property is changed, the original user for the crontab program continues to run until that crontab program is deleted. This property is not applicable on the AIX platform.",
+ default: "root"
+
+ property :environment, Hash,
+ description: "A Hash of environment variables in the form of ({'ENV_VARIABLE' => 'VALUE'}).",
+ default: lazy { Hash.new }
private
diff --git a/lib/chef/resource/cron_access.rb b/lib/chef/resource/cron_access.rb
index cf50d4ace4..5785eddbe5 100644
--- a/lib/chef/resource/cron_access.rb
+++ b/lib/chef/resource/cron_access.rb
@@ -30,7 +30,7 @@ class Chef
description "Use the cron_access resource to manage the /etc/cron.allow and /etc/cron.deny files."
property :user, String,
- description: "The user to allow or deny. If not provided we'll use the resource name.",
+ description: "An optional property to set the user name if it differs from the resource block's name.",
name_property: true
action :allow do
diff --git a/lib/chef/resource/cron_d.rb b/lib/chef/resource/cron_d.rb
index 304a1ad388..f42318b574 100644
--- a/lib/chef/resource/cron_d.rb
+++ b/lib/chef/resource/cron_d.rb
@@ -87,41 +87,41 @@ class Chef
end
property :cron_name, String,
- description: "Set the name of the cron job. If this isn't specified we'll use the resource name.",
+ description: "An optional property to set the cron name if it differs from the resource block's name.",
name_property: true
- property :cookbook, String
+ property :cookbook, String, desired_state: false
property :predefined_value, String,
description: 'Schedule your cron job with one of the special predefined value instead of ** * pattern. This correspond to "@reboot", "@yearly", "@annually", "@monthly", "@weekly", "@daily", "@midnight" or "@hourly".',
equal_to: %w{ @reboot @yearly @annually @monthly @weekly @daily @midnight @hourly }
property :minute, [Integer, String],
- description: "The minute to schedule the cron job to run at. Valid values: 0-59.",
+ description: "The minute at which the cron entry should run (0 - 59).",
default: "*", callbacks: {
"should be a valid minute spec" => ->(spec) { validate_numeric(spec, 0, 59) },
}
property :hour, [Integer, String],
- description: "The hour to schedule the cron job to run at. Valid values: 0-23.",
+ description: "The hour at which the cron entry should run (0 - 23).",
default: "*", callbacks: {
"should be a valid hour spec" => ->(spec) { validate_numeric(spec, 0, 23) },
}
property :day, [Integer, String],
- description: "The day to schedule the cron job to run at. Valid values: 1-31.",
+ description: "The day of month at which the cron entry should run (1 - 31).",
default: "*", callbacks: {
"should be a valid day spec" => ->(spec) { validate_numeric(spec, 1, 31) },
}
property :month, [Integer, String],
- description: "The month to schedule the cron job to run at. Valid values: 1-12, jan-dec, or *.",
+ description: "The month in the year on which a cron entry is to run (1 - 12, jan-dec, or *).",
default: "*", callbacks: {
"should be a valid month spec" => ->(spec) { validate_month(spec) },
}
property :weekday, [Integer, String],
- description: "The day to schedule the cron job to run at. Valid values: 0-7, mon-sun, or *.",
+ description: "The day of the week on which this entry is to run (0-7, mon-sun, or *), where Sunday is both 0 and 7.",
default: "*", callbacks: {
"should be a valid weekday spec" => ->(spec) { validate_dow(spec) },
}
@@ -131,7 +131,7 @@ class Chef
required: true
property :user, String,
- description: "The user to run the cron job as.",
+ description: "The name of the user that runs the command.",
default: "root"
property :mailto, String,
@@ -150,7 +150,7 @@ class Chef
description: "A comment to place in the cron.d file."
property :environment, Hash,
- description: "A Hash containing additional arbitrary environment variables under which the cron job will be run.",
+ description: "A Hash containing additional arbitrary environment variables under which the cron job will be run in the form of ``({'ENV_VARIABLE' => 'VALUE'})``.",
default: lazy { Hash.new }
property :mode, [String, Integer],
diff --git a/lib/chef/resource/directory.rb b/lib/chef/resource/directory.rb
index c585985291..f2e1aef254 100644
--- a/lib/chef/resource/directory.rb
+++ b/lib/chef/resource/directory.rb
@@ -44,7 +44,7 @@ class Chef
description: "The path to the directory. Using a fully qualified path is recommended, but is not always required."
property :recursive, [ TrueClass, FalseClass ],
- description: "Create or delete parent directories recursively. For the owner, group, and mode properties, the value of this attribute applies only to the leaf directory.",
+ description: "Create or delete parent directories recursively. For the owner, group, and mode properties, the value of this property applies only to the leaf directory.",
default: false
end
end
diff --git a/lib/chef/resource/dmg_package.rb b/lib/chef/resource/dmg_package.rb
index f697d8303b..29f38a6bf6 100644
--- a/lib/chef/resource/dmg_package.rb
+++ b/lib/chef/resource/dmg_package.rb
@@ -27,123 +27,118 @@ class Chef
introduced "14.0"
property :app, String,
- description: "The name of the application used by default for the /Volumes directory and the .app directory copied to /Applications.",
+ description: "The name of the application as it appears in the /Volumes directory, if it differs from the resource block's name.",
name_property: true
property :source, String,
- description: "The remote URL for the dmg to download if specified."
+ description: "The remote URL that is used to download the .dmg file, if specified."
property :file, String,
- description: "The local dmg full file path."
+ description: "The full path to the .dmg file on the local system."
- property :owner, String,
- description: "The owner that should own the package installation."
+ property :owner, [String, Integer],
+ description: "The user that should own the package installation."
property :destination, String,
description: "The directory to copy the .app into.",
default: "/Applications"
property :checksum, String,
- description: "The sha256 checksum of the dmg to download"
+ description: "The sha256 checksum of the .dmg file to download."
property :volumes_dir, String,
- description: "The Directory under /Volumes where the dmg is mounted as not all dmgs are mounted into a /Volumes location matching the name of the dmg."
+ description: "The directory under /Volumes where the dmg is mounted, if it differs from the name of the .dmg file.",
+ default: lazy { |r| r.app }, default_description: "The value passed for the application name."
property :dmg_name, String,
- description: "The name of the dmg if it is not the same as app, or if the name has spaces."
+ description: "The name of the .dmg file if it differs from that of the app, or if the name has spaces.",
+ desired_state: false,
+ default: lazy { |r| r.app }, default_description: "The value passed for the application name."
property :type, String,
description: "The type of package.",
equal_to: %w{app pkg mpkg},
- default: "app"
-
- property :installed, [TrueClass, FalseClass],
- default: false, desired_state: false
+ default: "app", desired_state: false
property :package_id, String,
- description: "The package id registered with pkgutil when a pkg or mpkg is installed"
+ description: "The package ID that is registered with pkgutil when a pkg or mpkg is installed."
property :dmg_passphrase, String,
- description: "Specify a passphrase to use to unencrypt the dmg while mounting."
+ description: "Specify a passphrase to be used to decrypt the .dmg file during the mount process.",
+ desired_state: false
property :accept_eula, [TrueClass, FalseClass],
description: "Specify whether to accept the EULA. Certain dmgs require acceptance of EULA before mounting.",
- default: false
+ default: false, desired_state: false
- property :headers, [Hash, nil],
+ property :headers, Hash,
description: "Allows custom HTTP headers (like cookies) to be set on the remote_file resource.",
- default: nil
+ desired_state: false
property :allow_untrusted, [TrueClass, FalseClass],
description: "Allow installation of packages that do not have trusted certificates.",
- default: false
+ default: false, desired_state: false
load_current_value do |new_resource|
if ::File.directory?("#{new_resource.destination}/#{new_resource.app}.app")
- Chef::Log.info "Already installed; to upgrade, remove \"#{new_resource.destination}/#{new_resource.app}.app\""
- installed true
- elsif shell_out("pkgutil --pkgs='#{new_resource.package_id}'").exitstatus == 0
- Chef::Log.info "Already installed; to upgrade, try \"sudo pkgutil --forget '#{new_resource.package_id}'\""
- installed true
+ Chef::Log.info "#{new_resource.app} is already installed. To upgrade, remove \"#{new_resource.destination}/#{new_resource.app}.app\""
+ elsif shell_out("pkgutil --pkg-info '#{new_resource.package_id}'").exitstatus == 0
+ Chef::Log.info "#{new_resource.app} is already installed. To upgrade, try \"sudo pkgutil --forget '#{new_resource.package_id}'\""
else
- installed false
+ current_value_does_not_exist! # allows us to check for current_resource.nil? below
end
end
action :install do
description "Installs the application."
- unless current_resource.installed
-
- volumes_dir = new_resource.volumes_dir ? new_resource.volumes_dir : new_resource.app
- dmg_name = new_resource.dmg_name ? new_resource.dmg_name : new_resource.app
-
+ if current_resource.nil?
if new_resource.source
- declare_resource(:remote_file, "#{dmg_file} - #{new_resource.name}") do
- path dmg_file
+ remote_file dmg_file do
source new_resource.source
headers new_resource.headers if new_resource.headers
checksum new_resource.checksum if new_resource.checksum
end
end
- passphrase_cmd = new_resource.dmg_passphrase ? "-passphrase #{new_resource.dmg_passphrase}" : ""
ruby_block "attach #{dmg_file}" do
block do
- cmd = shell_out("hdiutil imageinfo #{passphrase_cmd} '#{dmg_file}' | grep -q 'Software License Agreement: true'")
- software_license_agreement = cmd.exitstatus == 0
- raise "Requires EULA Acceptance; add 'accept_eula true' to package resource" if software_license_agreement && !new_resource.accept_eula
- accept_eula_cmd = new_resource.accept_eula ? "echo Y | PAGER=true" : ""
- shell_out!("#{accept_eula_cmd} hdiutil attach #{passphrase_cmd} '#{dmg_file}' -mountpoint '/Volumes/#{volumes_dir}' -quiet")
+ raise "This DMG package requires EULA acceptance. Add 'accept_eula true' to dmg_package resource to accept the EULA during installation." if software_license_agreement? && !new_resource.accept_eula
+
+ attach_cmd = new_resource.accept_eula ? "yes | " : ""
+ attach_cmd << "/usr/bin/hdiutil attach #{passphrase_cmd} '#{dmg_file}' -nobrowse -mountpoint '/Volumes/#{new_resource.volumes_dir}'"
+
+ shell_out!(attach_cmd, env: { "PAGER" => "true" })
end
- not_if "hdiutil info #{passphrase_cmd} | grep -q 'image-path.*#{dmg_file}'"
+ not_if { dmg_attached? }
end
case new_resource.type
when "app"
- declare_resource(:execute, "rsync --force --recursive --links --perms --executability --owner --group --times '/Volumes/#{volumes_dir}/#{new_resource.app}.app' '#{new_resource.destination}'") do
+ execute "rsync --force --recursive --links --perms --executability --owner --group --times '/Volumes/#{new_resource.volumes_dir}/#{new_resource.app}.app' '#{new_resource.destination}'" do
user new_resource.owner if new_resource.owner
end
- declare_resource(:file, "#{new_resource.destination}/#{new_resource.app}.app/Contents/MacOS/#{new_resource.app}") do
- mode "755"
+ file "#{new_resource.destination}/#{new_resource.app}.app/Contents/MacOS/#{new_resource.app}" do
+ mode "0755"
ignore_failure true
end
when "mpkg", "pkg"
- install_cmd = "installation_file=$(ls '/Volumes/#{volumes_dir}' | grep '.#{new_resource.type}$') && sudo installer -pkg \"/Volumes/#{volumes_dir}/$installation_file\" -target /"
+ install_cmd = "installation_file=$(ls '/Volumes/#{new_resource.volumes_dir}' | grep '.#{new_resource.type}$') && sudo installer -pkg \"/Volumes/#{new_resource.volumes_dir}/$installation_file\" -target /"
install_cmd += " -allowUntrusted" if new_resource.allow_untrusted
- declare_resource(:execute, install_cmd) do
+ execute install_cmd do
# Prevent cfprefsd from holding up hdiutil detach for certain disk images
environment("__CFPREFERENCES_AVOID_DAEMON" => "1")
end
end
- declare_resource(:execute, "hdiutil detach '/Volumes/#{volumes_dir}' || hdiutil detach '/Volumes/#{volumes_dir}' -force")
+ execute "/usr/bin/hdiutil detach '/Volumes/#{new_resource.volumes_dir}' || /usr/bin/hdiutil detach '/Volumes/#{new_resource.volumes_dir}' -force"
end
end
action_class do
+ # @return [String] the path to the dmg file
def dmg_file
@dmg_file ||= begin
if new_resource.file.nil?
@@ -153,6 +148,23 @@ class Chef
end
end
end
+
+ # @return [String] the hdiutil flag for handling DMGs with a password
+ def passphrase_cmd
+ @passphrase_cmd ||= new_resource.dmg_passphrase ? "-passphrase #{new_resource.dmg_passphrase}" : ""
+ end
+
+ # @return [Boolean] does the DMG require a software license agreement
+ def software_license_agreement?
+ # example hdiutil imageinfo output: http://rubular.com/r/0xvOaA6d8B
+ /Software License Agreement: true/.match?(shell_out!("/usr/bin/hdiutil imageinfo #{passphrase_cmd} '#{dmg_file}'").stdout)
+ end
+
+ # @return [Boolean] is the dmg file currently attached?
+ def dmg_attached?
+ # example hdiutil imageinfo output: http://rubular.com/r/CDcqenkixg
+ /image-path.*#{dmg_file}/.match?(shell_out!("/usr/bin/hdiutil info #{passphrase_cmd}").stdout)
+ end
end
end
end
diff --git a/lib/chef/resource/execute.rb b/lib/chef/resource/execute.rb
index 1becbf50a7..9eb86a2fef 100644
--- a/lib/chef/resource/execute.rb
+++ b/lib/chef/resource/execute.rb
@@ -62,10 +62,10 @@ class Chef
description: "Prevent a command from creating a file when that file already exists."
property :cwd, String,
- description: "Set the current working directory before running a command."
+ description: "The current working directory from which the command will be run."
property :environment, Hash,
- description: "Specify a Hash of environment variables to be set."
+ description: "A Hash of environment variables in the form of ({'ENV_VARIABLE' => 'VALUE'})."
alias :env :environment
@@ -87,7 +87,7 @@ class Chef
description: "The amount of time (in seconds) a command is to wait before timing out."
property :user, [ String, Integer ],
- description: "The user name of the user identity with which to launch the new process. The user name may optionally be specifed with a domain, i.e. domainuser or user@my.dns.domain.com via Universal Principal Name (UPN)format. It can also be specified without a domain simply as user if the domain is instead specified using the domain attribute. On Windows only, if this property is specified, the password property must be specified."
+ description: "The user name of the user identity with which to launch the new process. The user name may optionally be specifed with a domain, i.e. domainuser or user@my.dns.domain.com via Universal Principal Name (UPN)format. It can also be specified without a domain simply as user if the domain is instead specified using the domain property. On Windows only, if this property is specified, the password property must be specified."
property :domain, String,
introduced: "12.21",
@@ -100,7 +100,7 @@ class Chef
# lazy used to set default value of sensitive to true if password is set
property :sensitive, [ TrueClass, FalseClass ],
description: "Ensure that sensitive resource data is not logged by the chef-client.",
- default: lazy { |r| r.password ? true : false }
+ default: lazy { |r| r.password ? true : false }, default_description: "True if the password property is set. False otherwise."
property :elevated, [ TrueClass, FalseClass ], default: false,
description: "Determines whether the script will run with elevated permissions to circumvent User Access Control (UAC) interactively blocking the process.\nThis will cause the process to be run under a batch login instead of an interactive login. The user running Chef needs the “Replace a process level token” and “Adjust Memory Quotas for a process” permissions. The user that is running the command needs the “Log on as a batch job” permission.\nBecause this requires a login, the user and password properties are required.",
diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb
index cac20f2356..8db15fc661 100644
--- a/lib/chef/resource/file.rb
+++ b/lib/chef/resource/file.rb
@@ -66,7 +66,7 @@ class Chef
property :content, [ String, nil ], desired_state: false,
description: "A string that is written to the file. The contents of this property replace any previous content when this property has something other than the default value. The default behavior will not modify content."
- property :diff, [ String, nil ], desired_state: false
+ property :diff, [ String, nil ], desired_state: false, skip_docs: true
property :force_unlink, [ TrueClass, FalseClass ], desired_state: false, default: false,
description: "How the chef-client handles certain situations when the target file turns out not to be a file. For example, when a target file is actually a symlink. Set to true for the chef-client delete the non-file target and replace it with the specified file. Set to false for the chef-client to raise an error."
diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb
index f5e4010ee7..0f92d7c229 100644
--- a/lib/chef/resource/freebsd_package.rb
+++ b/lib/chef/resource/freebsd_package.rb
@@ -20,7 +20,6 @@
require "chef/resource/package"
require "chef/provider/package/freebsd/port"
-require "chef/provider/package/freebsd/pkg"
require "chef/provider/package/freebsd/pkgng"
require "chef/mixin/shell_out"
@@ -42,30 +41,13 @@ class Chef
assign_provider
end
- # Is the system at least version 1000017 or is the make variable WITH_PKGNG set
- #
- # @return [Boolean] do we support pkgng
- def supports_pkgng?
- ships_with_pkgng? || !!shell_out!("make", "-V", "WITH_PKGNG", env: nil).stdout.match(/yes/i)
- end
-
private
- # It was not until __FreeBSD_version 1000017 that pkgng became
- # the default binary package manager. See '/usr/ports/Mk/bsd.port.mk'.
- def ships_with_pkgng?
- node[:os_version].to_i >= 1000017
- end
-
def assign_provider
@provider = if source.to_s =~ /^ports$/i
Chef::Provider::Package::Freebsd::Port
- elsif supports_pkgng?
- Chef::Provider::Package::Freebsd::Pkgng
else
- Chef.deprecated(:freebsd_package_provider, "The freebsd_package provider for pkg (Chef::Provider::Package::Freebsd::Pkg) is deprecated and will be removed from Chef core in 15.0 (April 2019).")
-
- Chef::Provider::Package::Freebsd::Pkg
+ Chef::Provider::Package::Freebsd::Pkgng
end
end
end
diff --git a/lib/chef/resource/homebrew_cask.rb b/lib/chef/resource/homebrew_cask.rb
index 626ae02a69..a22d73aace 100644
--- a/lib/chef/resource/homebrew_cask.rb
+++ b/lib/chef/resource/homebrew_cask.rb
@@ -32,8 +32,9 @@ class Chef
include Chef::Mixin::HomebrewUser
property :cask_name, String,
- description: "The name of the Homebrew cask, if it differs from the resource block name.",
+ description: "An optional property to set the cask name if it differs from the resource block's name.",
regex: %r{^[\w/-]+$},
+ validation_message: "The provided Homebrew cask name is not valid. Cask names can contain alphanumeric characters, _, -, or / only!",
name_property: true
property :options, String,
@@ -47,7 +48,7 @@ class Chef
description: "The path to the homebrew binary.",
default: "/usr/local/bin/brew"
- property :owner, String,
+ property :owner, [String, Integer],
description: "The owner of the Homebrew installation.",
default: lazy { find_homebrew_username }
diff --git a/lib/chef/resource/homebrew_tap.rb b/lib/chef/resource/homebrew_tap.rb
index 20ac0bb5d5..aff65685b7 100644
--- a/lib/chef/resource/homebrew_tap.rb
+++ b/lib/chef/resource/homebrew_tap.rb
@@ -32,8 +32,8 @@ class Chef
include Chef::Mixin::HomebrewUser
property :tap_name, String,
- description: "Optional tap name to override the resource name",
- validation_message: "Homebrew tap names must be in the form REPO/TAP",
+ description: "An optional property to set the tap name if it differs from the resource block's name.",
+ validation_message: "Homebrew tap names must be in the form REPO/TAP format!",
regex: %r{^[\w-]+(?:\/[\w-]+)+$},
name_property: true
diff --git a/lib/chef/resource/hostname.rb b/lib/chef/resource/hostname.rb
index 30446fbead..6b5a5617cf 100644
--- a/lib/chef/resource/hostname.rb
+++ b/lib/chef/resource/hostname.rb
@@ -27,16 +27,16 @@ class Chef
introduced "14.0"
property :hostname, String,
- description: "Used to specify the hostname if it is different than the resource's name.",
+ description: "An optional property to set the hostname if it differs from the resource block's name.",
name_property: true
property :compile_time, [ TrueClass, FalseClass ],
description: "Determines whether or not the resource shoul be run at compile time.",
- default: true
+ default: true, desired_state: false
property :ipaddress, String,
description: "The IP address to use when configuring the hosts file.",
- default: lazy { node["ipaddress"] }
+ default: lazy { node["ipaddress"] }, default_description: "The node's IP address as determined by Ohai."
property :aliases, [ Array, nil ],
description: "An array of hostname aliases to use when configuring the hosts file.",
diff --git a/lib/chef/resource/kernel_module.rb b/lib/chef/resource/kernel_module.rb
index 0976b9c211..39c792cf3b 100644
--- a/lib/chef/resource/kernel_module.rb
+++ b/lib/chef/resource/kernel_module.rb
@@ -17,7 +17,7 @@ class Chef
introduced "14.3"
property :modname, String,
- description: "The name of the kernel module.",
+ description: "An optional property to set the kernel module name if it differs from the resource block's name.",
name_property: true, identity: true
property :load_dir, String,
@@ -40,12 +40,14 @@ class Chef
file "#{new_resource.load_dir}/#{new_resource.modname}.conf" do
content "#{new_resource.modname}\n"
- notifies :run, "execute[update initramfs]"
+ notifies :run, "execute[update initramfs]", :delayed
end
- execute "update initramfs" do
- command initramfs_command
- action :nothing
+ with_run_context :root do
+ find_resource(:execute, "update initramfs") do
+ command initramfs_command
+ action :nothing
+ end
end
end
@@ -54,17 +56,19 @@ class Chef
file "#{new_resource.load_dir}/#{new_resource.modname}.conf" do
action :delete
- notifies :run, "execute[update initramfs]"
+ notifies :run, "execute[update initramfs]", :delayed
end
file "#{new_resource.unload_dir}/blacklist_#{new_resource.modname}.conf" do
action :delete
- notifies :run, "execute[update initramfs]"
+ notifies :run, "execute[update initramfs]", :delayed
end
- execute "update initramfs" do
- command initramfs_command
- action :nothing
+ with_run_context :root do
+ find_resource(:execute, "update initramfs") do
+ command initramfs_command
+ action :nothing
+ end
end
new_resource.run_action(:unload)
@@ -75,12 +79,14 @@ class Chef
file "#{new_resource.unload_dir}/blacklist_#{new_resource.modname}.conf" do
content "blacklist #{new_resource.modname}"
- notifies :run, "execute[update initramfs]"
+ notifies :run, "execute[update initramfs]", :delayed
end
- execute "update initramfs" do
- command initramfs_command
- action :nothing
+ with_run_context :root do
+ find_resource(:execute, "update initramfs") do
+ command initramfs_command
+ action :nothing
+ end
end
new_resource.run_action(:unload)
diff --git a/lib/chef/resource/link.rb b/lib/chef/resource/link.rb
index 00ce69dddd..f62209108c 100644
--- a/lib/chef/resource/link.rb
+++ b/lib/chef/resource/link.rb
@@ -48,7 +48,7 @@ class Chef
end
property :target_file, String,
- description: "The name of the link. Default value: the name of the resource block.",
+ description: "An optional property to set the target file if it differs from the resource block's name.",
name_property: true, identity: true
property :to, String,
@@ -60,7 +60,7 @@ class Chef
equal_to: [ :symbolic, :hard ], default: :symbolic
property :group, [String, Integer],
- description: "A string or ID that identifies the group associated with a symbolic link.",
+ description: "A group name or ID number that identifies the group associated with a symbolic link.",
regex: [Chef::Config[:group_valid_regex]]
property :owner, [String, Integer],
diff --git a/lib/chef/resource/locale.rb b/lib/chef/resource/locale.rb
index 443e682c47..ca6ea510c0 100644
--- a/lib/chef/resource/locale.rb
+++ b/lib/chef/resource/locale.rb
@@ -28,6 +28,7 @@ class Chef
property :lang, String,
default: "en_US.utf8",
description: "Sets the default system language."
+
property :lc_all, String,
default: "en_US.utf8",
description: "Sets the fallback system language."
diff --git a/lib/chef/resource/macos_userdefaults.rb b/lib/chef/resource/macos_userdefaults.rb
index 9c1acc3334..5eed3f8648 100644
--- a/lib/chef/resource/macos_userdefaults.rb
+++ b/lib/chef/resource/macos_userdefaults.rb
@@ -58,7 +58,8 @@ class Chef
# @todo this should get refactored away: https://github.com/chef/chef/issues/7622
property :is_set, [TrueClass, FalseClass],
default: false,
- desired_state: false
+ desired_state: false,
+ skip_docs: true
# 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
diff --git a/lib/chef/resource/macosx_service.rb b/lib/chef/resource/macosx_service.rb
index deff6e1927..37681ca930 100644
--- a/lib/chef/resource/macosx_service.rb
+++ b/lib/chef/resource/macosx_service.rb
@@ -27,10 +27,6 @@ class Chef
description "Use the macosx_service resource to manage services on the macOS platform."
- identity_attr :service_name
-
- state_attrs :enabled, :running
-
property :plist, String,
description: "A plist to use in the case where the filename and label for the service do not match."
diff --git a/lib/chef/resource/mdadm.rb b/lib/chef/resource/mdadm.rb
index 3fc5b7c338..382573791e 100644
--- a/lib/chef/resource/mdadm.rb
+++ b/lib/chef/resource/mdadm.rb
@@ -40,9 +40,10 @@ class Chef
default: lazy { [] },
description: "The devices to be part of a RAID array."
+ # @todo this should get refactored away
property :exists, [ TrueClass, FalseClass ],
default: false,
- description: "Indicates whether the RAID array exists."
+ skip_docs: true
property :level, Integer,
default: 1,
@@ -57,7 +58,7 @@ class Chef
property :raid_device, String,
identity: true, name_property: true,
- description: "The name of the RAID device. We'll use the resource's name if this isn't specified."
+ description: "An optional property to specify the name of the RAID device if it differs from the resource block's name."
property :layout, String,
description: "The RAID5 parity algorithm. Possible values: left-asymmetric (or la), left-symmetric (or ls), right-asymmetric (or ra), or right-symmetric (or rs)."
diff --git a/lib/chef/resource/mount.rb b/lib/chef/resource/mount.rb
index f3a8af7932..4c20a62cf8 100644
--- a/lib/chef/resource/mount.rb
+++ b/lib/chef/resource/mount.rb
@@ -1,7 +1,7 @@
#
# Author:: Joshua Timberman (<joshua@chef.io>)
# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2009-2017, Chef Software Inc.
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,7 +28,7 @@ class Chef
allowed_actions :mount, :umount, :unmount, :remount, :enable, :disable
# this is a poor API please do not re-use this pattern
- property :supports, Hash,
+ property :supports, [Array, Hash],
description: "Specify a Hash of supported mount features.",
default: lazy { { remount: false } },
coerce: proc { |x| x.is_a?(Array) ? x.each_with_object({}) { |i, m| m[i] = true } : x }
@@ -50,7 +50,7 @@ class Chef
equal_to: RUBY_PLATFORM =~ /solaris/i ? %i{ device } : %i{ device label uuid }
# @todo this should get refactored away: https://github.com/chef/chef/issues/7621
- property :mounted, [TrueClass, FalseClass], default: false
+ property :mounted, [TrueClass, FalseClass], default: false, skip_docs: true
property :fsck_device, String,
description: "Solaris only: The fsck device.",
diff --git a/lib/chef/resource/ohai.rb b/lib/chef/resource/ohai.rb
index da221170c3..b5cd97cae0 100644
--- a/lib/chef/resource/ohai.rb
+++ b/lib/chef/resource/ohai.rb
@@ -27,10 +27,6 @@ class Chef
description "Use the ohai resource to reload the Ohai configuration on a node. This allows recipes that change system attributes (like a recipe that adds a user) to refer to those attributes later on during the chef-client run."
- property :ohai_name,
- deprecated: true,
- name_property: true, introduced: "12.17"
-
property :plugin, String,
description: "The name of an Ohai plugin to be reloaded. If this property is not specified, the chef-client will reload all plugins."
diff --git a/lib/chef/resource/ohai_hint.rb b/lib/chef/resource/ohai_hint.rb
index d1b538c70f..0a710a166c 100644
--- a/lib/chef/resource/ohai_hint.rb
+++ b/lib/chef/resource/ohai_hint.rb
@@ -27,7 +27,7 @@ class Chef
introduced "14.0"
property :hint_name, String,
- description: "The name of the hints file, if it differs from the resource name.",
+ description: "An optional property to set the hint name if it differs from the resource block's name.",
name_property: true
property :content, Hash,
diff --git a/lib/chef/resource/openssl_dhparam.rb b/lib/chef/resource/openssl_dhparam.rb
index 3b0d264f8b..445dd97bdc 100644
--- a/lib/chef/resource/openssl_dhparam.rb
+++ b/lib/chef/resource/openssl_dhparam.rb
@@ -30,7 +30,7 @@ class Chef
introduced "14.0"
property :path, String,
- description: "The path to write the file to if it's different than the resource name.",
+ description: "An optional property for specifying the path to write the file to if it differs from the resource block's name.",
name_property: true
property :key_length, Integer,
@@ -45,10 +45,10 @@ class Chef
description: "The desired Diffie-Hellmann generator.",
default: 2
- property :owner, String,
+ property :owner, [String, Integer],
description: "The owner applied to all files created by the resource."
- property :group, String,
+ property :group, [String, Integer],
description: "The group ownership applied to all files created by the resource."
property :mode, [Integer, String],
diff --git a/lib/chef/resource/openssl_ec_private_key.rb b/lib/chef/resource/openssl_ec_private_key.rb
index 72543f7612..06fec2939b 100644
--- a/lib/chef/resource/openssl_ec_private_key.rb
+++ b/lib/chef/resource/openssl_ec_private_key.rb
@@ -30,7 +30,7 @@ class Chef
introduced "14.4"
property :path, String,
- description: "The path to write the file to it's different than the resource name.",
+ description: "An optional property for specifying the path to write the file to if it differs from the resource block's name.",
name_property: true
property :key_curve, String,
@@ -47,10 +47,10 @@ class Chef
description: "The designed cipher to use when generating your key. Run `openssl list-cipher-algorithms` to see available options.",
default: "des3"
- property :owner, String,
+ property :owner, [String, Integer],
description: "The owner applied to all files created by the resource."
- property :group, String,
+ property :group, [String, Integer],
description: "The group ownership applied to all files created by the resource."
property :mode, [Integer, String],
diff --git a/lib/chef/resource/openssl_ec_public_key.rb b/lib/chef/resource/openssl_ec_public_key.rb
index 4019c7e94a..fad7fd9713 100644
--- a/lib/chef/resource/openssl_ec_public_key.rb
+++ b/lib/chef/resource/openssl_ec_public_key.rb
@@ -30,7 +30,7 @@ class Chef
introduced "14.4"
property :path, String,
- description: "The path to write the file to if different than the resource's name.",
+ description: "An optional property for specifying the path to write the file to if it differs from the resource block's name.",
name_property: true
property :private_key_path, String,
@@ -42,10 +42,10 @@ class Chef
property :private_key_pass, String,
description: "The passphrase of the provided private key."
- property :owner, String,
+ property :owner, [String, Integer],
description: "The owner applied to all files created by the resource."
- property :group, String,
+ property :group, [String, Integer],
description: "The group ownership applied to all files created by the resource."
property :mode, [Integer, String],
diff --git a/lib/chef/resource/openssl_rsa_private_key.rb b/lib/chef/resource/openssl_rsa_private_key.rb
index f2c1400a30..fb19e8ff99 100644
--- a/lib/chef/resource/openssl_rsa_private_key.rb
+++ b/lib/chef/resource/openssl_rsa_private_key.rb
@@ -31,12 +31,12 @@ class Chef
introduced "14.0"
property :path, String,
- description: "The path to write the file to it's different than the resource name.",
+ description: "An optional property for specifying the path to write the file to if it differs from the resource block's name.",
name_property: true
property :key_length, Integer,
equal_to: [1024, 2048, 4096, 8192],
- validation_message: "key_length (bits) must be 1024, 2048, 4096, or 8192.",
+ validation_message: "key_length (bits) must be 1024, 2048, 4096, or 8192!",
description: "The desired bit length of the generated key.",
default: 2048
@@ -49,10 +49,10 @@ class Chef
description: "The designed cipher to use when generating your key. Run `openssl list-cipher-algorithms` to see available options.",
default: "des3"
- property :owner, String,
+ property :owner, [String, Integer],
description: "The owner applied to all files created by the resource."
- property :group, String,
+ property :group, [String, Integer],
description: "The group ownership applied to all files created by the resource."
property :mode, [Integer, String],
diff --git a/lib/chef/resource/openssl_rsa_public_key.rb b/lib/chef/resource/openssl_rsa_public_key.rb
index b9a4924c3e..be7f25030f 100644
--- a/lib/chef/resource/openssl_rsa_public_key.rb
+++ b/lib/chef/resource/openssl_rsa_public_key.rb
@@ -30,7 +30,7 @@ class Chef
introduced "14.0"
property :path, String,
- description: "The path to the public key file, if it differs from the resource name.",
+ description: "An optional property for specifying the path to the public key if it differs from the resource block's name.",
name_property: true
property :private_key_path, String,
@@ -42,10 +42,10 @@ class Chef
property :private_key_pass, String,
description: "The passphrase of the provided private key."
- property :owner, String,
+ property :owner, [String, Integer],
description: "The owner applied to all files created by the resource."
- property :group, String,
+ property :group, [String, Integer],
description: "The group ownership applied to all files created by the resource."
property :mode, [Integer, String],
diff --git a/lib/chef/resource/openssl_x509_certificate.rb b/lib/chef/resource/openssl_x509_certificate.rb
index 467bffb9cf..71a1f8d6d7 100644
--- a/lib/chef/resource/openssl_x509_certificate.rb
+++ b/lib/chef/resource/openssl_x509_certificate.rb
@@ -31,13 +31,13 @@ class Chef
introduced "14.4"
property :path, String,
- description: "Optional path to write the file to if you'd like to specify it here instead of in the resource name.",
+ description: "An optional property for specifying the path to write the file to if it differs from the resource block's name.",
name_property: true
- property :owner, String,
+ property :owner, [String, Integer],
description: "The owner applied to all files created by the resource."
- property :group, String,
+ property :group, [String, Integer],
description: "The group ownership applied to all files created by the resource."
property :expire, Integer,
diff --git a/lib/chef/resource/openssl_x509_crl.rb b/lib/chef/resource/openssl_x509_crl.rb
index 7f41c551cc..c6a2918320 100644
--- a/lib/chef/resource/openssl_x509_crl.rb
+++ b/lib/chef/resource/openssl_x509_crl.rb
@@ -30,7 +30,7 @@ class Chef
introduced "14.4"
property :path, String,
- description: "Optional path to write the file to if you'd like to specify it here instead of in the resource name.",
+ description: "An optional property for specifying the path to write the file to if it differs from the resource block's name.",
name_property: true
property :serial_to_revoke, [Integer, String],
@@ -59,10 +59,10 @@ class Chef
property :ca_key_pass, String,
description: "The passphrase for CA private key's passphrase."
- property :owner, String,
+ property :owner, [String, Integer],
description: "The owner permission for the CRL file."
- property :group, String,
+ property :group, [String, Integer],
description: "The group permission for the CRL file."
property :mode, [Integer, String],
diff --git a/lib/chef/resource/openssl_x509_request.rb b/lib/chef/resource/openssl_x509_request.rb
index b4699612c9..6e5e182f31 100644
--- a/lib/chef/resource/openssl_x509_request.rb
+++ b/lib/chef/resource/openssl_x509_request.rb
@@ -30,12 +30,12 @@ class Chef
introduced "14.4"
property :path, String, name_property: true,
- description: "The optional path to write the file to if you'd like to specify it here instead of in the resource name."
+ description: "An optional property for specifying the path to write the file to if it differs from the resource block's name."
- property :owner, String,
+ property :owner, [String, Integer],
description: "The owner applied to all files created by the resource."
- property :group, String,
+ property :group, [String, Integer],
description: "The group ownership applied to all files created by the resource."
property :mode, [Integer, String],
diff --git a/lib/chef/resource/package.rb b/lib/chef/resource/package.rb
index 8954478ee3..71f030244b 100644
--- a/lib/chef/resource/package.rb
+++ b/lib/chef/resource/package.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -42,7 +42,7 @@ class Chef
end
property :package_name, [ String, Array ],
- description: "The name of the package. Defaults to the name of the resourse block unless specified.",
+ description: "An optional property to set the package name if it differs from the resource block's name.",
identity: true
property :version, [ String, Array ],
@@ -61,7 +61,7 @@ class Chef
default: lazy { Hash.new }, desired_state: false
property :source, String,
- description: "The direct path to a the package on the host.",
+ description: "The optional path to a package on the local file system.",
desired_state: false
property :timeout, [ String, Integer ],
diff --git a/lib/chef/resource/powershell_package.rb b/lib/chef/resource/powershell_package.rb
index 91e300584f..28dabc82b0 100644
--- a/lib/chef/resource/powershell_package.rb
+++ b/lib/chef/resource/powershell_package.rb
@@ -26,7 +26,7 @@ class Chef
resource_name :powershell_package
provides :powershell_package
- description "Use the powershell_package resource to install and manage packages via the PowerShell Package Manager for the Microsoft Windows platform. The powershell_package resource requires administrative access, and a source must be configured in the PowerShell Package Manager via the Register-PackageSource command"
+ description "Use the powershell_package resource to install and manage packages via the PowerShell Package Manager for the Microsoft Windows platform. The powershell_package resource requires administrative access, and a source must be configured in the PowerShell Package Manager via the powershell_package_source resource."
introduced "12.16"
allowed_actions :install, :remove
@@ -45,7 +45,7 @@ class Chef
property :skip_publisher_check, [true, false],
description: "Skip validating module author.",
- default: false, introduced: "14.3"
+ default: false, introduced: "14.3", desired_state: false
end
end
diff --git a/lib/chef/resource/remote_directory.rb b/lib/chef/resource/remote_directory.rb
index f03b13ef02..dd7077b9ae 100644
--- a/lib/chef/resource/remote_directory.rb
+++ b/lib/chef/resource/remote_directory.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,62 +26,59 @@ class Chef
class RemoteDirectory < Chef::Resource::Directory
include Chef::Mixin::Securable
- description "Use the remote_directory resource to incrementally transfer a directory"\
- " from a cookbook to a node. The director that is copied from the cookbook"\
- " should be located under COOKBOOK_NAME/files/default/REMOTE_DIRECTORY. The"\
- " remote_directory resource will obey file specificity."
-
- identity_attr :path
-
- state_attrs :files_owner, :files_group, :files_mode
+ description "Use the remote_directory resource to incrementally transfer a directory from a cookbook to a node. The director that is copied from the cookbook should be located under COOKBOOK_NAME/files/default/REMOTE_DIRECTORY. The remote_directory resource will obey file specificity."
default_action :create
allowed_actions :create, :create_if_missing, :delete
def initialize(name, run_context = nil)
super
- @path = name
@delete = false
- @recursive = true
- @files_owner = nil
- @files_group = nil
- @files_mode = 0644 unless Chef::Platform.windows?
end
if Chef::Platform.windows?
- # create a second instance of the 'rights' attribute
+ # create a second instance of the 'rights' attribute (property)
rights_attribute(:files_rights)
end
- property :source, String, default: lazy { ::File.basename(path) }
- property :files_backup, [ Integer, FalseClass ], default: 5, desired_state: false
- property :purge, [ TrueClass, FalseClass ], default: false, desired_state: false
- property :overwrite, [ TrueClass, FalseClass ], default: true
- property :cookbook, String
+ # This same property exists in the directory resource, but we need to change the default to true here.
+ property :recursive, [ TrueClass, FalseClass ],
+ description: "Create or delete parent directories recursively. For the owner, group, and mode properties, the value of this attribute applies only to the leaf directory.",
+ default: true, desired_state: false
- def files_group(arg = nil)
- set_or_return(
- :files_group,
- arg,
- regex: Chef::Config[:group_valid_regex]
- )
- end
+ property :source, String,
+ description: "The base name of the source file (and inferred from the path property).",
+ default_description: "The base portion of the 'path' property. For example '/some/path/' would be 'path'.",
+ default: lazy { ::File.basename(path) }, desired_state: false
- def files_mode(arg = nil)
- set_or_return(
- :files_mode,
- arg,
- regex: /^\d{3,4}$/
- )
- end
+ property :files_backup, [ Integer, FalseClass ],
+ description: "The number of backup copies to keep for files in the directory.",
+ default: 5, desired_state: false
- def files_owner(arg = nil)
- set_or_return(
- :files_owner,
- arg,
- regex: Chef::Config[:user_valid_regex]
- )
- end
+ property :purge, [ TrueClass, FalseClass ],
+ description: "Purge extra files found in the target directory.",
+ default: false, desired_state: false
+
+ property :overwrite, [ TrueClass, FalseClass ],
+ description: "Overwrite a file when it is different.",
+ default: true, desired_state: false
+
+ property :cookbook, String,
+ description: "The cookbook in which a file is located (if it is not located in the current cookbook). The default value is the current cookbook.",
+ desired_state: false
+
+ property :files_group, [String, Integer],
+ description: "Configure group permissions for files. A string or ID that identifies the group owner by group name, including fully qualified group names such as domain\\group or group@domain. If this value is not specified, existing groups remain unchanged and new group assignments use the default POSIX group (if available).",
+ regex: Chef::Config[:group_valid_regex]
+
+ property :files_mode, [String, Integer, nil],
+ description: "The octal mode for a file.\n UNIX- and Linux-based systems: A quoted 3-5 character string that defines the octal mode that is passed to chmod. For example: '755', '0755', or 00755. If the value is specified as a quoted string, it works exactly as if the chmod command was passed. If the value is specified as an integer, prepend a zero (0) to the value to ensure that it is interpreted as an octal number. For example, to assign read, write, and execute rights for all users, use '0777' or '777'; for the same rights, plus the sticky bit, use 01777 or '1777'.\n Microsoft Windows: A quoted 3-5 character string that defines the octal mode that is translated into rights for Microsoft Windows security. For example: '755', '0755', or 00755. Values up to '0777' are allowed (no sticky bits) and mean the same in Microsoft Windows as they do in UNIX, where 4 equals GENERIC_READ, 2 equals GENERIC_WRITE, and 1 equals GENERIC_EXECUTE. This property cannot be used to set :full_control. This property has no effect if not specified, but when it and rights are both specified, the effects are cumulative.",
+ default_description: "0644 on *nix systems",
+ regex: /^\d{3,4}$/, default: lazy { 0644 unless Chef::Platform.windows? }
+
+ property :files_owner, [String, Integer],
+ description: "Configure owner permissions for files. A string or ID that identifies the group owner by user name, including fully qualified user names such as domain\\user or user@domain. If this value is not specified, existing owners remain unchanged and new owner assignments use the current user (when necessary).",
+ regex: Chef::Config[:user_valid_regex]
end
end
end
diff --git a/lib/chef/resource/rhsm_errata.rb b/lib/chef/resource/rhsm_errata.rb
index 11aa49c34a..e37278de79 100644
--- a/lib/chef/resource/rhsm_errata.rb
+++ b/lib/chef/resource/rhsm_errata.rb
@@ -29,7 +29,7 @@ class Chef
introduced "14.0"
property :errata_id, String,
- description: "An optional property for specifying the errata ID if not using the resource's name.",
+ description: "An optional property for specifying the errata ID if it differs from the resource block's name.",
name_property: true
action :install do
diff --git a/lib/chef/resource/rhsm_errata_level.rb b/lib/chef/resource/rhsm_errata_level.rb
index 213487537b..1e82ee73aa 100644
--- a/lib/chef/resource/rhsm_errata_level.rb
+++ b/lib/chef/resource/rhsm_errata_level.rb
@@ -29,7 +29,7 @@ class Chef
property :errata_level, String,
coerce: proc { |x| x.downcase },
equal_to: %w{critical moderate important low},
- description: "The errata level of packages to install.",
+ description: "An optional property for specifying the errata level of packages to install if it differs from the resource block's name.",
name_property: true
action :install do
diff --git a/lib/chef/resource/rhsm_register.rb b/lib/chef/resource/rhsm_register.rb
index cf1a131c44..4e10e3a03d 100644
--- a/lib/chef/resource/rhsm_register.rb
+++ b/lib/chef/resource/rhsm_register.rb
@@ -30,22 +30,22 @@ class Chef
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."
+ description: "A string or array of activation keys to use when registering; you must also specify the 'organization' property when using this property."
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."
+ description: "The FQDN of the Satellite host to register with. If this property is not specified, the host will register with Red Hat's public RHSM service."
property :organization, String,
- description: "The organization to use when registering, required when using an activation key."
+ description: "The organization to use when registering; required when using the 'activation_key' property."
property :environment, String,
- description: "The environment to use when registering, required when using username and password."
+ description: "The environment to use when registering; required when using the username and password properties."
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."
+ description: "The username to use when registering. This property is not applicable if using an activation key. If specified, password and environment properties 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."
+ description: "The password to use when registering. This property is not applicable if using an activation key. If specified, username and environment are also required."
property :auto_attach,
[TrueClass, FalseClass],
@@ -57,7 +57,7 @@ class Chef
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.",
+ description: "If true, the system will be registered even if it is already registered. Normally, any register operations will fail if the machine has already been registered.",
default: false, desired_state: false
action :register do
diff --git a/lib/chef/resource/rhsm_repo.rb b/lib/chef/resource/rhsm_repo.rb
index 86857be211..943abc3331 100644
--- a/lib/chef/resource/rhsm_repo.rb
+++ b/lib/chef/resource/rhsm_repo.rb
@@ -28,7 +28,7 @@ class Chef
introduced "14.0"
property :repo_name, String,
- description: "An optional property for specifying the repository name if not using the resource's name.",
+ description: "An optional property for specifying the repository name if it differs from the resource block's name.",
name_property: true
action :enable do
diff --git a/lib/chef/resource/rhsm_subscription.rb b/lib/chef/resource/rhsm_subscription.rb
index f00f801afa..52f4c41653 100644
--- a/lib/chef/resource/rhsm_subscription.rb
+++ b/lib/chef/resource/rhsm_subscription.rb
@@ -29,7 +29,7 @@ class Chef
introduced "14.0"
property :pool_id, String,
- description: "An optional property for specifying the Pool ID if not using the resource's name.",
+ description: "An optional property for specifying the Pool ID if it differs from the resource block's name.",
name_property: true
action :attach do
diff --git a/lib/chef/resource/route.rb b/lib/chef/resource/route.rb
index 8c14394ace..45a1266fd7 100644
--- a/lib/chef/resource/route.rb
+++ b/lib/chef/resource/route.rb
@@ -27,20 +27,30 @@ class Chef
description "Use the route resource to manage the system routing table in a Linux environment."
- property :target, String, identity: true, name_property: true
- property :comment, [String, nil], introduced: "14.0"
- property :metric, [Integer, nil]
- property :netmask, [String, nil]
- property :gateway, [String, nil]
- property :device, [String, nil], desired_state: false # Has a partial default in the provider of eth0.
- property :route_type, [:host, :net], default: :host, coerce: proc { |x| x.to_sym }, desired_state: false
-
- # I can find no evidence of these properties actually being used by Chef. NK 2017-04-11
- property :networking, [String, nil], desired_state: false
- property :networking_ipv6, [String, nil], desired_state: false
- property :hostname, [String, nil], desired_state: false
- property :domainname, [String, nil], desired_state: false
- property :domain, [String, nil], desired_state: false
+ property :target, String,
+ description: "The IP address of the target route.",
+ identity: true, name_property: true
+
+ property :comment, [String, nil],
+ description: "Add a comment for the route.",
+ introduced: "14.0"
+
+ property :metric, [Integer, nil],
+ description: "The route metric value."
+
+ property :netmask, [String, nil],
+ description: "The decimal representation of the network mask. For example: 255.255.255.0."
+
+ property :gateway, [String, nil],
+ description: "The gateway for the route."
+
+ property :device, [String, nil],
+ description: "The network interface to which the route applies.",
+ desired_state: false # Has a partial default in the provider of eth0.
+
+ property :route_type, [Symbol, String],
+ description: "",
+ equal_to: [:host, :net], default: :host, desired_state: false
end
end
end
diff --git a/lib/chef/resource/rpm_package.rb b/lib/chef/resource/rpm_package.rb
index 4d79ba98d1..cf408cd094 100644
--- a/lib/chef/resource/rpm_package.rb
+++ b/lib/chef/resource/rpm_package.rb
@@ -26,7 +26,7 @@ class Chef
description "Use the rpm_package resource to manage packages for the RPM Package Manager platform."
- property :allow_downgrade, [ true, false ], default: false, desired_state: false
+ property :allow_downgrade, [ true, false ], default: true, desired_state: false
end
end
diff --git a/lib/chef/resource/scm.rb b/lib/chef/resource/scm.rb
index 9346405e53..fb0e70ad44 100644
--- a/lib/chef/resource/scm.rb
+++ b/lib/chef/resource/scm.rb
@@ -66,7 +66,7 @@ class Chef
default: "deploy"
property :environment, [Hash, nil],
- description: "A Hash of environment variables in the form of ({'ENV_VARIABLE' => 'VALUE'}). (These variables must exist for a command to be run successfully.)",
+ description: "A Hash of environment variables in the form of ({'ENV_VARIABLE' => 'VALUE'}).",
default: nil
alias :env :environment
diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb
index c5197d5f06..4e808d6035 100644
--- a/lib/chef/resource/service.rb
+++ b/lib/chef/resource/service.rb
@@ -1,7 +1,7 @@
#
# Author:: AJ Christensen (<aj@hjksolutions.com>)
# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,8 +25,6 @@ class Chef
class Service < Chef::Resource
identity_attr :service_name
- state_attrs :enabled, :running, :masked
-
description "Use the service resource to manage a service."
default_action :nothing
@@ -35,137 +33,64 @@ class Chef
# this is a poor API please do not re-use this pattern
property :supports, Hash, default: { restart: nil, reload: nil, status: nil },
- coerce: proc { |x| x.is_a?(Array) ? x.each_with_object({}) { |i, m| m[i] = true } : x }
-
- def initialize(name, run_context = nil)
- super
- @service_name = name
- @enabled = nil
- @running = nil
- @masked = nil
- @options = nil
- @parameters = nil
- @pattern = service_name
- @start_command = nil
- @stop_command = nil
- @status_command = nil
- @restart_command = nil
- @reload_command = nil
- @init_command = nil
- @priority = nil
- @timeout = nil
- @run_levels = nil
- @user = nil
- end
-
- def service_name(arg = nil)
- set_or_return(
- :service_name,
- arg,
- kind_of: [ String ]
- )
- end
+ description: "A list of properties that controls how the chef-client is to attempt to manage a service: :restart, :reload, :status. For :restart, the init script or other service provider can use a restart command; if :restart is not specified, the chef-client attempts to stop and then start a service. For :reload, the init script or other service provider can use a reload command. For :status, the init script or other service provider can use a status command to determine if the service is running; if :status is not specified, the chef-client attempts to match the service_name against the process table as a regular expression, unless a pattern is specified as a parameter property. Default value: { restart: false, reload: false, status: false } for all platforms (except for the Red Hat platform family, which defaults to { restart: false, reload: false, status: true }.)",
+ coerce: proc { |x| x.is_a?(Array) ? x.each_with_object({}) { |i, m| m[i] = true } : x }
+
+ property :service_name, String,
+ description: "An optional property to set the service name if it differs from the resource block's name.",
+ name_property: true, identity: true
# regex for match against ps -ef when !supports[:has_status] && status == nil
- def pattern(arg = nil)
- set_or_return(
- :pattern,
- arg,
- kind_of: [ String ]
- )
- end
+ property :pattern, String,
+ description: "The pattern to look for in the process table.",
+ default_description: "The value provided to 'service_name' or the resource block's name",
+ default: lazy { service_name }, desired_state: false
# command to call to start service
- def start_command(arg = nil)
- set_or_return(
- :start_command,
- arg,
- kind_of: [ String, NilClass, FalseClass ]
- )
- end
+ property :start_command, [ String, nil, FalseClass ],
+ description: "The command used to start a service.",
+ desired_state: false
# command to call to stop service
- def stop_command(arg = nil)
- set_or_return(
- :stop_command,
- arg,
- kind_of: [ String, NilClass, FalseClass ]
- )
- end
+ property :stop_command, [ String, nil, FalseClass ],
+ description: "The command used to stop a service.",
+ desired_state: false
# command to call to get status of service
- def status_command(arg = nil)
- set_or_return(
- :status_command,
- arg,
- kind_of: [ String, NilClass, FalseClass ]
- )
- end
+ property :status_command, [ String, nil, FalseClass ],
+ description: "The command used to check the run status for a service.",
+ desired_state: false
# command to call to restart service
- def restart_command(arg = nil)
- set_or_return(
- :restart_command,
- arg,
- kind_of: [ String, NilClass, FalseClass ]
- )
- end
-
- def reload_command(arg = nil)
- set_or_return(
- :reload_command,
- arg,
- kind_of: [ String, NilClass, FalseClass ]
- )
- end
+ property :restart_command, [ String, nil, FalseClass ],
+ description: "The command used to restart a service.",
+ desired_state: false
+
+ property :reload_command, [ String, nil, FalseClass ],
+ description: "The command used to tell a service to reload its configuration.",
+ desired_state: false
# The path to the init script associated with the service. On many
# distributions this is '/etc/init.d/SERVICE_NAME' by default. In
# non-standard configurations setting this value will save having to
# specify overrides for the start_command, stop_command and
# restart_command properties.
- def init_command(arg = nil)
- set_or_return(
- :init_command,
- arg,
- kind_of: [ String ]
- )
- end
+ property :init_command, String,
+ description: "The path to the init script that is associated with the service. Use init_command to prevent the need to specify overrides for the start_command, stop_command, and restart_command properties. When this property is not specified, the chef-client will use the default init command for the service provider being used.",
+ desired_state: false
# if the service is enabled or not
- def enabled(arg = nil)
- set_or_return(
- :enabled,
- arg,
- kind_of: [ TrueClass, FalseClass ]
- )
- end
+ property :enabled, [ TrueClass, FalseClass ], skip_docs: true
# if the service is running or not
- def running(arg = nil)
- set_or_return(
- :running,
- arg,
- kind_of: [ TrueClass, FalseClass ]
- )
- end
+ property :running, [ TrueClass, FalseClass ], skip_docs: true
# if the service is masked or not
- def masked(arg = nil)
- set_or_return(
- :masked,
- arg,
- kind_of: [ TrueClass, FalseClass ]
- )
- end
-
- def options(arg = nil)
- set_or_return(
- :options,
- arg.respond_to?(:split) ? arg.shellsplit : arg,
- kind_of: [ Array, String ]
- )
- end
+ property :masked, [ TrueClass, FalseClass ], skip_docs: true
+
+ property :options, [ Array, String ],
+ description: "Solaris platform only. Options to pass to the service command. See the svcadm manual for details of possible options.",
+ coerce: proc { |x| x.respond_to?(:split) ? x.shellsplit : x }
# Priority arguments can have two forms:
#
@@ -177,45 +102,23 @@ class Chef
# runlevel 2, stopped in 3 with priority 55 and no symlinks or
# similar for other runlevels
#
- def priority(arg = nil)
- set_or_return(
- :priority,
- arg,
- kind_of: [ Integer, String, Hash ]
- )
- end
+ property :priority, [ Integer, String, Hash ],
+ description: "Debian platform only. The relative priority of the program for start and shutdown ordering. May be an integer or a Hash. An integer is used to define the start run levels; stop run levels are then 100-integer. A Hash is used to define values for specific run levels. For example, { 2 => [:start, 20], 3 => [:stop, 55] } will set a priority of twenty for run level two and a priority of fifty-five for run level three."
# timeout only applies to the windows service manager
- def timeout(arg = nil)
- set_or_return(
- :timeout,
- arg,
- kind_of: Integer
- )
- end
-
- def parameters(arg = nil)
- set_or_return(
- :parameters,
- arg,
- kind_of: [ Hash ]
- )
- end
-
- def run_levels(arg = nil)
- set_or_return(
- :run_levels,
- arg,
- kind_of: [ Array ] )
- end
-
- def user(arg = nil)
- set_or_return(
- :user,
- arg,
- kind_of: [ String ]
- )
- end
+ property :timeout, Integer,
+ description: "Microsoft Windows platform only. The amount of time (in seconds) to wait before timing out.",
+ desired_state: false
+
+ property :parameters, Hash,
+ description: "Upstart only: A hash of parameters to pass to the service command for use in the service definition."
+
+ property :run_levels, Array,
+ description: "RHEL platforms only: Specific run_levels the service will run under."
+
+ property :user, String,
+ description: "systemd only: A username to run the service under.",
+ introduced: "12.21"
end
end
end
diff --git a/lib/chef/resource/ssh_known_hosts_entry.rb b/lib/chef/resource/ssh_known_hosts_entry.rb
index 5685a069a7..167ac959e8 100644
--- a/lib/chef/resource/ssh_known_hosts_entry.rb
+++ b/lib/chef/resource/ssh_known_hosts_entry.rb
@@ -50,11 +50,11 @@ class Chef
description: "The file mode for the ssh_known_hosts file.",
default: "0644"
- property :owner, String,
+ property :owner, [String, Integer],
description: "The file owner for the ssh_known_hosts file.",
default: "root"
- property :group, String,
+ property :group, [String, Integer],
description: "The file group for the ssh_known_hosts file.",
default: lazy { node["root_group"] }
diff --git a/lib/chef/resource/sudo.rb b/lib/chef/resource/sudo.rb
index c417a4d26c..9ace6ee359 100644
--- a/lib/chef/resource/sudo.rb
+++ b/lib/chef/resource/sudo.rb
@@ -37,17 +37,17 @@ class Chef
# acording to the sudo man pages sudo will ignore files in an include dir that have a `.` or `~`
# We convert either to `__`
property :filename, String,
- description: "The name of the sudoers.d file.",
+ description: "The name of the sudoers.d file, if it differs from the name of the resource block",
name_property: true,
coerce: proc { |x| x.gsub(/[\.~]/, "__") }
property :users, [String, Array],
- description: "User(s) to provide sudo privileges to. This accepts either an array or a comma separated.",
+ description: "User(s) to provide sudo privileges to. This property accepts either an array or a comma separated list.",
default: lazy { [] },
coerce: proc { |x| x.is_a?(Array) ? x : x.split(/\s*,\s*/) }
property :groups, [String, Array],
- description: "Group(s) to provide sudo privileges to. This accepts either an array or a comma separated list. Leading % on group names is optional.",
+ description: "Group(s) to provide sudo privileges to. This property accepts either an array or a comma separated list. Leading % on group names is optional.",
default: lazy { [] },
coerce: proc { |x| coerce_groups(x) }
@@ -72,10 +72,10 @@ class Chef
default: false
property :template, String,
- description: "The name of the erb template in your cookbook if you wish to supply your own template."
+ description: "The name of the erb template in your cookbook, if you wish to supply your own template."
property :variables, [Hash, nil],
- description: "The variables to pass to the custom template. Ignored if not using a custom template.",
+ description: "The variables to pass to the custom template. This property is ignored if not using a custom template.",
default: nil
property :defaults, Array,
@@ -99,15 +99,15 @@ class Chef
default: lazy { [] }
property :visudo_path, String,
- description: "Deprecated property. Do not use."
+ deprecated: true
property :visudo_binary, String,
description: "The path to visudo for configuration verification.",
default: "/usr/sbin/visudo"
property :config_prefix, String,
- description: "The directory that contains the sudoers configuration file",
- default: lazy { platform_config_prefix }
+ description: "The directory that contains the sudoers configuration file.",
+ default: lazy { platform_config_prefix }, default_description: "Prefix values based on the node's platform"
# handle legacy cookbook property
def after_created
diff --git a/lib/chef/resource/swap_file.rb b/lib/chef/resource/swap_file.rb
index c42c7b6d59..f4f95cb28c 100644
--- a/lib/chef/resource/swap_file.rb
+++ b/lib/chef/resource/swap_file.rb
@@ -27,7 +27,7 @@ class Chef
introduced "14.0"
property :path, String,
- description: "The path to put the swap file on the system.",
+ description: "The path where the swap file will be created on the system, if it differs from the resource block's name.",
name_property: true
property :size, Integer,
diff --git a/lib/chef/resource/sysctl.rb b/lib/chef/resource/sysctl.rb
index 10d6177221..a5568904ba 100644
--- a/lib/chef/resource/sysctl.rb
+++ b/lib/chef/resource/sysctl.rb
@@ -24,7 +24,7 @@ class Chef
provides(:sysctl) { true }
provides(:sysctl_param) { true }
- description "Use the sysctl resource to set kernel parameters using the sysctl"\
+ description "Use the sysctl resource to set or remove kernel parameters using the sysctl"\
" command line tool and configuration files in the system's sysctl.d directory. "\
"Configuration files managed by this resource are named 99-chef-KEYNAME.conf. If"\
" an existing value was already set for the value it will be backed up to the node"\
@@ -33,7 +33,7 @@ class Chef
introduced "14.0"
property :key, String,
- description: "The kernel parameter key in dotted format.",
+ description: "The kernel parameter key in dotted format, if it differs from the resource block's name.",
name_property: true
property :ignore_error, [TrueClass, FalseClass],
diff --git a/lib/chef/resource/systemd_unit.rb b/lib/chef/resource/systemd_unit.rb
index fe4d88ccd2..89bc30b9d1 100644
--- a/lib/chef/resource/systemd_unit.rb
+++ b/lib/chef/resource/systemd_unit.rb
@@ -38,22 +38,30 @@ class Chef
:reload_or_try_restart
# Internal provider-managed properties
- property :enabled, [TrueClass, FalseClass]
- property :active, [TrueClass, FalseClass]
- property :masked, [TrueClass, FalseClass]
- property :static, [TrueClass, FalseClass]
+ property :enabled, [TrueClass, FalseClass], skip_docs: true
+ property :active, [TrueClass, FalseClass], skip_docs: true
+ property :masked, [TrueClass, FalseClass], skip_docs: true
+ property :static, [TrueClass, FalseClass], skip_docs: true
# User-provided properties
- property :user, String, desired_state: false
- property :content, [String, Hash]
+ property :user, String, desired_state: false,
+ description: "The user account that the systemd unit process is run under. The path to the unit for that user would be something like '/etc/systemd/user/sshd.service'. If no user account is specified, the systemd unit will run under a 'system' account, with the path to the unit being something like '/etc/systemd/system/sshd.service'."
+
+ property :content, [String, Hash],
+ description: "A string or hash that contains a systemd `unit file <https://www.freedesktop.org/software/systemd/man/systemd.unit.html>`_ definition that describes the properties of systemd-managed entities, such as services, sockets, devices, and so on. In Chef 14.4 or later, repeatable options can be implemented with an array."
+
property :triggers_reload, [TrueClass, FalseClass],
- default: true, desired_state: false
+ description: "Specifies whether to trigger a daemon reload when creating or deleting a unit.",
+ default: true, desired_state: false
+
property :verify, [TrueClass, FalseClass],
- default: true, desired_state: false
+ default: true, desired_state: false,
+ description: "Specifies if the unit will be verified before installation. Systemd can be overly strict when verifying units, so in certain cases it is preferable not to verify the unit."
+
property :unit_name, String, desired_state: false,
- identity: true,
- name_property: true,
- introduced: "13.7"
+ identity: true, name_property: true,
+ description: "The name of the unit file if it differs from the resource block's name.",
+ introduced: "13.7"
def to_ini
case content
diff --git a/lib/chef/resource/template.rb b/lib/chef/resource/template.rb
index 26e85cc679..bd8325f2c1 100644
--- a/lib/chef/resource/template.rb
+++ b/lib/chef/resource/template.rb
@@ -57,9 +57,17 @@ class Chef
)
end
- property :variables, Hash, default: lazy { Hash.new }
- property :cookbook, String
- property :local, [ TrueClass, FalseClass ], default: false
+ property :variables, Hash,
+ description: "The variables property of the template resource can be used to reference a partial template file by using a Hash.",
+ default: lazy { Hash.new }
+
+ property :cookbook, String,
+ description: "The cookbook in which a file is located (if it is not located in the current cookbook). The default value is the current cookbook.",
+ desired_state: false
+
+ property :local, [ TrueClass, FalseClass ],
+ default: false, desired_state: false,
+ description: "Load a template from a local path. By default, the chef-client loads templates from a cookbook’s /templates directory. When this property is set to true, use the source property to specify the path to a template on the local node."
# Declares a helper method to be defined in the template context when
# rendering.
diff --git a/lib/chef/resource/timezone.rb b/lib/chef/resource/timezone.rb
index 25d2c2cd73..29c65b696c 100644
--- a/lib/chef/resource/timezone.rb
+++ b/lib/chef/resource/timezone.rb
@@ -97,7 +97,7 @@ class Chef
end
when "windows"
unless current_windows_tz.casecmp?(new_resource.timezone)
- converge_by("set timezone to \"#{new_resource.timezone}\"") do
+ converge_by("setting timezone to \"#{new_resource.timezone}\"") do
shell_out!("tzutil /s \"#{new_resource.timezone}\"")
end
end
@@ -106,7 +106,7 @@ class Chef
end
action_class do
- # detect the current TZ on darwin hosts & windows hosts
+ # detect the current TZ on darwin hosts
#
# @since 14.7
# @return [String] TZ database value
@@ -118,13 +118,15 @@ class Chef
/Time Zone: (.*)/.match(tz_shellout.stdout)[1]
end
end
+
+ # detect the current timezone on windows hosts
+ #
+ # @since 14.7
+ # @return [String] timezone id
def current_windows_tz
- tz_shellout = shell_out!("tzutil /g")
- if /is not recognized as an internal/.match?(tz_shellout.stderr)
- raise "The timezone resource requires tzutil to run on windows hosts!"
- else
- tz_shellout.stdout.strip
- end
+ tz_shellout = shell_out("tzutil /g")
+ raise "There was an error running the tzutil command" if tz_shellout.exitstatus == 1
+ tz_shellout.stdout.strip
end
end
end
diff --git a/lib/chef/resource/windows_ad_join.rb b/lib/chef/resource/windows_ad_join.rb
index cb0f43e9d1..b3acacc703 100644
--- a/lib/chef/resource/windows_ad_join.rb
+++ b/lib/chef/resource/windows_ad_join.rb
@@ -58,14 +58,14 @@ class Chef
# define this again so we can default it to true. Otherwise failures print the password
property :sensitive, [TrueClass, FalseClass],
- default: true
+ default: true, desired_state: false
action :join do
description "Join the Active Directory domain."
unless on_domain?
cmd = "$pswd = ConvertTo-SecureString \'#{new_resource.domain_password}\' -AsPlainText -Force;"
- cmd << "$credential = New-Object System.Management.Automation.PSCredential (\"#{new_resource.domain_user}\",$pswd);"
+ cmd << "$credential = New-Object System.Management.Automation.PSCredential (\"#{new_resource.domain_user}@#{new_resource.domain_name}\",$pswd);"
cmd << "Add-Computer -DomainName #{new_resource.domain_name} -Credential $credential"
cmd << " -OUPath \"#{new_resource.ou_path}\"" if new_resource.ou_path
cmd << " -NewName \"#{new_resource.new_hostname}\"" if new_resource.new_hostname
diff --git a/lib/chef/resource/windows_auto_run.rb b/lib/chef/resource/windows_auto_run.rb
index 0ff8c24bfc..74c3d85520 100644
--- a/lib/chef/resource/windows_auto_run.rb
+++ b/lib/chef/resource/windows_auto_run.rb
@@ -28,7 +28,7 @@ class Chef
introduced "14.0"
property :program_name, String,
- description: "The name of the program to run at login if different from the resource name.",
+ description: "The name of the program to run at login, if it differs from the resource block's name.",
name_property: true
property :path, String,
diff --git a/lib/chef/resource/windows_certificate.rb b/lib/chef/resource/windows_certificate.rb
new file mode 100644
index 0000000000..053a67e3e0
--- /dev/null
+++ b/lib/chef/resource/windows_certificate.rb
@@ -0,0 +1,269 @@
+#
+# Author:: Richard Lavey (richard.lavey@calastone.com)
+#
+# Copyright:: 2015-2017, Calastone Ltd.
+# 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/util/path_helper"
+require "chef/resource"
+require "win32-certstore" if Chef::Platform.windows?
+require "openssl"
+
+class Chef
+ class Resource
+ class WindowsCertificate < Chef::Resource
+ resource_name :windows_certificate
+
+ description "Use the windows_certificate resource to install a certificate into the Windows certificate store from a file. The resource grants read-only access to the private key for designated accounts. Due to current limitations in WinRM, installing certificates remotely may not work if the operation requires a user profile. Operations on the local machine store should still work."
+ introduced "14.7"
+
+ property :source, String,
+ description: "The source file (for create and acl_add), thumbprint (for delete and acl_add) or subject (for delete).",
+ name_property: true
+
+ property :pfx_password, String,
+ description: "The password to access the source if it is a pfx file."
+
+ property :private_key_acl, Array,
+ description: "An array of 'domain\account' entries to be granted read-only access to the certificate's private key. Not idempotent."
+
+ property :store_name, String,
+ description: "The certificate store to manipulate.",
+ default: "MY", equal_to: ["TRUSTEDPUBLISHER", "TrustedPublisher", "CLIENTAUTHISSUER", "REMOTE DESKTOP", "ROOT", "TRUSTEDDEVICES", "WEBHOSTING", "CA", "AUTHROOT", "TRUSTEDPEOPLE", "MY", "SMARTCARDROOT", "TRUST", "DISALLOWED"]
+
+ property :user_store, [TrueClass, FalseClass],
+ description: "Use the user store of the local machine store if set to false.",
+ default: false
+
+ property :cert_path, String,
+ description: ""
+
+ # lazy used to set default value of sensitive to true if password is set
+ property :sensitive, [ TrueClass, FalseClass ],
+ description: "Ensure that sensitive resource data is not logged by the chef-client.",
+ default: lazy { |r| r.pfx_password ? true : false }, skip_docs: true
+
+ action :create do
+ description "Creates or updates a certificate."
+
+ add_cert(OpenSSL::X509::Certificate.new(raw_source))
+ end
+
+ # acl_add is a modify-if-exists operation : not idempotent
+ action :acl_add do
+ description "Adds read-only entries to a certificate's private key ACL."
+
+ if ::File.exist?(new_resource.source)
+ hash = "$cert.GetCertHashString()"
+ code_script = cert_script(false)
+ guard_script = cert_script(false)
+ else
+ # make sure we have no spaces in the hash string
+ hash = "\"#{new_resource.source.gsub(/\s/, '')}\""
+ code_script = ""
+ guard_script = ""
+ end
+ code_script << acl_script(hash)
+ guard_script << cert_exists_script(hash)
+
+ powershell_script "setting the acls on #{new_resource.source} in #{cert_location}\\#{new_resource.store_name}" do
+ guard_interpreter :powershell_script
+ convert_boolean_return true
+ code code_script
+ only_if guard_script
+ sensitive if new_resource.sensitive
+ end
+ end
+
+ action :delete do
+ description "Deletes a certificate."
+
+ delete_cert
+ end
+
+ action :fetch do
+ description "Fetches a certificate."
+
+ cert_obj = fetch_cert
+ if cert_obj
+ show_or_store_cert(cert_obj)
+ else
+ Chef::Log.info("Certificate not found")
+ end
+ end
+
+ action :verify do
+ description ""
+
+ out = verify_cert
+ if !!out == out
+ out = out ? "Certificate is valid" : "Certificate not valid"
+ end
+ Chef::Log.info(out.to_s)
+ end
+
+ action_class do
+ def add_cert(cert_obj)
+ store = ::Win32::Certstore.open(new_resource.store_name)
+ store.add(cert_obj)
+ end
+
+ def delete_cert
+ store = ::Win32::Certstore.open(new_resource.store_name)
+ store.delete(new_resource.source)
+ end
+
+ def fetch_cert
+ store = ::Win32::Certstore.open(new_resource.store_name)
+ store.get(new_resource.source)
+ end
+
+ def verify_cert
+ store = ::Win32::Certstore.open(new_resource.store_name)
+ store.valid?(new_resource.source)
+ end
+
+ def show_or_store_cert(cert_obj)
+ if new_resource.cert_path
+ export_cert(cert_obj, new_resource.cert_path)
+ if ::File.size(new_resource.cert_path) > 0
+ Chef::Log.info("Certificate export in #{new_resource.cert_path}")
+ else
+ ::File.delete(new_resource.cert_path)
+ end
+ else
+ Chef::Log.info(cert_obj.display)
+ end
+ end
+
+ def export_cert(cert_obj, cert_path)
+ out_file = ::File.new(cert_path, "w+")
+ case ::File.extname(cert_path)
+ when ".pem"
+ out_file.puts(cert_obj.to_pem)
+ when ".der"
+ out_file.puts(cert_obj.to_der)
+ when ".cer"
+ cert_out = powershell_out("openssl x509 -text -inform DER -in #{cert_obj.to_pem} -outform CER").stdout
+ out_file.puts(cert_out)
+ when ".crt"
+ cert_out = powershell_out("openssl x509 -text -inform DER -in #{cert_obj.to_pem} -outform CRT").stdout
+ out_file.puts(cert_out)
+ when ".pfx"
+ cert_out = powershell_out("openssl pkcs12 -export -nokeys -in #{cert_obj.to_pem} -outform PFX").stdout
+ out_file.puts(cert_out)
+ when ".p7b"
+ cert_out = powershell_out("openssl pkcs7 -export -nokeys -in #{cert_obj.to_pem} -outform P7B").stdout
+ out_file.puts(cert_out)
+ else
+ Chef::Log.info("Supported certificate format .pem, .der, .cer, .crt, .pfx and .p7b")
+ end
+ out_file.close
+ end
+
+ def cert_location
+ @location ||= new_resource.user_store ? "CurrentUser" : "LocalMachine"
+ end
+
+ def cert_script(persist)
+ cert_script = "$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2"
+ file = Chef::Util::PathHelper.cleanpath(new_resource.source)
+ cert_script << " \"#{file}\""
+ if ::File.extname(file.downcase) == ".pfx"
+ cert_script << ", \"#{new_resource.pfx_password}\""
+ if persist && new_resource.user_store
+ cert_script << ", ([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet)"
+ elsif persist
+ cert_script << ", ([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeyset)"
+ end
+ end
+ cert_script << "\n"
+ end
+
+ def cert_exists_script(hash)
+ <<-EOH
+ $hash = #{hash}
+ Test-Path "Cert:\\#{cert_location}\\#{new_resource.store_name}\\$hash"
+ EOH
+ end
+
+ def within_store_script
+ inner_script = yield "$store"
+ <<-EOH
+ $store = New-Object System.Security.Cryptography.X509Certificates.X509Store "#{new_resource.store_name}", ([System.Security.Cryptography.X509Certificates.StoreLocation]::#{cert_location})
+ $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
+ #{inner_script}
+ $store.Close()
+ EOH
+ end
+
+ def acl_script(hash)
+ return "" if new_resource.private_key_acl.nil? || new_resource.private_key_acl.empty?
+ # this PS came from http://blogs.technet.com/b/operationsguy/archive/2010/11/29/provide-access-to-private-keys-commandline-vs-powershell.aspx
+ # and from https://msdn.microsoft.com/en-us/library/windows/desktop/bb204778(v=vs.85).aspx
+ set_acl_script = <<-EOH
+ $hash = #{hash}
+ $storeCert = Get-ChildItem "cert:\\#{cert_location}\\#{new_resource.store_name}\\$hash"
+ if ($storeCert -eq $null) { throw 'no key exists.' }
+ $keyname = $storeCert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
+ if ($keyname -eq $null) { throw 'no private key exists.' }
+ if ($storeCert.PrivateKey.CspKeyContainerInfo.MachineKeyStore)
+ {
+ $fullpath = "$Env:ProgramData\\Microsoft\\Crypto\\RSA\\MachineKeys\\$keyname"
+ }
+ else
+ {
+ $currentUser = New-Object System.Security.Principal.NTAccount($Env:UserDomain, $Env:UserName)
+ $userSID = $currentUser.Translate([System.Security.Principal.SecurityIdentifier]).Value
+ $fullpath = "$Env:ProgramData\\Microsoft\\Crypto\\RSA\\$userSID\\$keyname"
+ }
+ EOH
+ new_resource.private_key_acl.each do |name|
+ set_acl_script << "$uname='#{name}'; icacls $fullpath /grant $uname`:RX\n"
+ end
+ set_acl_script
+ end
+
+ def raw_source
+ ext = ::File.extname(new_resource.source)
+ convert_pem(ext, new_resource.source)
+ end
+
+ def convert_pem(ext, source)
+ out = case ext
+ when ".crt", ".der"
+ powershell_out("openssl x509 -text -inform DER -in #{source} -outform PEM").stdout
+ when ".cer"
+ powershell_out("openssl x509 -text -inform DER -in #{source} -outform PEM").stdout
+ when ".pfx"
+ powershell_out("openssl pkcs12 -in #{source} -nodes -passin pass:#{new_resource.pfx_password}").stdout
+ when ".p7b"
+ powershell_out("openssl pkcs7 -print_certs -in #{source} -outform PEM").stdout
+ end
+ out = ::File.read(source) if out.nil? || out.empty?
+ format_raw_out(out)
+ end
+
+ def format_raw_out(out)
+ begin_cert = "-----BEGIN CERTIFICATE-----"
+ end_cert = "-----END CERTIFICATE-----"
+ begin_cert + out[/#{begin_cert}(.*?)#{end_cert}/m, 1] + end_cert
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/resource/windows_env.rb b/lib/chef/resource/windows_env.rb
index 781a09fed7..e08ae596a9 100644
--- a/lib/chef/resource/windows_env.rb
+++ b/lib/chef/resource/windows_env.rb
@@ -31,9 +31,18 @@ class Chef
default_action :create
allowed_actions :create, :delete, :modify
- property :key_name, String, identity: true, name_property: true
- property :value, String, required: true
- property :delim, [ String, nil, false ], desired_state: false
+ property :key_name, String,
+ description: "The name of the key that is to be created, deleted, or modified.",
+ identity: true, name_property: true
+
+ property :value, String,
+ description: "The value of the environmental variable to set.",
+ required: true
+
+ property :delim, [ String, nil, false ],
+ description: "The delimiter that is used to separate multiple values for a single key.",
+ desired_state: false
+
property :user, String, default: "<System>"
end
end
diff --git a/lib/chef/resource/windows_feature.rb b/lib/chef/resource/windows_feature.rb
index c80b875fbd..24f555a86c 100644
--- a/lib/chef/resource/windows_feature.rb
+++ b/lib/chef/resource/windows_feature.rb
@@ -24,35 +24,31 @@ class Chef
resource_name :windows_feature
provides(:windows_feature) { true }
- description "Use the windows_feature resource to add, remove or delete Windows features and roles. This resource calls"\
- " the 'windows_feature_dism' or 'windows_feature_powershell' resources depending on the specified installation"\
- " method and defaults to dism, which is available on both Workstation and Server editions of Windows."
+ description "Use the windows_feature resource to add, remove or entirely delete Windows features and roles. This resource calls the 'windows_feature_dism' or 'windows_feature_powershell' resources depending on the specified installation method and defaults to dism, which is available on both Workstation and Server editions of Windows."
introduced "14.0"
property :feature_name, [Array, String],
- description: "The name of the feature/role(s) to install. The same feature may have different"\
- " names depending on the underlying resource being used (ie DHCPServer vs DHCP;"\
- " DNS-Server-Full-Role vs DNS).",
+ description: "The name of the feature(s) or role(s) to install, if it differs from the resource block's name. The same feature may have different names depending on the underlying installation method being used (ie DHCPServer vs DHCP; DNS-Server-Full-Role vs DNS).",
name_property: true
property :source, String,
- description: "Use a local repository for the feature install."
+ description: "Specify a local repository for the feature install."
property :all, [TrueClass, FalseClass],
description: "Install all sub features.",
default: false
property :management_tools, [TrueClass, FalseClass],
- description: "Install all applicable management tools of the roles, role services, or features (PowerShell only).",
+ description: "Install all applicable management tools for the roles, role services, or features (PowerShell-only).",
default: false
property :install_method, Symbol,
- description: "If DISM or PowerShell should be used for the installation. Note feature names differ"\
- " between the two installation methods.",
- equal_to: [:windows_feature_dism, :windows_feature_powershell, :windows_feature_servermanagercmd]
+ description: "The underlying installation method to use for feature installation. Specify ':windows_feature_dism' for DISM or ':windows_feature_powershell' for PowerShell.",
+ equal_to: [:windows_feature_dism, :windows_feature_powershell, :windows_feature_servermanagercmd],
+ default: :windows_feature_dism
property :timeout, Integer,
- description: "Specifies a timeout (in seconds) for feature install.",
+ description: "Specifies a timeout (in seconds) for the feature installation.",
default: 600
action :install do
@@ -77,16 +73,15 @@ class Chef
# call the appropriate windows_feature resource based on the specified subresource
# @return [void]
def run_default_subresource(desired_action)
- raise "Support for Windows feature installation via servermanagercmd.exe has been removed as this support is no longer needed in Windows 2008 R2 and above. You will need to update your cookbook to install either via dism or powershell (preferred)." if new_resource.install_method == :windows_feature_servermanagercmd
+ raise "Support for Windows feature installation via servermanagercmd.exe has been removed as this support is no longer needed in Windows 2008 R2 and above. You will need to update your recipe to install either via dism or powershell (preferred)." if new_resource.install_method == :windows_feature_servermanagercmd
- subresource = new_resource.install_method || :windows_feature_dism
- declare_resource(subresource, new_resource.name) do
+ declare_resource(new_resource.install_method, new_resource.name) do
action desired_action
feature_name new_resource.feature_name
source new_resource.source if new_resource.source
all new_resource.all
timeout new_resource.timeout
- management_tools new_resource.management_tools if subresource == :windows_feature_powershell
+ management_tools new_resource.management_tools if new_resource.install_method == :windows_feature_powershell
end
end
end
diff --git a/lib/chef/resource/windows_feature_dism.rb b/lib/chef/resource/windows_feature_dism.rb
index 2c2d7fc431..214ad5bedd 100644
--- a/lib/chef/resource/windows_feature_dism.rb
+++ b/lib/chef/resource/windows_feature_dism.rb
@@ -25,7 +25,7 @@ class Chef
resource_name :windows_feature_dism
provides(:windows_feature_dism) { true }
- description "Use the windows_feature_dism resource to add, remove or delete Windows features and roles using DISM"
+ description "Use the windows_feature_dism resource to add, remove, or entirely delete Windows features and roles using DISM."
introduced "14.0"
property :feature_name, [Array, String],
@@ -41,7 +41,7 @@ class Chef
default: false
property :timeout, Integer,
- description: "Specifies a timeout (in seconds) for feature install.",
+ description: "Specifies a timeout (in seconds) for the feature installation.",
default: 600
# @return [Array] lowercase the array unless we're on < Windows 2012
@@ -57,7 +57,6 @@ class Chef
reload_cached_dism_data unless node["dism_features_cache"]
fail_if_unavailable # fail if the features don't exist
- fail_if_removed # fail if the features are in removed state
logger.trace("Windows features needing installation: #{features_to_install.empty? ? 'none' : features_to_install.join(',')}")
unless features_to_install.empty?
@@ -66,8 +65,12 @@ class Chef
install_command = "dism.exe /online /enable-feature #{features_to_install.map { |f| "/featurename:#{f}" }.join(' ')} /norestart"
install_command << " /LimitAccess /Source:\"#{new_resource.source}\"" if new_resource.source
install_command << " /All" if new_resource.all
-
- shell_out!(install_command, returns: [0, 42, 127, 3010], timeout: new_resource.timeout)
+ begin
+ shell_out!(install_command, returns: [0, 42, 127, 3010], timeout: new_resource.timeout)
+ rescue Mixlib::ShellOut::ShellCommandFailed => e
+ raise "Error 50 returned by DISM related to parent features, try setting the 'all' property to 'true' on the 'windows_feature_dism' resource." if required_parent_feature?(e.inspect)
+ raise e.message
+ end
reload_cached_dism_data # Reload cached dism feature state
end
@@ -118,10 +121,10 @@ class Chef
# disabled features are always available to install
available_for_install = node["dism_features_cache"]["disabled"].dup
- # if the user passes a source then removed features are also available for installation
- available_for_install.concat(node["dism_features_cache"]["removed"]) if new_resource.source
+ # removed features are also available for installation
+ available_for_install.concat(node["dism_features_cache"]["removed"])
- # the intersection of the features to install & disabled/removed(if passing source) features are what needs installing
+ # the intersection of the features to install & disabled/removed features are what needs installing
new_resource.feature_name & available_for_install
end
end
@@ -204,22 +207,15 @@ class Chef
node.override["dism_features_cache"][feature_type] << feature_details
end
- # Fail if any of the packages are in a removed state
- # @return [void]
- def fail_if_removed
- return if new_resource.source # if someone provides a source then all is well
- if node["platform_version"].to_f > 6.2 # 2012R2 or later
- return if registry_key_exists?('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Servicing') && registry_value_exists?('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Servicing', name: "LocalSourcePath") # if source is defined in the registry, still fine
- end
- removed = new_resource.feature_name & node["dism_features_cache"]["removed"]
- raise "The Windows feature#{'s' if removed.count > 1} #{removed.join(',')} #{removed.count > 1 ? 'are' : 'is'} removed from the host and cannot be installed." unless removed.empty?
- end
-
# Fail unless we're on windows 8+ / 2012+ where deleting a feature is supported
# @return [void]
def raise_if_delete_unsupported
raise Chef::Exceptions::UnsupportedAction, "#{self} :delete action not supported on Windows releases before Windows 8/2012. Cannot continue!" if older_than_win_2012_or_8?
end
+
+ def required_parent_feature?(error_message)
+ error_message.include?("Error: 50") && error_message.include?("required parent feature")
+ end
end
end
end
diff --git a/lib/chef/resource/windows_feature_powershell.rb b/lib/chef/resource/windows_feature_powershell.rb
index ff9a501815..9a7b725575 100644
--- a/lib/chef/resource/windows_feature_powershell.rb
+++ b/lib/chef/resource/windows_feature_powershell.rb
@@ -27,27 +27,23 @@ class Chef
resource_name :windows_feature_powershell
provides(:windows_feature_powershell) { true }
- description "Use the windows_feature_powershell resource to add, remove or"\
- " delete Windows features and roles using PowerShell. This resource"\
- " offers significant speed benefits over the windows_feature_dism resource,"\
- " but requires installing the Remote Server Administration Tools on"\
- " non-server releases of Windows"
+ description "Use the windows_feature_powershell resource to add, remove, or entirely delete Windows features and roles using PowerShell. This resource offers significant speed benefits over the windows_feature_dism resource, but requires installing the Remote Server Administration Tools on non-server releases of Windows."
introduced "14.0"
property :feature_name, [Array, String],
- description: "The name of the feature/role(s) to install if it differs from the resource name.",
+ description: "The name of the feature(s) or role(s) to install, if it differs from the resource block's name.",
coerce: proc { |x| to_formatted_array(x) },
name_property: true
property :source, String,
- description: "Use a local repository for the feature install."
+ description: "Specify a local repository for the feature install."
property :all, [TrueClass, FalseClass],
- description: "Install all sub features. This is equivalent to using the -InstallAllSubFeatures switch with Add-WindowsFeature.",
+ description: "Install all subfeatures. When set to 'true', this is the equivalent of specifying the '-InstallAllSubFeatures' switch with 'Add-WindowsFeature'.",
default: false
property :timeout, Integer,
- description: "Specifies a timeout (in seconds) for feature install.",
+ description: "Specifies a timeout (in seconds) for the feature installation.",
default: 600
property :management_tools, [TrueClass, FalseClass],
diff --git a/lib/chef/resource/windows_firewall_rule.rb b/lib/chef/resource/windows_firewall_rule.rb
new file mode 100644
index 0000000000..0e313eb14a
--- /dev/null
+++ b/lib/chef/resource/windows_firewall_rule.rb
@@ -0,0 +1,204 @@
+# Author:: Matt Clifton (spartacus003@hotmail.com)
+# Author:: Matt Stratton (matt.stratton@gmail.com)
+# Author:: Tor Magnus Rakvåg (tor.magnus@outlook.com)
+# Author:: Tim Smith (tsmith@chef.io)
+# Copyright:: 2013-2015 Matt Clifton
+# Copyright:: 2018, Chef Software, Inc.
+# Copyright:: 2018, Intility AS
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/json_compat"
+
+class Chef
+ class Resource
+ class WindowsFirewallRule < Chef::Resource
+ resource_name :windows_firewall_rule
+
+ description "Use the windows_firewall_rule resource to create, change or remove windows firewall rules."
+ introduced "14.7"
+
+ property :rule_name, String,
+ name_property: true,
+ description: "The name to assign to the firewall rule."
+
+ property :description, String,
+ default: "Firewall rule",
+ description: "The description to assign to the firewall rule."
+
+ property :local_address, String,
+ description: "The local address the firewall rule applies to."
+
+ property :local_port, [String, Integer, Array],
+ # split various formats of comma separated lists and provide a sorted array of strings to match PS output
+ coerce: proc { |d| d.is_a?(String) ? d.split(/\s*,\s*/).sort : Array(d).sort.map { |x| x.to_s } },
+ description: "The local port the firewall rule applies to."
+
+ property :remote_address, String,
+ description: "The remote address the firewall rule applies to."
+
+ property :remote_port, [String, Integer, Array],
+ # split various formats of comma separated lists and provide a sorted array of strings to match PS output
+ coerce: proc { |d| d.is_a?(String) ? d.split(/\s*,\s*/).sort : Array(d).sort.map { |x| x.to_s } },
+ description: "The remote port the firewall rule applies to."
+
+ property :direction, [Symbol, String],
+ default: :inbound, equal_to: [:inbound, :outbound],
+ description: "The direction of the firewall rule. Direction means either inbound or outbound traffic.",
+ coerce: proc { |d| d.is_a?(String) ? d.downcase.to_sym : d }
+
+ property :protocol, String,
+ default: "TCP",
+ description: "The protocol the firewall rule applies to."
+
+ property :firewall_action, [Symbol, String],
+ default: :allow, equal_to: [:allow, :block, :notconfigured],
+ description: "The action of the firewall rule.",
+ coerce: proc { |f| f.is_a?(String) ? f.downcase.to_sym : f }
+
+ property :profile, [Symbol, String],
+ default: :any, equal_to: [:public, :private, :domain, :any, :notapplicable],
+ description: "The profile the firewall rule applies to.",
+ coerce: proc { |p| p.is_a?(String) ? p.downcase.to_sym : p }
+
+ property :program, String,
+ description: "The program the firewall rule applies to."
+
+ property :service, String,
+ description: "The service the firewall rule applies to."
+
+ property :interface_type, [Symbol, String],
+ default: :any, equal_to: [:any, :wireless, :wired, :remoteaccess],
+ description: "The interface type the firewall rule applies to.",
+ coerce: proc { |i| i.is_a?(String) ? i.downcase.to_sym : i }
+
+ property :enabled, [TrueClass, FalseClass],
+ default: true,
+ description: "Whether or not to enable the firewall rule."
+
+ alias_method :localip, :local_address
+ alias_method :remoteip, :remote_address
+ alias_method :localport, :local_port
+ alias_method :remoteport, :remote_port
+ alias_method :interfacetype, :interface_type
+
+ load_current_value do
+ load_state_cmd = load_firewall_state(rule_name)
+ output = powershell_out(load_state_cmd)
+ if output.stdout.empty?
+ current_value_does_not_exist!
+ else
+ state = Chef::JSONCompat.from_json(output.stdout)
+ end
+ local_address state["local_address"]
+ local_port Array(state["local_port"]).sort
+ remote_address state["remote_address"]
+ remote_port Array(state["remote_port"]).sort
+ direction state["direction"]
+ protocol state["protocol"]
+ firewall_action state["firewall_action"]
+ profile state["profile"]
+ program state["program"]
+ service state["service"]
+ interface_type state["interface_type"]
+ enabled state["enabled"]
+ end
+
+ action :create do
+ description "Create a Windows firewall entry."
+
+ if current_resource
+ converge_if_changed :rule_name, :local_address, :local_port, :remote_address, :remote_port, :direction,
+ :protocol, :firewall_action, :profile, :program, :service, :interface_type, :enabled do
+ cmd = firewall_command("Set")
+ powershell_out!(cmd)
+ end
+ else
+ converge_by("create firewall rule #{new_resource.rule_name}") do
+ cmd = firewall_command("New")
+ powershell_out!(cmd)
+ end
+ end
+ end
+
+ action :delete do
+ description "Delete an existing Windows firewall entry."
+
+ if current_resource
+ converge_by("delete firewall rule #{new_resource.rule_name}") do
+ powershell_out!("Remove-NetFirewallRule -Name '#{new_resource.rule_name}'")
+ end
+ else
+ Chef::Log.info("Firewall rule \"#{new_resource.rule_name}\" doesn't exist. Skipping.")
+ end
+ end
+
+ action_class do
+ # build the command to create a firewall rule based on new_resource values
+ # @return [String] firewall create command
+ def firewall_command(cmdlet_type)
+ cmd = "#{cmdlet_type}-NetFirewallRule -Name '#{new_resource.rule_name}'"
+ cmd << " -DisplayName '#{new_resource.rule_name}'" if cmdlet_type == "New"
+ cmd << " -Description '#{new_resource.description}'" if new_resource.description
+ cmd << " -LocalAddress '#{new_resource.local_address}'" if new_resource.local_address
+ cmd << " -LocalPort #{new_resource.local_port.join(',')}" if new_resource.local_port
+ cmd << " -RemoteAddress '#{new_resource.remote_address}'" if new_resource.remote_address
+ cmd << " -RemotePort #{new_resource.remote_port.join(',')}" if new_resource.remote_port
+ cmd << " -Direction '#{new_resource.direction}'" if new_resource.direction
+ cmd << " -Protocol '#{new_resource.protocol}'" if new_resource.protocol
+ cmd << " -Action '#{new_resource.firewall_action}'" if new_resource.firewall_action
+ cmd << " -Profile '#{new_resource.profile}'" if new_resource.profile
+ cmd << " -Program '#{new_resource.program}'" if new_resource.program
+ cmd << " -Service '#{new_resource.service}'" if new_resource.service
+ cmd << " -InterfaceType '#{new_resource.interface_type}'" if new_resource.interface_type
+ cmd << " -Enabled '#{new_resource.enabled}'"
+
+ cmd
+ end
+ end
+
+ private
+
+ # build the command to load the current resource
+ # # @return [String] current firewall state
+ def load_firewall_state(rule_name)
+ <<-EOH
+ Remove-TypeData System.Array # workaround for PS bug here: https://bit.ly/2SRMQ8M
+ $rule = Get-NetFirewallRule -Name '#{rule_name}'
+ $addressFilter = $rule | Get-NetFirewallAddressFilter
+ $portFilter = $rule | Get-NetFirewallPortFilter
+ $applicationFilter = $rule | Get-NetFirewallApplicationFilter
+ $serviceFilter = $rule | Get-NetFirewallServiceFilter
+ $interfaceTypeFilter = $rule | Get-NetFirewallInterfaceTypeFilter
+ ([PSCustomObject]@{
+ rule_name = $rule.Name
+ description = $rule.Description
+ local_address = $addressFilter.LocalAddress
+ local_port = $portFilter.LocalPort
+ remote_address = $addressFilter.RemoteAddress
+ remote_port = $portFilter.RemotePort
+ direction = $rule.Direction.ToString()
+ protocol = $portFilter.Protocol
+ firewall_action = $rule.Action.ToString()
+ profile = $rule.Profile.ToString()
+ program = $applicationFilter.Program
+ service = $serviceFilter.Service
+ interface_type = $interfaceTypeFilter.InterfaceType.ToString()
+ enabled = [bool]::Parse($rule.Enabled.ToString())
+ }) | ConvertTo-Json
+ EOH
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/windows_path.rb b/lib/chef/resource/windows_path.rb
index 0c5aaa9ce1..7f2e79d9d2 100644
--- a/lib/chef/resource/windows_path.rb
+++ b/lib/chef/resource/windows_path.rb
@@ -30,7 +30,9 @@ class Chef
allowed_actions :add, :remove
default_action :add
- property :path, String, name_property: true
+ property :path, String,
+ description: "The name of the value to add to the system path",
+ name_property: true
end
end
end
diff --git a/lib/chef/resource/windows_printer.rb b/lib/chef/resource/windows_printer.rb
index 7d596a9691..605b7b8521 100644
--- a/lib/chef/resource/windows_printer.rb
+++ b/lib/chef/resource/windows_printer.rb
@@ -42,7 +42,7 @@ class Chef
default: false
property :driver_name, String,
- description: "Exact name of printer driver. Note that the printer driver must already be installed on the node.",
+ description: "The exact name of printer driver installed on the system.",
required: true
property :location, String,
@@ -61,7 +61,7 @@ class Chef
regex: Resolv::IPv4::Regex
property :exists, [TrueClass, FalseClass],
- desired_state: true
+ skip_docs: true
PRINTERS_REG_KEY = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\\'.freeze unless defined?(PRINTERS_REG_KEY)
diff --git a/lib/chef/resource/windows_printer_port.rb b/lib/chef/resource/windows_printer_port.rb
index 3d54c72f47..799a37a651 100644
--- a/lib/chef/resource/windows_printer_port.rb
+++ b/lib/chef/resource/windows_printer_port.rb
@@ -34,7 +34,7 @@ class Chef
name_property: true,
regex: Resolv::IPv4::Regex,
validation_message: "The ipv4_address property must be in the format of WWW.XXX.YYY.ZZZ!",
- description: "The IPv4 address of the printer port."
+ description: "An optional property for the IPv4 address of the printer if it differs from the resource block's name."
property :port_name, String,
description: "The port name."
@@ -51,12 +51,12 @@ class Chef
default: false
property :port_protocol, Integer,
- description: "The printer port protocol, 1 (RAW), or 2 (LPR).",
+ description: "The printer port protocol: 1 (RAW) or 2 (LPR).",
validation_message: "port_protocol must be either 1 for RAW or 2 for LPR!",
default: 1, equal_to: [1, 2]
property :exists, [TrueClass, FalseClass],
- desired_state: true
+ skip_docs: true
PORTS_REG_KEY = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\\'.freeze unless defined?(PORTS_REG_KEY)
diff --git a/lib/chef/resource/windows_service.rb b/lib/chef/resource/windows_service.rb
index 1e7271b1fe..33805ed482 100644
--- a/lib/chef/resource/windows_service.rb
+++ b/lib/chef/resource/windows_service.rb
@@ -41,28 +41,23 @@ class Chef
allowed_actions :configure_startup, :create, :delete, :configure
- state_attrs :enabled, :running
-
- property :service_name, String,
- description: "The name of the service.",
- name_property: true, identity: true
-
# The display name to be used by user interface programs to identify the
# service. This string has a maximum length of 256 characters.
property :display_name, String, regex: /^.{1,256}$/,
+ validation_message: "The display_name can only be a maximum of 256 characters!",
introduced: "14.0"
- # https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L19-L29
+ # https://github.com/chef/win32-service/blob/ffi/lib/win32/windows/constants.rb#L19-L29
property :desired_access, Integer, default: SERVICE_ALL_ACCESS
- # https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L31-L41
+ # https://github.com/chef/win32-service/blob/ffi/lib/win32/windows/constants.rb#L31-L41
property :service_type, Integer, default: SERVICE_WIN32_OWN_PROCESS
# Valid options:
# - :automatic
# - :manual
# - :disabled
- # Reference: https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L49-L54
+ # Reference: https://github.com/chef/win32-service/blob/ffi/lib/win32/windows/constants.rb#L49-L54
property :startup_type, [Symbol], equal_to: [:automatic, :manual, :disabled], default: :automatic, coerce: proc { |x|
if x.is_a?(Integer)
ALLOWED_START_TYPES.invert.fetch(x) do
@@ -89,7 +84,7 @@ class Chef
end
}
- # https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L43-L47
+ # https://github.com/chef/win32-service/blob/ffi/lib/win32/windows/constants.rb#L43-L47
property :error_control, Integer, default: SERVICE_ERROR_NORMAL
property :binary_path_name, String,
diff --git a/lib/chef/resource/windows_share.rb b/lib/chef/resource/windows_share.rb
new file mode 100644
index 0000000000..48fcc9b946
--- /dev/null
+++ b/lib/chef/resource/windows_share.rb
@@ -0,0 +1,320 @@
+#
+# Author:: Sölvi Páll Ásgeirsson (<solvip@gmail.com>)
+# Author:: Richard Lavey (richard.lavey@calastone.com)
+# Author:: Tim Smith (tsmith@chef.io)
+#
+# Copyright:: 2014-2017, Sölvi Páll Ásgeirsson.
+# 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"
+require "chef/json_compat"
+
+class Chef
+ class Resource
+ class WindowsShare < Chef::Resource
+ resource_name :windows_share
+
+ description "Use the windows_share resource to create, modify and remove Windows shares."
+ introduced "14.7"
+
+ # Specifies a name for the SMB share. The name may be composed of any valid file name characters, but must be less than 80 characters long. The names pipe and mailslot are reserved for use by the computer.
+ property :share_name, String,
+ description: "The name to assign to the share.",
+ name_property: true
+
+ # Specifies the path of the location of the folder to share. The path must be fully qualified. Relative paths or paths that contain wildcard characters are not permitted.
+ property :path, String,
+ description: "The path of the folder to share. Required when creating. If the share already exists on a different path then it is deleted and re-created."
+
+ # Specifies an optional description of the SMB share. A description of the share is displayed by running the Get-SmbShare cmdlet. The description may not contain more than 256 characters.
+ property :description, String,
+ description: "The description to be applied to the share.",
+ default: ""
+
+ # Specifies which accounts are granted full permission to access the share. Use a comma-separated list to specify multiple accounts. An account may not be specified more than once in the FullAccess, ChangeAccess, or ReadAccess parameter lists, but may be specified once in the FullAccess, ChangeAccess, or ReadAccess parameter list and once in the NoAccess parameter list.
+ property :full_users, Array,
+ description: "The users that should have 'Full control' permissions on the share in domain\\username format.",
+ default: lazy { [] }, coerce: proc { |u| u.sort }
+
+ # Specifies which users are granted modify permission to access the share
+ property :change_users, Array,
+ description: "The users that should have 'modify' permission on the share in domain\\username format.",
+ default: lazy { [] }, coerce: proc { |u| u.sort }
+
+ # Specifies which users are granted read permission to access the share. Multiple users can be specified by supplying a comma-separated list.
+ property :read_users, Array,
+ description: "The users that should have 'read' permission on the share in domain\\username format.",
+ default: lazy { [] }, coerce: proc { |u| u.sort }
+
+ # Specifies the lifetime of the new SMB share. A temporary share does not persist beyond the next restart of the computer. By default, new SMB shares are persistent, and non-temporary.
+ property :temporary, [TrueClass, FalseClass],
+ description: "The lifetime of the new SMB share. A temporary share does not persist beyond the next restart of the computer.",
+ default: false
+
+ # Specifies the scope name of the share.
+ property :scope_name, String,
+ description: "The scope name of the share.",
+ default: "*"
+
+ # Specifies the continuous availability time-out for the share.
+ property :ca_timeout, Integer,
+ description: "The continuous availability time-out for the share.",
+ default: 0
+
+ # Indicates that the share is continuously available.
+ property :continuously_available, [TrueClass, FalseClass],
+ description: "Indicates that the share is continuously available.",
+ default: false
+
+ # Specifies the caching mode of the offline files for the SMB share.
+ # property :caching_mode, String, equal_to: %w(None Manual Documents Programs BranchCache)
+
+ # Specifies the maximum number of concurrently connected users that the new SMB share may accommodate. If this parameter is set to zero (0), then the number of users is unlimited.
+ property :concurrent_user_limit, Integer,
+ description: "The maximum number of concurrently connected users the share can accommodate.",
+ default: 0
+
+ # Indicates that the share is encrypted.
+ property :encrypt_data, [TrueClass, FalseClass],
+ description: "Indicates that the share is encrypted.",
+ default: false
+
+ # Specifies which files and folders in the SMB share are visible to users. AccessBased: SMB does not the display the files and folders for a share to a user unless that user has rights to access the files and folders. By default, access-based enumeration is disabled for new SMB shares. Unrestricted: SMB displays files and folders to a user even when the user does not have permission to access the items.
+ # property :folder_enumeration_mode, String, equal_to: %(AccessBased Unrestricted)
+
+ include Chef::Mixin::PowershellOut
+
+ load_current_value do |desired|
+ # this command selects individual objects because EncryptData & CachingMode have underlying
+ # types that get converted to their Integer values by ConvertTo-Json & we need to make sure
+ # those get written out as strings
+ share_state_cmd = "Get-SmbShare -Name '#{desired.share_name}' | Select-Object Name,Path, Description, Temporary, CATimeout, ContinuouslyAvailable, ConcurrentUserLimit, EncryptData | ConvertTo-Json"
+
+ Chef::Log.debug("Running '#{share_state_cmd}' to determine share state'")
+ ps_results = powershell_out(share_state_cmd)
+
+ # detect a failure without raising and then set current_resource to nil
+ if ps_results.error?
+ Chef::Log.debug("Error fetching share state: #{ps_results.stderr}")
+ current_value_does_not_exist!
+ end
+
+ Chef::Log.debug("The Get-SmbShare results were #{ps_results.stdout}")
+ results = Chef::JSONCompat.from_json(ps_results.stdout)
+
+ path results["Path"]
+ description results["Description"]
+ temporary results["Temporary"]
+ ca_timeout results["CATimeout"]
+ continuously_available results["ContinuouslyAvailable"]
+ # caching_mode results['CachingMode']
+ concurrent_user_limit results["ConcurrentUserLimit"]
+ encrypt_data results["EncryptData"]
+ # folder_enumeration_mode results['FolderEnumerationMode']
+
+ perm_state_cmd = %{Get-SmbShareAccess -Name "#{desired.share_name}" | Select-Object AccountName,AccessControlType,AccessRight | ConvertTo-Json}
+
+ Chef::Log.debug("Running '#{perm_state_cmd}' to determine share permissions state'")
+ ps_perm_results = powershell_out(perm_state_cmd)
+
+ # we raise here instead of warning like above because we'd only get here if the above Get-SmbShare
+ # command was successful and that continuing would leave us with 1/2 known state
+ raise "Could not determine #{desired.share_name} share permissions by running '#{perm_state_cmd}'" if ps_perm_results.error?
+
+ Chef::Log.debug("The Get-SmbShareAccess results were #{ps_perm_results.stdout}")
+
+ f_users, c_users, r_users = parse_permissions(ps_perm_results.stdout)
+
+ full_users f_users
+ change_users c_users
+ read_users r_users
+ end
+
+ def after_created
+ raise "The windows_share resource relies on PowerShell cmdlets not present in Windows releases prior to 8/2012. Cannot continue!" if node["platform_version"].to_f < 6.3
+ end
+
+# given the string output of Get-SmbShareAccess parse out
+# arrays of full access users, change users, and read only users
+ def parse_permissions(results_string)
+ json_results = Chef::JSONCompat.from_json(results_string)
+ json_results = [json_results] unless json_results.is_a?(Array) # single result is not an array
+
+ f_users = []
+ c_users = []
+ r_users = []
+
+ json_results.each do |perm|
+ next unless perm["AccessControlType"] == 0 # allow
+ case perm["AccessRight"]
+ when 0 then f_users << stripped_account(perm["AccountName"]) # 0 full control
+ when 1 then c_users << stripped_account(perm["AccountName"]) # 1 == change
+ when 2 then r_users << stripped_account(perm["AccountName"]) # 2 == read
+ end
+ end
+ [f_users, c_users, r_users]
+ end
+
+# local names are returned from Get-SmbShareAccess in the full format MACHINE\\NAME
+# but users of this resource would simply say NAME so we need to strip the values for comparison
+ def stripped_account(name)
+ name.slice!("#{node['hostname']}\\")
+ name
+ end
+
+ action :create do
+ description "Create and modify Windows shares."
+
+ # we do this here instead of requiring the property because :delete doesn't need path set
+ raise "No path property set" unless new_resource.path
+
+ converge_if_changed do
+ # you can't actually change the path so you have to delete the old share first
+ delete_share if different_path?
+
+ # powershell cmdlet for create is different than updates
+ if current_resource.nil?
+ Chef::Log.debug("The current resource is nil so we will create a new share")
+ create_share
+ else
+ Chef::Log.debug("The current resource was not nil so we will update an existing share")
+ update_share
+ end
+
+ # creating the share does not set permissions so we need to update
+ update_permissions
+ end
+ end
+
+ action :delete do
+ description "Delete an existing Windows share."
+
+ if current_resource.nil?
+ Chef::Log.debug("#{new_resource.share_name} does not exist - nothing to do")
+ else
+ converge_by("delete #{new_resource.share_name}") do
+ delete_share
+ end
+ end
+ end
+
+ action_class do
+ def different_path?
+ return false if current_resource.nil? # going from nil to something isn't different for our concerns
+ return false if current_resource.path == new_resource.path
+ true
+ end
+
+ def delete_share
+ delete_command = "Remove-SmbShare -Name '#{new_resource.share_name}' -Force"
+
+ Chef::Log.debug("Running '#{delete_command}' to remove the share")
+ powershell_out!(delete_command)
+ end
+
+ def update_share
+ update_command = "Set-SmbShare -Name '#{new_resource.share_name}' -Description '#{new_resource.description}' -Force"
+
+ Chef::Log.debug("Running '#{update_command}' to update the share")
+ powershell_out!(update_command)
+ end
+
+ def create_share
+ raise "#{new_resource.path} is missing or not a directory. Shares cannot be created if the path doesn't first exist." unless ::File.directory? new_resource.path
+
+ share_cmd = "New-SmbShare -Name '#{new_resource.share_name}' -Path '#{new_resource.path}' -Description '#{new_resource.description}' -ConcurrentUserLimit #{new_resource.concurrent_user_limit} -CATimeout #{new_resource.ca_timeout} -EncryptData:#{bool_string(new_resource.encrypt_data)} -ContinuouslyAvailable:#{bool_string(new_resource.continuously_available)}"
+ share_cmd << " -ScopeName #{new_resource.scope_name}" unless new_resource.scope_name == "*" # passing * causes the command to fail
+ share_cmd << " -Temporary:#{bool_string(new_resource.temporary)}" if new_resource.temporary # only set true
+
+ Chef::Log.debug("Running '#{share_cmd}' to create the share")
+ powershell_out!(share_cmd)
+
+ # New-SmbShare adds the "Everyone" user with read access no matter what so we need to remove it
+ # before we add our permissions
+ revoke_user_permissions(["Everyone"])
+ end
+
+ # determine what users in the current state don't exist in the desired state
+ # users/groups will have their permissions updated with the same command that
+ # sets it, but removes must be performed with Revoke-SmbShareAccess
+ def users_to_revoke
+ @users_to_revoke ||= begin
+ # if the resource doesn't exist then nothing needs to be revoked
+ if current_resource.nil?
+ []
+ else # if it exists then calculate the current to new resource diffs
+ (current_resource.full_users + current_resource.change_users + current_resource.read_users) - (new_resource.full_users + new_resource.change_users + new_resource.read_users)
+ end
+ end
+ end
+
+ # update existing permissions on a share
+ def update_permissions
+ # revoke any users that had something, but now has nothing
+ revoke_user_permissions(users_to_revoke) unless users_to_revoke.empty?
+
+ # set permissions for each of the permission types
+ %w{full read change}.each do |perm_type|
+ # set permissions for a brand new share OR
+ # update permissions if the current state and desired state differ
+ next unless permissions_need_update?(perm_type)
+ grant_command = "Grant-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{new_resource.send("#{perm_type}_users").join('","')}\" -Force -AccessRight #{perm_type}"
+
+ Chef::Log.debug("Running '#{grant_command}' to update the share permissions")
+ powershell_out!(grant_command)
+ end
+ end
+
+ # determine if permissions need to be updated.
+ # Brand new share with no permissions defined: no
+ # Brand new share with permissions defined: yes
+ # Existing share with differing permissions: yes
+ #
+ # @param [String] type the permissions type (Full, Read, or Change)
+ def permissions_need_update?(type)
+ property_name = "#{type}_users"
+
+ # brand new share, but nothing to set
+ return false if current_resource.nil? && new_resource.send(property_name).empty?
+
+ # brand new share with new permissions to set
+ return true if current_resource.nil? && !new_resource.send(property_name).empty?
+
+ # there's a difference between the current and desired state
+ return true unless (new_resource.send(property_name) - current_resource.send(property_name)).empty?
+
+ # anything else
+ false
+ end
+
+ # revoke user permissions from a share
+ # @param [Array] users
+ def revoke_user_permissions(users)
+ revoke_command = "Revoke-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{users.join('","')}\" -Force"
+ Chef::Log.debug("Running '#{revoke_command}' to revoke share permissions")
+ powershell_out!(revoke_command)
+ end
+
+ # convert True/False into "$True" & "$False"
+ def bool_string(bool)
+ # bool ? 1 : 0
+ bool ? "$true" : "$false"
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/resource/windows_task.rb b/lib/chef/resource/windows_task.rb
index 405846cb9e..5bd6d7e557 100644
--- a/lib/chef/resource/windows_task.rb
+++ b/lib/chef/resource/windows_task.rb
@@ -22,315 +22,318 @@ require "chef/win32/security" if Chef::Platform.windows?
class Chef
class Resource
class WindowsTask < Chef::Resource
- if Chef::Platform.windows?
- resource_name :windows_task
- provides(:windows_task) { true }
+ resource_name :windows_task
+ provides(:windows_task) { true }
- description "Use the windows_task resource to create, delete or run a Windows scheduled task. Requires Windows Server 2008 or later due to API usage."
- introduced "13.0"
+ description "Use the windows_task resource to create, delete or run a Windows scheduled task. Requires Windows Server 2008 or later due to API usage."
+ introduced "13.0"
- allowed_actions :create, :delete, :run, :end, :enable, :disable, :change
- default_action :create
+ allowed_actions :create, :delete, :run, :end, :enable, :disable, :change
+ default_action :create
- property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/],
- description: "The task name, such as 'Task Name' or '/Task Name'",
- name_property: true
+ property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/],
+ description: "The task name, such as 'Task Name' or '/Task Name'",
+ name_property: true
- property :command, String,
- description: "The command to be executed by the windows scheduled task."
+ property :command, String,
+ description: "The command to be executed by the windows scheduled task."
- property :cwd, String,
- description: "The directory the task will be run from."
+ property :cwd, String,
+ description: "The directory the task will be run from."
- property :user, String,
- description: "The user to run the task as.",
- default: Chef::ReservedNames::Win32::Security::SID.LocalSystem.account_simple_name
+ property :user, String,
+ description: "The user to run the task as.",
+ default: lazy { Chef::ReservedNames::Win32::Security::SID.LocalSystem.account_simple_name if Chef::Platform.windows? },
+ default_description: "The localized SYSTEM user for the node."
- property :password, String,
- description: "The user’s password. The user property must be set if using this property."
+ property :password, String,
+ description: "The user’s password. The user property must be set if using this property."
- property :run_level, Symbol, equal_to: [:highest, :limited],
- description: "Run with ':limited' or ':highest' privileges.",
- default: :limited
+ property :run_level, Symbol, equal_to: [:highest, :limited],
+ description: "Run with ':limited' or ':highest' privileges.",
+ default: :limited
- property :force, [TrueClass, FalseClass],
- description: "When used with create, will update the task.",
- default: false
+ property :force, [TrueClass, FalseClass],
+ description: "When used with create, will update the task.",
+ default: false
- property :interactive_enabled, [TrueClass, FalseClass],
- description: "Allow task to run interactively or non-interactively. Requires user and password to also be set.",
- default: false
+ property :interactive_enabled, [TrueClass, FalseClass],
+ description: "Allow task to run interactively or non-interactively. Requires user and password to also be set.",
+ default: false
- property :frequency_modifier, [Integer, String],
- default: 1
+ property :frequency_modifier, [Integer, String],
+ default: 1
- property :frequency, Symbol, equal_to: [:minute,
- :hourly,
- :daily,
- :weekly,
- :monthly,
- :once,
- :on_logon,
- :onstart,
- :on_idle,
- :none],
- description: "The frequency with which to run the task."
+ property :frequency, Symbol, equal_to: [:minute,
+ :hourly,
+ :daily,
+ :weekly,
+ :monthly,
+ :once,
+ :on_logon,
+ :onstart,
+ :on_idle,
+ :none],
+ description: "The frequency with which to run the task."
- property :start_day, String,
- description: "Specifies the first date on which the task runs in MM/DD/YYYY format."
+ property :start_day, String,
+ description: "Specifies the first date on which the task runs in MM/DD/YYYY format."
- property :start_time, String,
- description: "Specifies the start time to run the task, in HH:mm format."
+ property :start_time, String,
+ description: "Specifies the start time to run the task, in HH:mm format."
- property :day, [String, Integer],
- description: "The day(s) on which the task runs."
+ property :day, [String, Integer],
+ description: "The day(s) on which the task runs."
- property :months, String,
- description: "The Months of the year on which the task runs, such as: 'JAN, FEB' or '\*'. Multiple months should be comma delimited. e.g. 'Jan, Feb, Mar, Dec'."
+ property :months, String,
+ description: "The Months of the year on which the task runs, such as: 'JAN, FEB' or '\*'. Multiple months should be comma delimited. e.g. 'Jan, Feb, Mar, Dec'."
- property :idle_time, Integer,
- description: "For :on_idle frequency, the time (in minutes) without user activity that must pass to trigger the task, from 1 - 999."
+ property :idle_time, Integer,
+ description: "For :on_idle frequency, the time (in minutes) without user activity that must pass to trigger the task, from 1 - 999."
- property :random_delay, [String, Integer],
- description: "Delays the task up to a given time (in seconds)."
+ property :random_delay, [String, Integer],
+ description: "Delays the task up to a given time (in seconds)."
- property :execution_time_limit, [String, Integer],
- description: "The maximum time (in seconds) the task will run.",
- default: "PT72H" # 72 hours in ISO8601 duration format
+ property :execution_time_limit, [String, Integer],
+ description: "The maximum time (in seconds) the task will run.",
+ default: "PT72H" # 72 hours in ISO8601 duration format
- property :minutes_duration, [String, Integer],
- description: ""
+ property :minutes_duration, [String, Integer],
+ description: ""
- property :minutes_interval, [String, Integer],
- description: ""
+ property :minutes_interval, [String, Integer],
+ description: ""
- property :priority, Integer,
- description: "Use to set Priority Levels range from 0 to 10.",
- default: 7, callbacks: { "should be in range of 0 to 10" => proc { |v| v >= 0 && v <= 10 } }
+ property :priority, Integer,
+ description: "Use to set Priority Levels range from 0 to 10.",
+ default: 7, callbacks: { "should be in range of 0 to 10" => proc { |v| v >= 0 && v <= 10 } }
- property :disallow_start_if_on_batteries, [TrueClass, FalseClass],
- introduced: "14.4", default: false,
- description: "Disallow start of the task if the system is running on battery power."
+ property :disallow_start_if_on_batteries, [TrueClass, FalseClass],
+ introduced: "14.4", default: false,
+ description: "Disallow start of the task if the system is running on battery power."
- property :stop_if_going_on_batteries, [TrueClass, FalseClass],
- introduced: "14.4", default: false,
- description: "Scheduled task option when system is switching on battery."
+ property :stop_if_going_on_batteries, [TrueClass, FalseClass],
+ introduced: "14.4", default: false,
+ description: "Scheduled task option when system is switching on battery."
- attr_accessor :exists, :task, :command_arguments
+ property :description, String,
+ introduced: "14.7",
+ description: "The task description."
- VALID_WEEK_DAYS = %w{ mon tue wed thu fri sat sun * }.freeze
- VALID_DAYS_OF_MONTH = ("1".."31").to_a << "last" << "lastday"
- VALID_MONTHS = %w{JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC *}.freeze
- VALID_WEEKS = %w{FIRST SECOND THIRD FOURTH LAST LASTDAY}.freeze
+ attr_accessor :exists, :task, :command_arguments
- def after_created
- if random_delay
- validate_random_delay(random_delay, frequency)
- random_delay(sec_to_min(random_delay))
- end
+ VALID_WEEK_DAYS = %w{ mon tue wed thu fri sat sun * }.freeze
+ VALID_DAYS_OF_MONTH = ("1".."31").to_a << "last" << "lastday"
+ VALID_MONTHS = %w{JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC *}.freeze
+ VALID_WEEKS = %w{FIRST SECOND THIRD FOURTH LAST LASTDAY}.freeze
- if execution_time_limit
- execution_time_limit(259200) if execution_time_limit == "PT72H"
- raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(execution_time_limit)
- execution_time_limit(sec_to_min(execution_time_limit))
- end
+ def after_created
+ if random_delay
+ validate_random_delay(random_delay, frequency)
+ random_delay(sec_to_min(random_delay))
+ end
- validate_frequency(frequency) if action.include?(:create) || action.include?(:change)
- validate_start_time(start_time, frequency)
- validate_start_day(start_day, frequency) if start_day
- validate_user_and_password(user, password)
- validate_interactive_setting(interactive_enabled, password)
- validate_create_frequency_modifier(frequency, frequency_modifier) if frequency_modifier
- validate_create_day(day, frequency, frequency_modifier) if day
- validate_create_months(months, frequency) if months
- validate_frequency_monthly(frequency_modifier, months, day) if frequency == :monthly
- validate_idle_time(idle_time, frequency)
- idempotency_warning_for_frequency_weekly(day, start_day) if frequency == :weekly
+ if execution_time_limit
+ execution_time_limit(259200) if execution_time_limit == "PT72H"
+ raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(execution_time_limit)
+ execution_time_limit(sec_to_min(execution_time_limit))
end
- private
+ validate_frequency(frequency) if action.include?(:create) || action.include?(:change)
+ validate_start_time(start_time, frequency)
+ validate_start_day(start_day, frequency) if start_day
+ validate_user_and_password(user, password)
+ validate_interactive_setting(interactive_enabled, password)
+ validate_create_frequency_modifier(frequency, frequency_modifier) if frequency_modifier
+ validate_create_day(day, frequency, frequency_modifier) if day
+ validate_create_months(months, frequency) if months
+ validate_frequency_monthly(frequency_modifier, months, day) if frequency == :monthly
+ validate_idle_time(idle_time, frequency)
+ idempotency_warning_for_frequency_weekly(day, start_day) if frequency == :weekly
+ end
+
+ private
## Resource is not idempotent when day, start_day is not provided with frequency :weekly
## we set start_day when not given by user as current date based on which we set the day property for current current date day is monday ..
## we set the monday as the day so at next run when new_resource.day is nil and current_resource day is monday due to which udpate gets called
- def idempotency_warning_for_frequency_weekly(day, start_day)
- if start_day.nil? && day.nil?
- logger.warn "To maintain idempotency for frequency :weekly provide start_day, start_time and day."
- end
+ def idempotency_warning_for_frequency_weekly(day, start_day)
+ if start_day.nil? && day.nil?
+ logger.warn "To maintain idempotency for frequency :weekly provide start_day, start_time and day."
end
+ end
# Validate the passed value is numeric values only if it is a string
- def numeric_value_in_string?(val)
- return true if Integer(val)
- rescue ArgumentError
- false
- end
+ def numeric_value_in_string?(val)
+ return true if Integer(val)
+ rescue ArgumentError
+ false
+ end
- def validate_frequency(frequency)
- if frequency.nil? || !([:minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none].include?(frequency))
- raise ArgumentError, "Frequency needs to be provided. Valid frequencies are :minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none."
- end
+ def validate_frequency(frequency)
+ if frequency.nil? || !([:minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none].include?(frequency))
+ raise ArgumentError, "Frequency needs to be provided. Valid frequencies are :minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none."
end
+ end
- def validate_frequency_monthly(frequency_modifier, months, day)
- # validates the frequency :monthly and raises error if frequency_modifier is first, second, thrid etc and day is not provided
- if (frequency_modifier != 1) && (frequency_modifier_includes_days_of_weeks?(frequency_modifier)) && !(day)
- raise ArgumentError, "Please select day on which you want to run the task e.g. 'Mon, Tue'. Multiple values must be seprated by comma."
- end
-
- # frequency_modifer 2-12 is used to set every (n) months, so using :months propety with frequency_modifer is not valid since they both used to set months.
- # Not checking value 1 here for frequecy_modifier since we are setting that as default value it won't break anything since preference is given to months property
- if (frequency_modifier.to_i.between?(2, 12)) && !(months.nil?)
- raise ArgumentError, "For frequency :monthly either use property months or frequency_modifier to set months."
- end
+ def validate_frequency_monthly(frequency_modifier, months, day)
+ # validates the frequency :monthly and raises error if frequency_modifier is first, second, thrid etc and day is not provided
+ if (frequency_modifier != 1) && (frequency_modifier_includes_days_of_weeks?(frequency_modifier)) && !(day)
+ raise ArgumentError, "Please select day on which you want to run the task e.g. 'Mon, Tue'. Multiple values must be seprated by comma."
end
- # returns true if frequency_modifer has values First, second, third, fourth, last, lastday
- def frequency_modifier_includes_days_of_weeks?(frequency_modifier)
- frequency_modifier = frequency_modifier.to_s.split(",")
- frequency_modifier.map! { |value| value.strip.upcase }
- (frequency_modifier - VALID_WEEKS).empty?
+ # frequency_modifer 2-12 is used to set every (n) months, so using :months propety with frequency_modifer is not valid since they both used to set months.
+ # Not checking value 1 here for frequecy_modifier since we are setting that as default value it won't break anything since preference is given to months property
+ if (frequency_modifier.to_i.between?(2, 12)) && !(months.nil?)
+ raise ArgumentError, "For frequency :monthly either use property months or frequency_modifier to set months."
end
+ end
- def validate_random_delay(random_delay, frequency)
- if [:on_logon, :onstart, :on_idle, :none].include? frequency
- raise ArgumentError, "`random_delay` property is supported only for frequency :once, :minute, :hourly, :daily, :weekly and :monthly"
- end
+ # returns true if frequency_modifer has values First, second, third, fourth, last, lastday
+ def frequency_modifier_includes_days_of_weeks?(frequency_modifier)
+ frequency_modifier = frequency_modifier.to_s.split(",")
+ frequency_modifier.map! { |value| value.strip.upcase }
+ (frequency_modifier - VALID_WEEKS).empty?
+ end
- raise ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(random_delay)
+ def validate_random_delay(random_delay, frequency)
+ if [:on_logon, :onstart, :on_idle, :none].include? frequency
+ raise ArgumentError, "`random_delay` property is supported only for frequency :once, :minute, :hourly, :daily, :weekly and :monthly"
end
+ raise ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(random_delay)
+ end
+
# @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~f
- def validate_start_day(start_day, frequency)
- if start_day && frequency == :none
- raise ArgumentError, "`start_day` property is not supported with frequency: #{frequency}"
- end
+ def validate_start_day(start_day, frequency)
+ if start_day && frequency == :none
+ raise ArgumentError, "`start_day` property is not supported with frequency: #{frequency}"
+ end
- # make sure the start_day is in MM/DD/YYYY format: http://rubular.com/r/cgjHemtWl5
- if start_day
- raise ArgumentError, "`start_day` property must be in the MM/DD/YYYY format." unless /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d$/ =~ start_day
- end
+ # make sure the start_day is in MM/DD/YYYY format: http://rubular.com/r/cgjHemtWl5
+ if start_day
+ raise ArgumentError, "`start_day` property must be in the MM/DD/YYYY format." unless /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d$/ =~ start_day
end
+ end
# @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~
- def validate_start_time(start_time, frequency)
- if start_time
- raise ArgumentError, "`start_time` property is not supported with `frequency :none`" if frequency == :none
- raise ArgumentError, "`start_time` property must be in the HH:mm format (e.g. 6:20pm -> 18:20)." unless /^[0-2][0-9]:[0-5][0-9]$/ =~ start_time
- else
- raise ArgumentError, "`start_time` needs to be provided with `frequency :once`" if frequency == :once
- end
+ def validate_start_time(start_time, frequency)
+ if start_time
+ raise ArgumentError, "`start_time` property is not supported with `frequency :none`" if frequency == :none
+ raise ArgumentError, "`start_time` property must be in the HH:mm format (e.g. 6:20pm -> 18:20)." unless /^[0-2][0-9]:[0-5][0-9]$/ =~ start_time
+ else
+ raise ArgumentError, "`start_time` needs to be provided with `frequency :once`" if frequency == :once
end
+ end
- def validate_user_and_password(user, password)
- if password_required?(user) && password.nil?
- raise ArgumentError, "Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: '#{Chef::ReservedNames::Win32::Security::SID::SYSTEM_USER.join("', '")}'"
- end
+ def validate_user_and_password(user, password)
+ if password_required?(user) && password.nil?
+ raise ArgumentError, "Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: '#{Chef::ReservedNames::Win32::Security::SID::SYSTEM_USER.join("', '")}'"
end
+ end
- def password_required?(user)
- return false if user.nil?
- @password_required ||= !Chef::ReservedNames::Win32::Security::SID.system_user?(user)
- end
+ def password_required?(user)
+ return false if user.nil?
+ @password_required ||= !Chef::ReservedNames::Win32::Security::SID.system_user?(user)
+ end
- def validate_interactive_setting(interactive_enabled, password)
- raise ArgumentError, "Please provide the password when attempting to set interactive/non-interactive." if interactive_enabled && password.nil?
+ def validate_interactive_setting(interactive_enabled, password)
+ raise ArgumentError, "Please provide the password when attempting to set interactive/non-interactive." if interactive_enabled && password.nil?
+ end
+
+ def validate_create_frequency_modifier(frequency, frequency_modifier)
+ if ([:on_logon, :onstart, :on_idle, :none].include?(frequency)) && ( frequency_modifier != 1)
+ raise ArgumentError, "frequency_modifier property not supported with frequency :#{frequency}"
end
- def validate_create_frequency_modifier(frequency, frequency_modifier)
- if ([:on_logon, :onstart, :on_idle, :none].include?(frequency)) && ( frequency_modifier != 1)
- raise ArgumentError, "frequency_modifier property not supported with frequency :#{frequency}"
+ if frequency == :monthly
+ unless (1..12).cover?(frequency_modifier.to_i) || frequency_modifier_includes_days_of_weeks?(frequency_modifier)
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'."
end
-
- if frequency == :monthly
- unless (1..12).cover?(frequency_modifier.to_i) || frequency_modifier_includes_days_of_weeks?(frequency_modifier)
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'."
- end
- else
- unless frequency.nil? || frequency_modifier.nil?
- frequency_modifier = frequency_modifier.to_i
- min = 1
- max = case frequency
- when :minute
- 1439
- when :hourly
- 23
- when :daily
- 365
- when :weekly
- 52
- else
- min
- end
- unless frequency_modifier.between?(min, max)
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :#{frequency} frequency are #{min} - #{max}."
- end
+ else
+ unless frequency.nil? || frequency_modifier.nil?
+ frequency_modifier = frequency_modifier.to_i
+ min = 1
+ max = case frequency
+ when :minute
+ 1439
+ when :hourly
+ 23
+ when :daily
+ 365
+ when :weekly
+ 52
+ else
+ min
+ end
+ unless frequency_modifier.between?(min, max)
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :#{frequency} frequency are #{min} - #{max}."
end
end
end
+ end
+
+ def validate_create_day(day, frequency, frequency_modifier)
+ raise ArgumentError, "day property is only valid for tasks that run monthly or weekly" unless [:weekly, :monthly].include?(frequency)
- def validate_create_day(day, frequency, frequency_modifier)
- raise ArgumentError, "day property is only valid for tasks that run monthly or weekly" unless [:weekly, :monthly].include?(frequency)
-
- # This has been verified with schtask.exe https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks#d-dayday--
- # verified with earlier code if day "*" is given with frequency it raised exception Invalid value for /D option
- raise ArgumentError, "day wild card (*) is only valid with frequency :weekly" if frequency == :monthly && day == "*"
-
- if day.is_a?(String) && day.to_i.to_s != day
- days = day.split(",")
- if days_includes_days_of_months?(days)
- # Following error will be raise if day is set as 1-31 and frequency is selected as :weekly since those values are valid with only frequency :monthly
- raise ArgumentError, "day values 1-31 or last is only valid with frequency :monthly" if frequency == :weekly
- else
- days.map! { |day| day.to_s.strip.downcase }
- unless (days - VALID_WEEK_DAYS).empty?
- raise ArgumentError, "day property invalid. Only valid values are: #{VALID_WEEK_DAYS.map(&:upcase).join(', ')}. Multiple values must be separated by a comma."
- end
+ # This has been verified with schtask.exe https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks#d-dayday--
+ # verified with earlier code if day "*" is given with frequency it raised exception Invalid value for /D option
+ raise ArgumentError, "day wild card (*) is only valid with frequency :weekly" if frequency == :monthly && day == "*"
+
+ if day.is_a?(String) && day.to_i.to_s != day
+ days = day.split(",")
+ if days_includes_days_of_months?(days)
+ # Following error will be raise if day is set as 1-31 and frequency is selected as :weekly since those values are valid with only frequency :monthly
+ raise ArgumentError, "day values 1-31 or last is only valid with frequency :monthly" if frequency == :weekly
+ else
+ days.map! { |day| day.to_s.strip.downcase }
+ unless (days - VALID_WEEK_DAYS).empty?
+ raise ArgumentError, "day property invalid. Only valid values are: #{VALID_WEEK_DAYS.map(&:upcase).join(', ')}. Multiple values must be separated by a comma."
end
end
end
+ end
- def validate_create_months(months, frequency)
- raise ArgumentError, "months property is only valid for tasks that run monthly" if frequency != :monthly
- if months.is_a?(String)
- months = months.split(",")
- months.map! { |month| month.strip.upcase }
- unless (months - VALID_MONTHS).empty?
- raise ArgumentError, "months property invalid. Only valid values are: #{VALID_MONTHS.join(', ')}. Multiple values must be separated by a comma."
- end
+ def validate_create_months(months, frequency)
+ raise ArgumentError, "months property is only valid for tasks that run monthly" if frequency != :monthly
+ if months.is_a?(String)
+ months = months.split(",")
+ months.map! { |month| month.strip.upcase }
+ unless (months - VALID_MONTHS).empty?
+ raise ArgumentError, "months property invalid. Only valid values are: #{VALID_MONTHS.join(', ')}. Multiple values must be separated by a comma."
end
end
+ end
# This method returns true if day has values from 1-31 which is a days of moths and used with frequency :monthly
- def days_includes_days_of_months?(days)
- days.map! { |day| day.to_s.strip.downcase }
- (days - VALID_DAYS_OF_MONTH).empty?
- end
+ def days_includes_days_of_months?(days)
+ days.map! { |day| day.to_s.strip.downcase }
+ (days - VALID_DAYS_OF_MONTH).empty?
+ end
- def validate_idle_time(idle_time, frequency)
- if !idle_time.nil? && frequency != :on_idle
- raise ArgumentError, "idle_time property is only valid for tasks that run on_idle"
- end
- if idle_time.nil? && frequency == :on_idle
- raise ArgumentError, "idle_time value should be set for :on_idle frequency."
- end
- unless idle_time.nil? || idle_time > 0 && idle_time <= 999
- raise ArgumentError, "idle_time value #{idle_time} is invalid. Valid values for :on_idle frequency are 1 - 999."
- end
+ def validate_idle_time(idle_time, frequency)
+ if !idle_time.nil? && frequency != :on_idle
+ raise ArgumentError, "idle_time property is only valid for tasks that run on_idle"
end
+ if idle_time.nil? && frequency == :on_idle
+ raise ArgumentError, "idle_time value should be set for :on_idle frequency."
+ end
+ unless idle_time.nil? || idle_time > 0 && idle_time <= 999
+ raise ArgumentError, "idle_time value #{idle_time} is invalid. Valid values for :on_idle frequency are 1 - 999."
+ end
+ end
# Converts the number of seconds to an ISO8601 duration format and returns it.
# Ref : https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23
# e.g.
# ISO8601::Duration.new(65707200).to_s
# returns 'PT65707200S'
- def sec_to_dur(seconds)
- ISO8601::Duration.new(seconds.to_i).to_s
- end
+ def sec_to_dur(seconds)
+ ISO8601::Duration.new(seconds.to_i).to_s
+ end
- def sec_to_min(seconds)
- seconds.to_i / 60
- end
+ def sec_to_min(seconds)
+ seconds.to_i / 60
end
end
end
diff --git a/lib/chef/resource/windows_workgroup.rb b/lib/chef/resource/windows_workgroup.rb
index 229afa2e8e..2aeb534074 100644
--- a/lib/chef/resource/windows_workgroup.rb
+++ b/lib/chef/resource/windows_workgroup.rb
@@ -36,39 +36,51 @@ class Chef
name_property: true
property :user, String,
- description: "The local administrator user to use to change the workgroup."
+ description: "The local administrator user to use to change the workgroup. Required if using the password property.",
+ desired_state: false
property :password, String,
- description: "The password for the local administrator user."
+ description: "The password for the local administrator user. Required if using the user property.",
+ desired_state: false
property :reboot, Symbol,
- equal_to: [:immediate, :delayed, :never, :request_reboot, :reboot_now],
+ equal_to: [:never, :request_reboot, :reboot_now],
validation_message: "The reboot property accepts :immediate (reboot as soon as the resource completes), :delayed (reboot once the Chef run completes), and :never (Don't reboot)",
description: "Controls the system reboot behavior post workgroup joining. Reboot immediately, after the Chef run completes, or never. Note that a reboot is necessary for changes to take effect.",
- default: :immediate
+ coerce: proc { |x| clarify_reboot(x) },
+ default: :immediate, desired_state: false
+
+ # This resource historically took `:immediate` and `:delayed` as arguments to the reboot property but then
+ # tried to shove that straight to the `reboot` resource which objected strenuously. We need to convert these
+ # legacy actions into actual reboot actions
+ #
+ # @return [Symbol] chef reboot resource action
+ def clarify_reboot(reboot_action)
+ case reboot_action
+ when :immediate
+ :reboot_now
+ when :delayed
+ :request_reboot
+ else
+ reboot_action
+ end
+ end
# define this again so we can default it to true. Otherwise failures print the password
property :sensitive, [TrueClass, FalseClass],
- default: true
+ default: true, desired_state: false
action :join do
description "Update the workgroup."
unless workgroup_member?
- cmd = ""
- cmd << "$pswd = ConvertTo-SecureString \'#{new_resource.password}\' -AsPlainText -Force;" if new_resource.password
- cmd << "$credential = New-Object System.Management.Automation.PSCredential (\"#{new_resource.user}\",$pswd);" if new_resource.password
- cmd << "Add-Computer -WorkgroupName #{new_resource.workgroup_name}"
- cmd << " -Credential $credential" if new_resource.password
- cmd << " -Force"
-
converge_by("join workstation workgroup #{new_resource.workgroup_name}") do
- ps_run = powershell_out(cmd)
+ ps_run = powershell_out(join_command)
raise "Failed to join the workgroup #{new_resource.workgroup_name}: #{ps_run.stderr}}" if ps_run.error?
unless new_resource.reboot == :never
reboot "Reboot to join workgroup #{new_resource.workgroup_name}" do
- action clarify_reboot(new_resource.reboot)
+ action new_resource.reboot
reason "Reboot to join workgroup #{new_resource.workgroup_name}"
end
end
@@ -77,19 +89,18 @@ class Chef
end
action_class do
- # This resource historically took `:immediate` and `:delayed` as arguments to the reboot property but then
- # tried to shove that straight to the `reboot` resource which objected strenuously
- def clarify_reboot(reboot_action)
- case reboot_action
- when :immediate
- :reboot_now
- when :delayed
- :request_reboot
- else
- reboot_action
- end
+ # return [String] the appropriate PS command to joint the workgroup
+ def join_command
+ cmd = ""
+ cmd << "$pswd = ConvertTo-SecureString \'#{new_resource.password}\' -AsPlainText -Force;" if new_resource.password
+ cmd << "$credential = New-Object System.Management.Automation.PSCredential (\"#{new_resource.user}\",$pswd);" if new_resource.password
+ cmd << "Add-Computer -WorkgroupName #{new_resource.workgroup_name}"
+ cmd << " -Credential $credential" if new_resource.password
+ cmd << " -Force"
+ cmd
end
+ # @return [Boolean] is the node a member of the workgroup specified in the resource
def workgroup_member?
node_workgroup = powershell_out!("(Get-WmiObject -Class Win32_ComputerSystem).Workgroup")
raise "Failed to determine if system already a member of workgroup #{new_resource.workgroup_name}" if node_workgroup.error?
diff --git a/lib/chef/resource/yum_package.rb b/lib/chef/resource/yum_package.rb
index f0ea7dbf50..602fe489fb 100644
--- a/lib/chef/resource/yum_package.rb
+++ b/lib/chef/resource/yum_package.rb
@@ -69,7 +69,8 @@ class Chef
property :allow_downgrade, [ true, false ],
description: "Downgrade a package to satisfy requested version requirements.",
- default: false
+ default: true,
+ desired_state: false
property :yum_binary, String
end
diff --git a/lib/chef/resource/yum_repository.rb b/lib/chef/resource/yum_repository.rb
index df3bfb6454..f3d73bff53 100644
--- a/lib/chef/resource/yum_repository.rb
+++ b/lib/chef/resource/yum_repository.rb
@@ -45,7 +45,8 @@ class Chef
default: true
property :cost, String, regex: /^\d+$/,
- description: "Relative cost of accessing this repository. Useful for weighing one repo's packages as greater/less than any other."
+ description: "Relative cost of accessing this repository. Useful for weighing one repo's packages as greater/less than any other.",
+ validation_message: "The cost property must be a numeric value!"
property :description, String,
description: "Descriptive name for the repository channel and maps to the 'name' parameter in a repository .conf.",
@@ -73,7 +74,7 @@ class Chef
default: true
property :gpgkey, [String, Array],
- description: "URL pointing to the ASCII-armored GPG key file for the repository. This is used if Yum needs a public key to verify a package and the required key hasn't been imported into the RPM database. If this option is set, Yum will automatically import the key from the specified URL. Multiple URLs may be specified in the same manner as the baseurl option. If a GPG key is required to install a package from a repository, all keys specified for that repository will be installed."
+ description: "URL pointing to the ASCII-armored GPG key file for the repository. This is used if Yum needs a public key to verify a package and the required key hasn't been imported into the RPM database. If this option is set, Yum will automatically import the key from the specified URL. Multiple URLs may be specified in the same manner as the baseurl option. If a GPG key is required to install a package from a repository, all keys specified for that repository will be installed.\nMultiple URLs may be specified in the same manner as the baseurl option. If a GPG key is required to install a package from a repository, all keys specified for that repository will be installed."
property :http_caching, String, equal_to: %w{packages all none},
description: "Determines how upstream HTTP caches are instructed to handle any HTTP downloads that Yum does. This option can take the following values: all (all HTTP downloads should be cached), packages (only RPM package downloads should be cached, but not repository metadata downloads), or none (no HTTP downloads should be cached)"
@@ -95,16 +96,19 @@ class Chef
description: "Number of times any attempt to retrieve a file should retry before returning an error. Setting this to '0' makes Yum try forever."
property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/],
- description: "Time (in seconds) after which the metadata will expire. If the current metadata downloaded is less than the value specified, then Yum will not update the metadata against the repository. If you find that Yum is not downloading information on updates as often as you would like lower the value of this option. You can also change from the default of using seconds to using days, hours or minutes by appending a 'd', 'h' or 'm' respectively. The default is six hours to compliment yum-updates running once per hour. It is also possible to use the word ``never``, meaning that the metadata will never expire. Note: When using a metalink file, the metalink must always be newer than the metadata for the repository due to the validation, so this timeout also applies to the metalink file."
+ description: "Time (in seconds) after which the metadata will expire. If the current metadata downloaded is less than the value specified, then Yum will not update the metadata against the repository. If you find that Yum is not downloading information on updates as often as you would like lower the value of this option. You can also change from the default of using seconds to using days, hours or minutes by appending a 'd', 'h' or 'm' respectively. The default is six hours to compliment yum-updates running once per hour. It is also possible to use the word ``never``, meaning that the metadata will never expire. Note: When using a metalink file, the metalink must always be newer than the metadata for the repository due to the validation, so this timeout also applies to the metalink file.",
+ validation_message: "The metadata_expire property must be a numeric value for time in seconds, the string 'never', or a numeric value appended with with 'd', 'h', or 'm'!"
property :metalink, String,
description: "Specifies a URL to a metalink file for the repomd.xml, a list of mirrors for the entire repository are generated by converting the mirrors for the repomd.xml file to a baseurl."
property :mirror_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/],
- description: "Time (in seconds) after which the mirrorlist locally cached will expire. If the current mirrorlist is less than this many seconds old then Yum will not download another copy of the mirrorlist, it has the same extra format as metadata_expire. If you find that Yum is not downloading the mirrorlists as often as you would like lower the value of this option."
+ description: "Time (in seconds) after which the mirrorlist locally cached will expire. If the current mirrorlist is less than this many seconds old then Yum will not download another copy of the mirrorlist, it has the same extra format as metadata_expire. If you find that Yum is not downloading the mirrorlists as often as you would like lower the value of this option. You can also change from the default of using seconds to using days, hours or minutes by appending a 'd', 'h' or 'm' respectively.",
+ validation_message: "The mirror_expire property must be a numeric value for time in seconds, the string 'never', or a numeric value appended with with 'd', 'h', or 'm'!"
property :mirrorlist_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/],
- description: "Specifies the time (in seconds) after which the mirrorlist locally cached will expire. If the current mirrorlist is less than the value specified, then Yum will not download another copy of the mirrorlist."
+ description: "Specifies the time (in seconds) after which the mirrorlist locally cached will expire. If the current mirrorlist is less than the value specified, then Yum will not download another copy of the mirrorlist. You can also change from the default of using seconds to using days, hours or minutes by appending a 'd', 'h' or 'm' respectively.",
+ validation_message: "The mirrorlist_expire property must be a numeric value for time in seconds, the string 'never', or a numeric value appended with with 'd', 'h', or 'm'!"
property :mirrorlist, String,
description: "URL to a file containing a list of baseurls. This can be used instead of or with the baseurl option. Substitution variables, described below, can be used with this option."
@@ -120,7 +124,8 @@ class Chef
description: "Password to use with the username for basic authentication."
property :priority, String, regex: /^(\d?[1-9]|[0-9][0-9])$/,
- description: "Assigns a priority to a repository where the priority value is between '1' and '99' inclusive. Priorities are used to enforce ordered protection of repositories. Packages from repositories with a lower priority (higher numerical value) will never be used to upgrade packages that were installed from a repository with a higher priority (lower numerical value). The repositories with the lowest numerical priority number have the highest priority."
+ description: "Assigns a priority to a repository where the priority value is between '1' and '99' inclusive. Priorities are used to enforce ordered protection of repositories. Packages from repositories with a lower priority (higher numerical value) will never be used to upgrade packages that were installed from a repository with a higher priority (lower numerical value). The repositories with the lowest numerical priority number have the highest priority.",
+ validation_message: "The priority property must be a numeric value from 1-99!"
property :proxy_password, String,
description: "Password for this proxy."
@@ -138,7 +143,7 @@ class Chef
description: "Determines whether to report the instance ID when using Amazon Linux AMIs and repositories."
property :repositoryid, String, regex: [/^[^\/]+$/],
- description: "Specifies a unique name for each repository, one word. Defaults to name attribute.",
+ description: "Specifies a unique name for each repository, one word. Defaults to name property.",
validation_message: "repositoryid property cannot contain a forward slash '/'",
name_property: true
@@ -164,7 +169,8 @@ class Chef
description: "Enable bandwidth throttling for downloads."
property :timeout, String, regex: /^\d+$/,
- description: "Number of seconds to wait for a connection before timing out. Defaults to 30 seconds. This may be too short of a time for extremely overloaded sites."
+ description: "Number of seconds to wait for a connection before timing out. Defaults to 30 seconds. This may be too short of a time for extremely overloaded sites.",
+ validation_message: "The timeout property must be a numeric value!"
property :username, String,
description: "Username to use for basic authentication to a repository."
diff --git a/lib/chef/resource/zypper_package.rb b/lib/chef/resource/zypper_package.rb
index c4b967381b..c8d776cebb 100644
--- a/lib/chef/resource/zypper_package.rb
+++ b/lib/chef/resource/zypper_package.rb
@@ -29,14 +29,16 @@ class Chef
property :gpg_check, [ TrueClass, FalseClass ],
description: "Verify the package's GPG signature. Can also be controlled site-wide using the ``zypper_check_gpg`` config option.",
- default: lazy { Chef::Config[:zypper_check_gpg] }
+ default: lazy { Chef::Config[:zypper_check_gpg] }, default_description: "true"
property :allow_downgrade, [ TrueClass, FalseClass ],
description: "Allow downgrading a package to satisfy requested version requirements.",
- default: false, introduced: "13.6"
+ default: true,
+ desired_state: false,
+ introduced: "13.6"
property :global_options, [ String, Array ],
- description: "One (or more) additional options that are passed to the package resource other than options to the command.",
+ description: "One (or more) additional command options that are passed to the command. For example, common zypper directives, such as '--no-recommends'. See the zypper man page at https://en.opensuse.org/SDB:Zypper_manual_(plain) for the full list.",
coerce: proc { |x| x.is_a?(String) ? x.shellsplit : x },
introduced: "14.6"
end
diff --git a/lib/chef/resource/zypper_repository.rb b/lib/chef/resource/zypper_repository.rb
index b3e1db6b83..e4db20d446 100644
--- a/lib/chef/resource/zypper_repository.rb
+++ b/lib/chef/resource/zypper_repository.rb
@@ -85,7 +85,8 @@ class Chef
description: "The name of the template for the repository file. Only necessary if you're not using the built in template."
property :cookbook, String,
- description: "The cookbook to source the repository template file from. Only necessary if you're not using the built in template."
+ description: "The cookbook to source the repository template file from. Only necessary if you're not using the built in template.",
+ desired_state: false
property :gpgautoimportkeys, [TrueClass, FalseClass],
description: "Automatically import the specified key when setting up the repository.",
diff --git a/lib/chef/resource_inspector.rb b/lib/chef/resource_inspector.rb
index 7363aad2a6..ac65e55e99 100644
--- a/lib/chef/resource_inspector.rb
+++ b/lib/chef/resource_inspector.rb
@@ -31,7 +31,7 @@ module ResourceInspector
# code for the resource ourselves and just no
"lazy default"
else
- default
+ default.is_a?(Symbol) ? default.inspect : default # inspect properly returns symbols
end
end
@@ -46,9 +46,9 @@ module ResourceInspector
data[:preview] = resource.preview_resource
properties = unless complete
- resource.properties.reject { |_, k| k.options[:declared_in] == Chef::Resource }
+ resource.properties.reject { |_, k| k.options[:declared_in] == Chef::Resource || k.options[:skip_docs] }
else
- resource.properties
+ resource.properties.reject { |_, k| k.options[:skip_docs] }
end
data[:properties] = properties.each_with_object([]) do |(n, k), acc|
@@ -57,7 +57,7 @@ module ResourceInspector
introduced: opts[:introduced], is: opts[:is],
deprecated: opts[:deprecated] || false,
required: opts[:required] || false,
- default: get_default(opts[:default]),
+ default: opts[:default_description] || get_default(opts[:default]),
name_property: opts[:name_property] || false }
end
data
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index 6324ce5b66..32739087d5 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -130,14 +130,17 @@ require "chef/resource/powershell_package"
require "chef/resource/msu_package"
require "chef/resource/windows_ad_join"
require "chef/resource/windows_auto_run"
+require "chef/resource/windows_certificate"
require "chef/resource/windows_feature"
require "chef/resource/windows_feature_dism"
require "chef/resource/windows_feature_powershell"
+require "chef/resource/windows_firewall_rule"
require "chef/resource/windows_font"
require "chef/resource/windows_pagefile"
require "chef/resource/windows_path"
require "chef/resource/windows_printer"
require "chef/resource/windows_printer_port"
+require "chef/resource/windows_share"
require "chef/resource/windows_shortcut"
require "chef/resource/windows_task"
require "chef/resource/windows_workgroup"
diff --git a/lib/chef/run_context/cookbook_compiler.rb b/lib/chef/run_context/cookbook_compiler.rb
index 4edf175824..c3cee5841f 100644
--- a/lib/chef/run_context/cookbook_compiler.rb
+++ b/lib/chef/run_context/cookbook_compiler.rb
@@ -1,6 +1,6 @@
#
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -226,7 +226,7 @@ class Chef
begin
# FIXME(log): should be trace
logger.debug("Loading cookbook #{cookbook_name}'s library file: #{filename}")
- Kernel.load(filename)
+ Kernel.require(filename)
@events.library_file_loaded(filename)
rescue Exception => e
@events.library_file_load_failed(filename, e)
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index b1fbcaefb6..6ee94261a6 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("15.0.8")
+ VERSION = Chef::VersionString.new("15.0.83")
end
#
diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock
index 575ca1f61b..ea3fd8699c 100644
--- a/omnibus/Gemfile.lock
+++ b/omnibus/Gemfile.lock
@@ -18,7 +18,7 @@ GIT
GIT
remote: https://github.com/chef/omnibus-software
- revision: 3b6ef4c42d8c2f9f9e1c6e285b2ea48e0d0f0fdd
+ revision: 1a5846d7afb9ab8f3005cd04d771b057b19ab514
branch: master
specs:
omnibus-software (4.0.0)
@@ -32,8 +32,8 @@ GEM
public_suffix (>= 2.0.2, < 4.0)
awesome_print (1.8.0)
aws-eventstream (1.0.1)
- aws-partitions (1.106.0)
- aws-sdk-core (3.35.0)
+ aws-partitions (1.113.0)
+ aws-sdk-core (3.38.0)
aws-eventstream (~> 1.0)
aws-partitions (~> 1.0)
aws-sigv4 (~> 1.0)
@@ -41,7 +41,7 @@ GEM
aws-sdk-kms (1.11.0)
aws-sdk-core (~> 3, >= 3.26.0)
aws-sigv4 (~> 1.0)
- aws-sdk-s3 (1.23.0)
+ aws-sdk-s3 (1.23.1)
aws-sdk-core (~> 3, >= 3.26.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.0)
@@ -63,10 +63,10 @@ GEM
debug_inspector (>= 0.0.1)
builder (3.2.3)
byebug (10.0.2)
- chef (14.6.47)
+ chef (14.7.17)
addressable
bundler (>= 1.10)
- chef-config (= 14.6.47)
+ chef-config (= 14.7.17)
chef-zero (>= 13.0)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
@@ -93,10 +93,10 @@ GEM
specinfra (~> 2.10)
syslog-logger (~> 1.6)
uuidtools (~> 2.1.5)
- chef (14.6.47-universal-mingw32)
+ chef (14.7.17-universal-mingw32)
addressable
bundler (>= 1.10)
- chef-config (= 14.6.47)
+ chef-config (= 14.7.17)
chef-zero (>= 13.0)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
@@ -125,6 +125,7 @@ GEM
syslog-logger (~> 1.6)
uuidtools (~> 2.1.5)
win32-api (~> 1.5.3)
+ win32-certstore (>= 0.1.8)
win32-dir (~> 0.5.0)
win32-event (~> 0.6.1)
win32-eventlog (= 0.6.3)
@@ -135,23 +136,23 @@ GEM
win32-taskscheduler (~> 2.0)
windows-api (~> 0.4.4)
wmi-lite (~> 1.0)
- chef-config (14.6.47)
+ chef-config (14.7.17)
addressable
fuzzyurl
mixlib-config (>= 2.2.12, < 3.0)
mixlib-shellout (~> 2.0)
tomlrb (~> 1.2)
chef-sugar (4.1.0)
- chef-zero (14.0.6)
+ chef-zero (14.0.11)
ffi-yajl (~> 2.2)
hashie (>= 2.0, < 4.0)
mixlib-log (~> 2.0)
- rack (~> 2.0)
+ rack (~> 2.0, >= 2.0.6)
uuidtools (~> 2.1)
citrus (3.0.2)
cleanroom (1.0.0)
coderay (1.1.2)
- concurrent-ruby (1.0.5)
+ concurrent-ruby (1.1.3)
debug_inspector (0.0.3)
diff-lcs (1.3)
erubis (2.7.0)
@@ -177,7 +178,7 @@ GEM
ipaddress (0.8.3)
iso8601 (0.12.1)
jmespath (1.4.0)
- kitchen-vagrant (1.3.5)
+ kitchen-vagrant (1.3.6)
test-kitchen (~> 1.4)
libyajl2 (1.2.0)
license_scout (1.0.16)
@@ -188,8 +189,8 @@ GEM
logging (2.2.2)
little-plugger (~> 1.1)
multi_json (~> 1.10)
- method_source (0.9.0)
- minitar (0.6.1)
+ method_source (0.9.2)
+ minitar (0.7)
mixlib-archive (0.4.18)
mixlib-log
mixlib-archive (0.4.18-universal-mingw32)
@@ -246,17 +247,17 @@ GEM
plist (3.4.0)
progressbar (1.10.0)
proxifier (1.0.3)
- pry (0.11.3)
+ pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-byebug (3.6.0)
byebug (~> 10.0)
pry (~> 0.10)
- pry-stack_explorer (0.4.9.2)
+ pry-stack_explorer (0.4.9.3)
binding_of_caller (>= 0.7)
pry (>= 0.9.11)
public_suffix (3.0.3)
- rack (2.0.5)
+ rack (2.0.6)
retryable (2.0.4)
rspec (3.8.0)
rspec-core (~> 3.8.0)
@@ -311,12 +312,15 @@ GEM
winrm (~> 2.0)
winrm-elevated (~> 1.0)
winrm-fs (~> 1.1)
- thor (0.20.0)
+ thor (0.20.3)
toml-rb (1.1.2)
citrus (~> 3.0, > 3.0)
tomlrb (1.2.7)
uuidtools (2.1.5)
win32-api (1.5.3-universal-mingw32)
+ win32-certstore (0.1.11)
+ ffi
+ mixlib-shellout
win32-dir (0.5.1)
ffi (>= 1.0.0)
win32-event (0.6.3)
@@ -334,7 +338,7 @@ GEM
win32-service (1.0.1)
ffi
ffi-win32-extensions
- win32-taskscheduler (2.0.0)
+ win32-taskscheduler (2.0.1)
ffi
structured_warnings
windows-api (0.4.4)
@@ -378,4 +382,4 @@ DEPENDENCIES
winrm-fs (~> 1.0)
BUNDLED WITH
- 1.16.6
+ 1.17.1
diff --git a/omnibus/package-scripts/angrychef/postrm b/omnibus/package-scripts/angrychef/postrm
index 247688074e..a153da7102 100755
--- a/omnibus/package-scripts/angrychef/postrm
+++ b/omnibus/package-scripts/angrychef/postrm
@@ -11,11 +11,19 @@ is_smartos() {
uname -v | grep "^joyent" 2>&1 >/dev/null
}
-is_darwin()
-{
+is_darwin() {
uname -v | grep "^Darwin" 2>&1 >/dev/null
}
+is_suse() {
+ if [ -f /etc/os-release ]; then
+ . /etc/os-release
+ [ "$ID_LIKE" = "sles" ] || [ "$ID_LIKE" = "suse" ]
+ else
+ [ -f /etc/SuSE-release ]
+ fi
+}
+
if is_smartos; then
PREFIX="/opt/local"
elif is_darwin; then
@@ -33,7 +41,7 @@ cleanup_symlinks() {
# Clean up binary symlinks if they exist
# see: http://tickets.opscode.com/browse/CHEF-3022
-if [ ! -f /etc/redhat-release -a ! -f /etc/fedora-release -a ! -f /etc/system-release -a ! -f /etc/SuSE-release ]; then
+if [ ! -f /etc/redhat-release -a ! -f /etc/fedora-release -a ! -f /etc/system-release -a ! is_suse ]; then
# not a redhat-ish RPM-based system
cleanup_symlinks
elif [ "x$1" = "x0" ]; then
diff --git a/omnibus/package-scripts/angrychef/preinst b/omnibus/package-scripts/angrychef/preinst
new file mode 100755
index 0000000000..b3038a10c6
--- /dev/null
+++ b/omnibus/package-scripts/angrychef/preinst
@@ -0,0 +1,12 @@
+#!/bin/sh
+# WARNING: REQUIRES /bin/sh
+#
+# - must run on /bin/sh on solaris 9
+# - must run on /bin/sh on AIX 6.x
+# - if you think you are a bash wizard, you probably do not understand
+# this programming language. do not touch.
+# - if you are under 40, get peer review from your elders.
+
+INSTALLER_DIR=/opt/angrychef
+echo "removing $INSTALLER_DIR..."
+rm -rf $INSTALLER_DIR
diff --git a/omnibus/package-scripts/chef-fips/postrm b/omnibus/package-scripts/chef-fips/postrm
index 247688074e..a153da7102 100755
--- a/omnibus/package-scripts/chef-fips/postrm
+++ b/omnibus/package-scripts/chef-fips/postrm
@@ -11,11 +11,19 @@ is_smartos() {
uname -v | grep "^joyent" 2>&1 >/dev/null
}
-is_darwin()
-{
+is_darwin() {
uname -v | grep "^Darwin" 2>&1 >/dev/null
}
+is_suse() {
+ if [ -f /etc/os-release ]; then
+ . /etc/os-release
+ [ "$ID_LIKE" = "sles" ] || [ "$ID_LIKE" = "suse" ]
+ else
+ [ -f /etc/SuSE-release ]
+ fi
+}
+
if is_smartos; then
PREFIX="/opt/local"
elif is_darwin; then
@@ -33,7 +41,7 @@ cleanup_symlinks() {
# Clean up binary symlinks if they exist
# see: http://tickets.opscode.com/browse/CHEF-3022
-if [ ! -f /etc/redhat-release -a ! -f /etc/fedora-release -a ! -f /etc/system-release -a ! -f /etc/SuSE-release ]; then
+if [ ! -f /etc/redhat-release -a ! -f /etc/fedora-release -a ! -f /etc/system-release -a ! is_suse ]; then
# not a redhat-ish RPM-based system
cleanup_symlinks
elif [ "x$1" = "x0" ]; then
diff --git a/omnibus/package-scripts/chef-fips/preinst b/omnibus/package-scripts/chef-fips/preinst
new file mode 100755
index 0000000000..834c29544b
--- /dev/null
+++ b/omnibus/package-scripts/chef-fips/preinst
@@ -0,0 +1,12 @@
+#!/bin/sh
+# WARNING: REQUIRES /bin/sh
+#
+# - must run on /bin/sh on solaris 9
+# - must run on /bin/sh on AIX 6.x
+# - if you think you are a bash wizard, you probably do not understand
+# this programming language. do not touch.
+# - if you are under 40, get peer review from your elders.
+
+INSTALLER_DIR=/opt/chef-fips
+echo "removing $INSTALLER_DIR..."
+rm -rf $INSTALLER_DIR
diff --git a/omnibus/package-scripts/chef/postrm b/omnibus/package-scripts/chef/postrm
index 247688074e..a153da7102 100755
--- a/omnibus/package-scripts/chef/postrm
+++ b/omnibus/package-scripts/chef/postrm
@@ -11,11 +11,19 @@ is_smartos() {
uname -v | grep "^joyent" 2>&1 >/dev/null
}
-is_darwin()
-{
+is_darwin() {
uname -v | grep "^Darwin" 2>&1 >/dev/null
}
+is_suse() {
+ if [ -f /etc/os-release ]; then
+ . /etc/os-release
+ [ "$ID_LIKE" = "sles" ] || [ "$ID_LIKE" = "suse" ]
+ else
+ [ -f /etc/SuSE-release ]
+ fi
+}
+
if is_smartos; then
PREFIX="/opt/local"
elif is_darwin; then
@@ -33,7 +41,7 @@ cleanup_symlinks() {
# Clean up binary symlinks if they exist
# see: http://tickets.opscode.com/browse/CHEF-3022
-if [ ! -f /etc/redhat-release -a ! -f /etc/fedora-release -a ! -f /etc/system-release -a ! -f /etc/SuSE-release ]; then
+if [ ! -f /etc/redhat-release -a ! -f /etc/fedora-release -a ! -f /etc/system-release -a ! is_suse ]; then
# not a redhat-ish RPM-based system
cleanup_symlinks
elif [ "x$1" = "x0" ]; then
diff --git a/omnibus/package-scripts/chef/preinst b/omnibus/package-scripts/chef/preinst
new file mode 100755
index 0000000000..1880275e99
--- /dev/null
+++ b/omnibus/package-scripts/chef/preinst
@@ -0,0 +1,12 @@
+#!/bin/sh
+# WARNING: REQUIRES /bin/sh
+#
+# - must run on /bin/sh on solaris 9
+# - must run on /bin/sh on AIX 6.x
+# - if you think you are a bash wizard, you probably do not understand
+# this programming language. do not touch.
+# - if you are under 40, get peer review from your elders.
+
+INSTALLER_DIR=/opt/chef
+echo "removing $INSTALLER_DIR..."
+rm -rf $INSTALLER_DIR
diff --git a/spec/functional/resource/windows_task_spec.rb b/spec/functional/resource/windows_task_spec.rb
index cb14da80d8..9b355d37ed 100644
--- a/spec/functional/resource/windows_task_spec.rb
+++ b/spec/functional/resource/windows_task_spec.rb
@@ -132,6 +132,45 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
end
+ context "when description is passed" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
+ new_resource.command task_name
+ # Make sure MM/DD/YYYY is accepted
+ new_resource.start_day "09/20/2017"
+ new_resource.frequency :hourly
+ new_resource
+ end
+
+ let(:some_description) { "this is test description" }
+
+ it "create the task and sets its description" do
+ subject.description some_description
+ call_for_create_action
+ # loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ expect(current_resource.task.description).to eq(some_description)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.description some_description
+ subject.run_action(:create)
+ subject.description some_description
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "updates task with new description if task already exist" do
+ subject.description some_description
+ subject.run_action(:create)
+ subject.description "test description"
+ subject.run_action(:create)
+ expect(subject).to be_updated_by_last_action
+ end
+ end
+
context "when frequency_modifier are not passed" do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
diff --git a/spec/functional/resource/yum_package_spec.rb b/spec/functional/resource/yum_package_spec.rb
index 3735e67cf2..f99f03bdf1 100644
--- a/spec/functional/resource/yum_package_spec.rb
+++ b/spec/functional/resource/yum_package_spec.rb
@@ -443,8 +443,9 @@ describe Chef::Resource::YumPackage, :requires_root, external: exclude_test do
expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
- it "downgrade on a local file is ignored" do
+ it "downgrade on a local file is ignored when allow_downgrade is false" do
preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ yum_package.allow_downgrade false
yum_package.version "1.2-1"
yum_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
yum_package.run_action(:install)
@@ -485,6 +486,24 @@ describe Chef::Resource::YumPackage, :requires_root, external: exclude_test do
expect(yum_package.updated_by_last_action?).to be false
expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
+
+ it "is idempotent when the package is already installed and there is a version string" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ yum_package.version "1.2-1"
+ yum_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ yum_package.run_action(:install)
+ expect(yum_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ end
+
+ it "is idempotent when the package is already installed and there is a version string with arch" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ yum_package.version "1.2-1.#{pkg_arch}"
+ yum_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ yum_package.run_action(:install)
+ expect(yum_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ end
end
context "with no available version" do
diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb
index 4408c00b23..7800cf653d 100644
--- a/spec/integration/client/client_spec.rb
+++ b/spec/integration/client/client_spec.rb
@@ -366,26 +366,6 @@ EOM
end
end
- when_the_repository "has a cookbook that uses chef-provisioning resources" do
- before do
- file "cookbooks/x/recipes/default.rb", <<-EOM
- with_driver 'blah'
- EOM
- file "config/client.rb", <<-EOM
- local_mode true
- cookbook_path "#{path_to('cookbooks')}"
- EOM
- end
-
- it "the cheffish DSL tries to load but fails (because chef-provisioning is not there)" do
- # we'd need to have a custom bundle to fix this that omitted chef-provisioning, but that would dig our crazy even deeper, so lets not
- skip "but if chef-provisioning is in our bundle or in our gemset then this test, very annoyingly, always fails"
- command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", cwd: chef_dir)
- expect(command.exitstatus).to eql(1)
- expect(command.stdout).to match(/cannot load such file -- chef\/provisioning/)
- end
- end
-
when_the_repository "has a cookbook that generates deprecation warnings" do
before do
file "cookbooks/x/recipes/default.rb", <<-EOM
diff --git a/spec/integration/knife/raw_spec.rb b/spec/integration/knife/raw_spec.rb
index 1c8239746f..04f14be335 100644
--- a/spec/integration/knife/raw_spec.rb
+++ b/spec/integration/knife/raw_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: John Keiser (<jkeiser@chef.io>)
-# Copyright:: Copyright 2013-2016, Chef Software Inc.
+# Copyright:: Copyright 2013-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -190,12 +190,14 @@ EOM
app = lambda do |env|
[200, { "Content-Type" => "application/json" }, ['{ "x": "y", "a": "b" }'] ]
end
- @raw_server, @raw_server_thread = start_app_server(app, 9018)
+ @raw_server_thread = start_app_server(app, 9018)
end
after :each do
- @raw_server.shutdown if @raw_server
- @raw_server_thread.kill if @raw_server_thread
+ if @raw_server_thread
+ @raw_server_thread.kill
+ @raw_server_thread.join(30)
+ end
end
it "knife raw /blah returns the prettified json", skip: (RUBY_VERSION < "1.9") do
@@ -220,12 +222,14 @@ EOM
app = lambda do |env|
[200, { "Content-Type" => "text" }, ['{ "x": "y", "a": "b" }'] ]
end
- @raw_server, @raw_server_thread = start_app_server(app, 9018)
+ @raw_server_thread = start_app_server(app, 9018)
end
after :each do
- @raw_server.shutdown if @raw_server
- @raw_server_thread.kill if @raw_server_thread
+ if @raw_server_thread
+ @raw_server_thread.kill
+ @raw_server_thread.join(30)
+ end
end
it "knife raw /blah returns the raw text" do
diff --git a/spec/integration/knife/redirection_spec.rb b/spec/integration/knife/redirection_spec.rb
index 29c1ee6ffb..d387b10e3b 100644
--- a/spec/integration/knife/redirection_spec.rb
+++ b/spec/integration/knife/redirection_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: John Keiser (<jkeiser@chef.io>)
-# Copyright:: Copyright 2013-2016, Chef Software Inc.
+# Copyright:: Copyright 2013-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -36,12 +36,14 @@ describe "redirection", :workstation do
app = lambda do |env|
[302, { "Content-Type" => "text", "Location" => "#{real_chef_server_url}#{env['PATH_INFO']}" }, ["302 found"] ]
end
- @redirector_server, @redirector_server_thread = start_app_server(app, 9018)
+ @redirector_server_thread = start_app_server(app, 9018)
end
after :each do
- @redirector_server.shutdown if @redirector_server
- @redirector_thread.kill if @redirector_thread
+ if @redirector_thread
+ @redirector_thread.kill
+ @redirector_thread.join(30)
+ end
end
it "knife list /roles returns the role" do
diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb
index 6ae052ba1d..5ae9c01722 100644
--- a/spec/support/platform_helpers.rb
+++ b/spec/support/platform_helpers.rb
@@ -220,7 +220,8 @@ def selinux_enabled?
end
def suse?
- File.exists?("/etc/SuSE-release")
+ ::File.exists?("/etc/SuSE-release") ||
+ ( ::File.exists?("/etc/os-release") && /sles|suse/.match?(File.read("/etc/os-release")) )
end
def root?
diff --git a/spec/support/shared/integration/app_server_support.rb b/spec/support/shared/integration/app_server_support.rb
index c0b24d9443..7f05b14689 100644
--- a/spec/support/shared/integration/app_server_support.rb
+++ b/spec/support/shared/integration/app_server_support.rb
@@ -1,7 +1,7 @@
#
# Author:: John Keiser (<jkeiser@chef.io>)
# Author:: Ho-Sheng Hsiao (<hosh@chef.io>)
-# Copyright:: Copyright 2012-2016 Chef Software, Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,6 +35,6 @@ module AppServerSupport
Timeout.timeout(30) do
sleep(0.01) until server && server.status == :Running
end
- [server, thread]
+ thread
end
end
diff --git a/spec/unit/cookbook/cookbook_version_loader_spec.rb b/spec/unit/cookbook/cookbook_version_loader_spec.rb
index 40a054abee..c38af059f5 100644
--- a/spec/unit/cookbook/cookbook_version_loader_spec.rb
+++ b/spec/unit/cookbook/cookbook_version_loader_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -173,7 +173,7 @@ describe Chef::Cookbook::CookbookVersionLoader do
let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "incomplete-metadata-chef-repo/incomplete-metadata") }
let(:error_message) do
- "Cookbook loaded at path(s) [#{cookbook_path}] has invalid metadata: The `name' attribute is required in cookbook metadata"
+ "Cookbook loaded at path [#{cookbook_path}] has invalid metadata: The `name' attribute is required in cookbook metadata"
end
it "raises an error when loading with #load!" do
diff --git a/spec/unit/cookbook_loader_spec.rb b/spec/unit/cookbook_loader_spec.rb
index 15c7d1e299..ddb4f00f35 100644
--- a/spec/unit/cookbook_loader_spec.rb
+++ b/spec/unit/cookbook_loader_spec.rb
@@ -59,7 +59,6 @@ describe Chef::CookbookLoader do
]
end
it "should not support multiple merged cookbooks in the cookbook path" do
- start_merged_cookbooks = cookbook_loader.merged_cookbooks
expect { cookbook_loader.load_cookbooks }.to raise_error(Chef::Exceptions::CookbookMergingError)
end
end
@@ -197,7 +196,9 @@ describe Chef::CookbookLoader do
end
it "should not load the cookbook again when accessed" do
- expect(cookbook_loader).not_to receive("load_cookbook")
+ cookbook_loader.send(:cookbook_version_loaders).each do |cbv_loader|
+ expect(cbv_loader).not_to receive(:load)
+ end
cookbook_loader["openldap"]
end
diff --git a/spec/unit/knife/cookbook_create_spec.rb b/spec/unit/knife/cookbook_create_spec.rb
deleted file mode 100644
index ef86a0cd2b..0000000000
--- a/spec/unit/knife/cookbook_create_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Author:: Nuo Yan (<nuo@chef.io>)
-# Copyright:: Copyright 2010-2016, 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"
-require "tmpdir"
-
-describe Chef::Knife::CookbookCreate do
- before(:each) do
- Chef::Config[:node_name] = "webmonkey.example.com"
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- @knife = Chef::Knife::CookbookCreate.new
- @knife.config = {}
- @knife.name_args = ["foobar"]
- @stdout = StringIO.new
- allow(@knife).to receive(:stdout).and_return(@stdout)
- end
-
- describe "run" do
-
- # Fixes CHEF-2579
- it "should expand the path of the cookbook directory" do
- expect(Chef::Log).to receive(:fatal).with("knife cookbook create has been removed. Please use `chef generate cookbook` from the ChefDK")
- @knife.run
- end
-
- end
-end
diff --git a/spec/unit/knife/cookbook_test_spec.rb b/spec/unit/knife/cookbook_test_spec.rb
deleted file mode 100644
index dd5d4f096a..0000000000
--- a/spec/unit/knife/cookbook_test_spec.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-#
-# Author:: Stephen Delano (<stephen@chef.io>)$
-# Author:: Matthew Kent (<mkent@magoazul.com>)
-# Copyright:: Copyright 2010-2018, Chef Software Inc.$
-# Copyright:: Copyright 2010-2016, Matthew Kent
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "spec_helper"
-Chef::Knife::CookbookTest.load_deps
-
-describe Chef::Knife::CookbookTest do
- before(:each) do
- Chef::Config[:node_name] = "webmonkey.example.com"
- @knife = Chef::Knife::CookbookTest.new
- @knife.config[:cookbook_path] = File.join(CHEF_SPEC_DATA, "cookbooks")
- allow(@knife.cookbook_loader).to receive(:cookbook_exists?).and_return(true)
- @cookbooks = []
- %w{tats central_market jimmy_johns pho}.each do |cookbook_name|
- @cookbooks << Chef::CookbookVersion.new(cookbook_name)
- end
- @stdout = StringIO.new
- allow(@knife.ui).to receive(:stdout).and_return(@stdout)
- end
-
- describe "run" do
- it "should test the cookbook" do
- allow(@knife).to receive(:test_cookbook).and_return(true)
- @knife.name_args = ["italian"]
- expect(@knife).to receive(:test_cookbook).with("italian")
- @knife.run
- end
-
- it "should test multiple cookbooks when provided" do
- allow(@knife).to receive(:test_cookbook).and_return(true)
- @knife.name_args = %w{tats jimmy_johns}
- expect(@knife).to receive(:test_cookbook).with("tats")
- expect(@knife).to receive(:test_cookbook).with("jimmy_johns")
- expect(@knife).not_to receive(:test_cookbook).with("central_market")
- expect(@knife).not_to receive(:test_cookbook).with("pho")
- @knife.run
- end
-
- it "should test both ruby and templates" do
- @knife.name_args = ["example"]
- expect(@knife.config[:cookbook_path]).not_to be_empty
- Array(@knife.config[:cookbook_path]).reverse_each do |path|
- expect(@knife).to receive(:test_ruby).with(an_instance_of(Chef::Cookbook::SyntaxCheck))
- expect(@knife).to receive(:test_templates).with(an_instance_of(Chef::Cookbook::SyntaxCheck))
- end
- @knife.run
- end
-
- describe "with -a or --all" do
- it "should test all of the cookbooks" do
- allow(@knife).to receive(:test_cookbook).and_return(true)
- @knife.config[:all] = true
- @loader = {}
- allow(@loader).to receive(:load_cookbooks).and_return(@loader)
- @cookbooks.each do |cookbook|
- @loader[cookbook.name] = cookbook
- end
- allow(@knife).to receive(:cookbook_loader).and_return(@loader)
- @loader.each_value do |cookbook|
- expect(@knife).to receive(:test_cookbook).with(cookbook.name)
- end
- @knife.run
- end
- end
-
- end
-end
diff --git a/spec/unit/knife/osc_user_create_spec.rb b/spec/unit/knife/osc_user_create_spec.rb
deleted file mode 100644
index 0413d46f78..0000000000
--- a/spec/unit/knife/osc_user_create_spec.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-2016, 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"
-
-Chef::Knife::OscUserCreate.load_deps
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_create_spec.rb.
-
-describe Chef::Knife::OscUserCreate do
- before(:each) do
- @knife = Chef::Knife::OscUserCreate.new
-
- @stdout = StringIO.new
- @stderr = StringIO.new
- allow(@knife.ui).to receive(:stdout).and_return(@stdout)
- allow(@knife.ui).to receive(:stderr).and_return(@stderr)
-
- @knife.name_args = [ "a_user" ]
- @knife.config[:user_password] = "foobar"
- @user = Chef::User.new
- @user.name "a_user"
- @user_with_private_key = Chef::User.new
- @user_with_private_key.name "a_user"
- @user_with_private_key.private_key "private_key"
- allow(@user).to receive(:create).and_return(@user_with_private_key)
- allow(Chef::User).to receive(:new).and_return(@user)
- allow(Chef::User).to receive(:from_hash).and_return(@user)
- allow(@knife).to receive(:edit_hash).and_return(@user.to_hash)
- end
-
- it "creates a new user" do
- expect(Chef::User).to receive(:new).and_return(@user)
- expect(@user).to receive(:create)
- @knife.run
- expect(@stderr.string).to match /created user.+a_user/i
- end
-
- it "sets the password" do
- @knife.config[:user_password] = "a_password"
- expect(@user).to receive(:password).with("a_password")
- @knife.run
- end
-
- it "exits with an error if password is blank" do
- @knife.config[:user_password] = ""
- expect { @knife.run }.to raise_error SystemExit
- expect(@stderr.string).to match /You must specify a non-blank password/
- end
-
- it "sets the user name" do
- expect(@user).to receive(:name).with("a_user")
- @knife.run
- end
-
- it "sets the public key if given" do
- @knife.config[:user_key] = "/a/filename"
- allow(File).to receive(:read).with(File.expand_path("/a/filename")).and_return("a_key")
- expect(@user).to receive(:public_key).with("a_key")
- @knife.run
- end
-
- it "allows you to edit the data" do
- expect(@knife).to receive(:edit_hash).with(@user)
- @knife.run
- end
-
- it "writes the private key to a file when --file is specified" do
- @knife.config[:file] = "/tmp/a_file"
- filehandle = double("filehandle")
- expect(filehandle).to receive(:print).with("private_key")
- expect(File).to receive(:open).with("/tmp/a_file", "w").and_yield(filehandle)
- @knife.run
- end
-end
diff --git a/spec/unit/knife/osc_user_delete_spec.rb b/spec/unit/knife/osc_user_delete_spec.rb
deleted file mode 100644
index 6e90988156..0000000000
--- a/spec/unit/knife/osc_user_delete_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-2016, 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"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_delete_spec.rb.
-
-describe Chef::Knife::OscUserDelete do
- before(:each) do
- Chef::Knife::OscUserDelete.load_deps
- @knife = Chef::Knife::OscUserDelete.new
- @knife.name_args = [ "my_user" ]
- end
-
- it "deletes the user" do
- expect(@knife).to receive(:delete_object).with(Chef::User, "my_user")
- @knife.run
- end
-
- it "prints usage and exits when a user name is not provided" do
- @knife.name_args = []
- expect(@knife).to receive(:show_usage)
- expect(@knife.ui).to receive(:fatal)
- expect { @knife.run }.to raise_error(SystemExit)
- end
-end
diff --git a/spec/unit/knife/osc_user_edit_spec.rb b/spec/unit/knife/osc_user_edit_spec.rb
deleted file mode 100644
index 1792e38027..0000000000
--- a/spec/unit/knife/osc_user_edit_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-2016, 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"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_edit_spec.rb.
-
-describe Chef::Knife::OscUserEdit do
- before(:each) do
- @stderr = StringIO.new
- @stdout = StringIO.new
-
- Chef::Knife::OscUserEdit.load_deps
- @knife = Chef::Knife::OscUserEdit.new
- allow(@knife.ui).to receive(:stderr).and_return(@stderr)
- allow(@knife.ui).to receive(:stdout).and_return(@stdout)
- @knife.name_args = [ "my_user" ]
- @knife.config[:disable_editing] = true
- end
-
- it "loads and edits the user" do
- data = { name: "my_user" }
- allow(Chef::User).to receive(:load).with("my_user").and_return(data)
- expect(@knife).to receive(:edit_hash).with(data).and_return(data)
- @knife.run
- end
-
- it "prints usage and exits when a user name is not provided" do
- @knife.name_args = []
- expect(@knife).to receive(:show_usage)
- expect(@knife.ui).to receive(:fatal)
- expect { @knife.run }.to raise_error(SystemExit)
- end
-end
diff --git a/spec/unit/knife/osc_user_reregister_spec.rb b/spec/unit/knife/osc_user_reregister_spec.rb
deleted file mode 100644
index b0ac92568e..0000000000
--- a/spec/unit/knife/osc_user_reregister_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-2016, 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"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_reregister_spec.rb.
-
-describe Chef::Knife::OscUserReregister do
- before(:each) do
- Chef::Knife::OscUserReregister.load_deps
- @knife = Chef::Knife::OscUserReregister.new
- @knife.name_args = [ "a_user" ]
- @user_mock = double("user_mock", private_key: "private_key")
- allow(Chef::User).to receive(:load).and_return(@user_mock)
- @stdout = StringIO.new
- allow(@knife.ui).to receive(:stdout).and_return(@stdout)
- end
-
- it "prints usage and exits when a user name is not provided" do
- @knife.name_args = []
- expect(@knife).to receive(:show_usage)
- expect(@knife.ui).to receive(:fatal)
- expect { @knife.run }.to raise_error(SystemExit)
- end
-
- it "reregisters the user and prints the key" do
- expect(@user_mock).to receive(:reregister).and_return(@user_mock)
- @knife.run
- expect(@stdout.string).to match( /private_key/ )
- end
-
- it "writes the private key to a file when --file is specified" do
- expect(@user_mock).to receive(:reregister).and_return(@user_mock)
- @knife.config[:file] = "/tmp/a_file"
- filehandle = StringIO.new
- expect(File).to receive(:open).with("/tmp/a_file", "w").and_yield(filehandle)
- @knife.run
- expect(filehandle.string).to eq("private_key")
- end
-end
diff --git a/spec/unit/knife/osc_user_show_spec.rb b/spec/unit/knife/osc_user_show_spec.rb
deleted file mode 100644
index ecdb0a9fce..0000000000
--- a/spec/unit/knife/osc_user_show_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# Author:: Steven Danna (<steve@chef.io>)
-# Copyright:: Copyright 2012-2016, 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"
-
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur user_show_spec.rb.
-
-describe Chef::Knife::OscUserShow do
- before(:each) do
- Chef::Knife::OscUserShow.load_deps
- @knife = Chef::Knife::OscUserShow.new
- @knife.name_args = [ "my_user" ]
- @user_mock = double("user_mock")
- end
-
- it "loads and displays the user" do
- expect(Chef::User).to receive(:load).with("my_user").and_return(@user_mock)
- expect(@knife).to receive(:format_for_display).with(@user_mock)
- @knife.run
- end
-
- it "prints usage and exits when a user name is not provided" do
- @knife.name_args = []
- expect(@knife).to receive(:show_usage)
- expect(@knife.ui).to receive(:fatal)
- expect { @knife.run }.to raise_error(SystemExit)
- end
-end
diff --git a/spec/unit/knife/user_create_spec.rb b/spec/unit/knife/user_create_spec.rb
index 07d72fd05a..375077abb3 100644
--- a/spec/unit/knife/user_create_spec.rb
+++ b/spec/unit/knife/user_create_spec.rb
@@ -38,25 +38,6 @@ describe Chef::Knife::UserCreate do
allow(knife.ui).to receive(:warn)
end
- # delete this once OSC11 support is gone
- context "when only one name_arg is passed" do
- before do
- knife.name_args = ["some_user"]
- allow(knife).to receive(:run_osc_11_user_create).and_raise(SystemExit)
- end
-
- it "displays the osc warning" do
- expect(knife.ui).to receive(:warn).with(knife.osc_11_warning)
- expect { knife.run }.to raise_error(SystemExit)
- end
-
- it "calls knife osc_user create" do
- expect(knife).to receive(:run_osc_11_user_create)
- expect { knife.run }.to raise_error(SystemExit)
- end
-
- end
-
context "when USERNAME isn't specified" do
# from spec/support/shared/unit/knife_shared.rb
it_should_behave_like "mandatory field missing" do
@@ -65,17 +46,6 @@ describe Chef::Knife::UserCreate do
end
end
- # uncomment once OSC11 support is gone,
- # pending doesn't work for shared_examples_for by default
- #
- # context "when DISPLAY_NAME isn't specified" do
- # # from spec/support/shared/unit/knife_shared.rb
- # it_should_behave_like "mandatory field missing" do
- # let(:name_args) { ['some_user'] }
- # let(:fieldname) { 'display name' }
- # end
- # end
-
context "when FIRST_NAME isn't specified" do
# from spec/support/shared/unit/knife_shared.rb
it_should_behave_like "mandatory field missing" do
diff --git a/spec/unit/knife/user_delete_spec.rb b/spec/unit/knife/user_delete_spec.rb
index 68749fe727..b8649e2fbd 100644
--- a/spec/unit/knife/user_delete_spec.rb
+++ b/spec/unit/knife/user_delete_spec.rb
@@ -32,27 +32,8 @@ describe Chef::Knife::UserDelete do
allow(knife.ui).to receive(:stdout).and_return(stdout)
end
- # delete this once OSC11 support is gone
- context "when the username field is not supported by the server" do
- before do
- allow(knife).to receive(:run_osc_11_user_delete).and_raise(SystemExit)
- allow(user).to receive(:username).and_return(nil)
- end
-
- it "displays the osc warning" do
- expect(knife.ui).to receive(:warn).with(knife.osc_11_warning)
- expect { knife.run }.to raise_error(SystemExit)
- end
-
- it "forwards the command to knife osc_user edit" do
- expect(knife).to receive(:run_osc_11_user_delete)
- expect { knife.run }.to raise_error(SystemExit)
- end
- end
-
it "deletes the user" do
- # expect(knife).to receive(:delete_object).with(Chef::UserV1, 'my_user')
- expect(knife).to receive(:delete_object).with("my_user")
+ expect(knife).to receive(:delete_object).with(Chef::UserV1, "my_user")
knife.run
end
diff --git a/spec/unit/knife/user_edit_spec.rb b/spec/unit/knife/user_edit_spec.rb
index 18ade54068..8ebc19de2d 100644
--- a/spec/unit/knife/user_edit_spec.rb
+++ b/spec/unit/knife/user_edit_spec.rb
@@ -32,24 +32,6 @@ describe Chef::Knife::UserEdit do
knife.config[:disable_editing] = true
end
- # delete this once OSC11 support is gone
- context "when the username field is not supported by the server" do
- before do
- allow(knife).to receive(:run_osc_11_user_edit).and_raise(SystemExit)
- allow(Chef::UserV1).to receive(:load).and_return({ "username" => nil })
- end
-
- it "displays the osc warning" do
- expect(knife.ui).to receive(:warn).with(knife.osc_11_warning)
- expect { knife.run }.to raise_error(SystemExit)
- end
-
- it "forwards the command to knife osc_user edit" do
- expect(knife).to receive(:run_osc_11_user_edit)
- expect { knife.run }.to raise_error(SystemExit)
- end
- end
-
it "loads and edits the user" do
data = { "username" => "my_user" }
allow(Chef::UserV1).to receive(:load).with("my_user").and_return(data)
diff --git a/spec/unit/knife/user_reregister_spec.rb b/spec/unit/knife/user_reregister_spec.rb
index 8501347087..2c861ff35d 100644
--- a/spec/unit/knife/user_reregister_spec.rb
+++ b/spec/unit/knife/user_reregister_spec.rb
@@ -32,24 +32,6 @@ describe Chef::Knife::UserReregister do
allow(user_mock).to receive(:username).and_return("a_user")
end
- # delete this once OSC11 support is gone
- context "when the username field is not supported by the server" do
- before do
- allow(knife).to receive(:run_osc_11_user_reregister).and_raise(SystemExit)
- allow(user_mock).to receive(:username).and_return(nil)
- end
-
- it "displays the osc warning" do
- expect(knife.ui).to receive(:warn).with(knife.osc_11_warning)
- expect { knife.run }.to raise_error(SystemExit)
- end
-
- it "forwards the command to knife osc_user edit" do
- expect(knife).to receive(:run_osc_11_user_reregister)
- expect { knife.run }.to raise_error(SystemExit)
- end
- end
-
it "prints usage and exits when a user name is not provided" do
knife.name_args = []
expect(knife).to receive(:show_usage)
diff --git a/spec/unit/knife/user_show_spec.rb b/spec/unit/knife/user_show_spec.rb
index 3a38161b34..c15dfed43c 100644
--- a/spec/unit/knife/user_show_spec.rb
+++ b/spec/unit/knife/user_show_spec.rb
@@ -31,25 +31,6 @@ describe Chef::Knife::UserShow do
allow(knife.ui).to receive(:stdout).and_return(stdout)
end
- # delete this once OSC11 support is gone
- context "when the username field is not supported by the server" do
- before do
- allow(knife).to receive(:run_osc_11_user_show).and_raise(SystemExit)
- allow(Chef::UserV1).to receive(:load).with("my_user").and_return(user_mock)
- allow(user_mock).to receive(:username).and_return(nil)
- end
-
- it "displays the osc warning" do
- expect(knife.ui).to receive(:warn).with(knife.osc_11_warning)
- expect { knife.run }.to raise_error(SystemExit)
- end
-
- it "forwards the command to knife osc_user edit" do
- expect(knife).to receive(:run_osc_11_user_show)
- expect { knife.run }.to raise_error(SystemExit)
- end
- end
-
it "loads and displays the user" do
expect(Chef::UserV1).to receive(:load).with("my_user").and_return(user_mock)
expect(knife).to receive(:format_for_display).with(user_mock)
diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb
index 36827215f0..c6fdf1e1c2 100644
--- a/spec/unit/node/attribute_spec.rb
+++ b/spec/unit/node/attribute_spec.rb
@@ -1273,4 +1273,34 @@ describe Chef::Node::Attribute do
expect { @attributes["foo"]["bar"][0] << "buzz" }.to raise_error(RuntimeError, "can't modify frozen String")
end
end
+
+ describe "deep merging with nils" do
+ it "nils when deep merging between default levels knocks out values" do
+ @attributes.default["foo"] = "bar"
+ expect(@attributes["foo"]).to eql("bar")
+ @attributes.force_default["foo"] = nil
+ expect(@attributes["foo"]).to be nil
+ end
+
+ it "nils when deep merging between override levels knocks out values" do
+ @attributes.override["foo"] = "bar"
+ expect(@attributes["foo"]).to eql("bar")
+ @attributes.force_override["foo"] = nil
+ expect(@attributes["foo"]).to be nil
+ end
+
+ it "nils when deep merging between default+override levels knocks out values" do
+ @attributes.default["foo"] = "bar"
+ expect(@attributes["foo"]).to eql("bar")
+ @attributes.override["foo"] = nil
+ expect(@attributes["foo"]).to be nil
+ end
+
+ it "nils when deep merging between normal+automatic levels knocks out values" do
+ @attributes.normal["foo"] = "bar"
+ expect(@attributes["foo"]).to eql("bar")
+ @attributes.automatic["foo"] = nil
+ expect(@attributes["foo"]).to be nil
+ end
+ end
end
diff --git a/spec/unit/node/immutable_collections_spec.rb b/spec/unit/node/immutable_collections_spec.rb
index 273c3d2704..2208c45717 100644
--- a/spec/unit/node/immutable_collections_spec.rb
+++ b/spec/unit/node/immutable_collections_spec.rb
@@ -209,7 +209,6 @@ describe Chef::Node::ImmutableArray do
:merge!,
:pop,
:push,
- :update,
:reject!,
:reverse!,
:replace,
diff --git a/spec/unit/node/vivid_mash_spec.rb b/spec/unit/node/vivid_mash_spec.rb
index e1021ba0c0..cfdc813b50 100644
--- a/spec/unit/node/vivid_mash_spec.rb
+++ b/spec/unit/node/vivid_mash_spec.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2016, Chef Software Inc.
+# Copyright:: Copyright 2016-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -351,3 +351,108 @@ describe Chef::Node::VividMash do
end
end
end
+
+describe Chef::Node::AttrArray do
+ let(:root) { instance_double(Chef::Node::Attribute) }
+
+ let(:array) do
+ Chef::Node::AttrArray.new(
+ %w{zero one two},
+ root
+ )
+ end
+
+ context "#<<" do
+ it "converts a Hash appended with #<< to a VividMash" do
+ array << { "three" => "four" }
+ expect(array[3].class).to eql(Chef::Node::VividMash)
+ end
+
+ it "deeply converts objects appended with #<<" do
+ array << [ { "three" => [ 0, 1] } ]
+ expect(array[3].class).to eql(Chef::Node::AttrArray)
+ expect(array[3][0].class).to eql(Chef::Node::VividMash)
+ expect(array[3][0]["three"].class).to eql(Chef::Node::AttrArray)
+ end
+ end
+
+ context "#[]=" do
+ it "assigning a Hash into an array converts it to VividMash" do
+ array[0] = { "zero" => "zero2" }
+ expect(array[0].class).to eql(Chef::Node::VividMash)
+ end
+ end
+
+ context "#push" do
+ it "pushing a Hash into an array converts it to VividMash" do
+ array.push({ "three" => "four" })
+ expect(array[3].class).to eql(Chef::Node::VividMash)
+ end
+ end
+
+ context "#unshift" do
+ it "unshifting a Hash into an array converts it to VividMash" do
+ array.unshift({ "zero" => "zero2" })
+ expect(array[0].class).to eql(Chef::Node::VividMash)
+ end
+ end
+
+ context "#insert" do
+ it "inserting a Hash into an array converts it to VividMash" do
+ array.insert(1, { "zero" => "zero2" })
+ expect(array[1].class).to eql(Chef::Node::VividMash)
+ end
+ end
+
+ context "#collect!" do
+ it "converts Hashes" do
+ array.collect! { |x| { "zero" => "zero2" } }
+ expect(array[1].class).to eql(Chef::Node::VividMash)
+ end
+ end
+
+ context "#map!" do
+ it "converts Hashes" do
+ array.map! { |x| { "zero" => "zero2" } }
+ expect(array[1].class).to eql(Chef::Node::VividMash)
+ end
+ end
+
+ context "#compact!" do
+ it "VividMashes remain VividMashes" do
+ array = Chef::Node::AttrArray.new(
+ [ nil, { "one" => "two" }, nil ],
+ root
+ )
+ expect(array[1].class).to eql(Chef::Node::VividMash)
+ array.compact!
+ expect(array[0].class).to eql(Chef::Node::VividMash)
+ end
+ end
+
+ context "#fill" do
+ it "inserts VividMashes for Hashes" do
+ array.fill({ "one" => "two" })
+ expect(array[0].class).to eql(Chef::Node::VividMash)
+ end
+ end
+
+ context "#flatten!" do
+ it "flattens sub-arrays maintaining VividMashes in them" do
+ array = Chef::Node::AttrArray.new(
+ [ [ { "one" => "two" } ], [ { "one" => "two" } ] ],
+ root
+ )
+ expect(array[0][0].class).to eql(Chef::Node::VividMash)
+ array.flatten!
+ expect(array[0].class).to eql(Chef::Node::VividMash)
+ end
+ end
+
+ context "#replace" do
+ it "replaces the array converting hashes to mashes" do
+ array.replace([ { "foo" => "bar" } ])
+ expect(array[0].class).to eql(Chef::Node::VividMash)
+ end
+ end
+end
diff --git a/spec/unit/policy_builder/dynamic_spec.rb b/spec/unit/policy_builder/dynamic_spec.rb
index d94b2a69a2..f014cd9f2e 100644
--- a/spec/unit/policy_builder/dynamic_spec.rb
+++ b/spec/unit/policy_builder/dynamic_spec.rb
@@ -131,18 +131,6 @@ describe Chef::PolicyBuilder::Dynamic do
end
- context "and :use_policyfile is set in Chef::Config" do
-
- before do
- Chef::Config[:use_policyfile] = true
- end
-
- it "uses the Policyfile implementation" do
- expect(implementation).to be_a(Chef::PolicyBuilder::Policyfile)
- end
-
- end
-
context "and policy_name and policy_group are set on Chef::Config" do
before do
diff --git a/spec/unit/provider/apt_repository_spec.rb b/spec/unit/provider/apt_repository_spec.rb
index 1601e9f629..11d505dad8 100644
--- a/spec/unit/provider/apt_repository_spec.rb
+++ b/spec/unit/provider/apt_repository_spec.rb
@@ -162,16 +162,16 @@ C5986B4F1257FFA86632CBA746181433FBB75451
describe "#keyserver_install_cmd" do
it "returns keyserver install command" do
- expect(provider.keyserver_install_cmd("ABC", "gpg.mit.edu")).to eq("apt-key adv --recv --keyserver hkp://gpg.mit.edu:80 ABC")
+ expect(provider.keyserver_install_cmd("ABC", "gpg.mit.edu")).to eq("apt-key adv --no-tty --recv --keyserver hkp://gpg.mit.edu:80 ABC")
end
it "uses proxy if key_proxy property is set" do
new_resource.key_proxy("proxy.mycorp.dmz:3128")
- expect(provider.keyserver_install_cmd("ABC", "gpg.mit.edu")).to eq("apt-key adv --recv --keyserver-options http-proxy=proxy.mycorp.dmz:3128 --keyserver hkp://gpg.mit.edu:80 ABC")
+ expect(provider.keyserver_install_cmd("ABC", "gpg.mit.edu")).to eq("apt-key adv --no-tty --recv --keyserver-options http-proxy=proxy.mycorp.dmz:3128 --keyserver hkp://gpg.mit.edu:80 ABC")
end
it "properly handles keyservers passed with hkp:// URIs" do
- expect(provider.keyserver_install_cmd("ABC", "hkp://gpg.mit.edu")).to eq("apt-key adv --recv --keyserver hkp://gpg.mit.edu ABC")
+ expect(provider.keyserver_install_cmd("ABC", "hkp://gpg.mit.edu")).to eq("apt-key adv --no-tty --recv --keyserver hkp://gpg.mit.edu ABC")
end
end
diff --git a/spec/unit/provider/package/freebsd/pkg_spec.rb b/spec/unit/provider/package/freebsd/pkg_spec.rb
deleted file mode 100644
index 29a8bfef44..0000000000
--- a/spec/unit/provider/package/freebsd/pkg_spec.rb
+++ /dev/null
@@ -1,274 +0,0 @@
-#
-# Authors:: Bryan McLellan (btm@loftninjas.org)
-# Matthew Landauer (matthew@openaustralia.org)
-# Copyright:: Copyright 2009-2016, Bryan McLellan, Matthew Landauer
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "spec_helper"
-require "ostruct"
-
-describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
- before(:each) do
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @new_resource = Chef::Resource::Package.new("zsh")
- @current_resource = Chef::Resource::Package.new("zsh")
-
- @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
- @provider.current_resource = @current_resource
- allow(::File).to receive(:exist?).with("/usr/ports/Makefile").and_return(false)
- allow(::File).to receive(:exist?).with("/usr/ports/www/wordpress").and_return(false)
- allow(::File).to receive(:exist?).with("www/wordpress").and_return(false)
- end
-
- describe "when determining the current package state" do
- before do
- allow(@provider).to receive(:ports_candidate_version).and_return("4.3.6")
- end
-
- it "should create a current resource with the name of the new_resource" do
- current_resource = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context).current_resource
- expect(current_resource.name).to eq("zsh")
- end
-
- it "should return a version if the package is installed" do
- expect(@provider).to receive(:current_installed_version).and_return("4.3.6_7")
- @provider.load_current_resource
- expect(@current_resource.version).to eq("4.3.6_7")
- end
-
- it "should return nil if the package is not installed" do
- expect(@provider).to receive(:current_installed_version).and_return(nil)
- @provider.load_current_resource
- expect(@current_resource.version).to be_nil
- end
-
- it "should return a candidate version if it exists" do
- expect(@provider).to receive(:current_installed_version).and_return(nil)
- @provider.load_current_resource
- expect(@provider.candidate_version).to eql("4.3.6")
- end
- end
-
- describe "when querying for package state and properties" do
- before do
- # @new_resource = Chef::Resource::Package.new("zsh")
-
- # @provider = Chef::Provider::Package::Freebsd::Pkg.new(@node, @new_resource)
-
- # @status = double("Status", :exitstatus => 0)
- # @stdin = double("STDIN", :null_object => true)
- # @stdout = double("STDOUT", :null_object => true)
- # @stderr = double("STDERR", :null_object => true)
- # @pid = double("PID", :null_object => true)
- end
-
- it "should return the version number when it is installed" do
- pkg_info = OpenStruct.new(stdout: "zsh-4.3.6_7")
- expect(@provider).to receive(:shell_out_compacted!).with("pkg_info", "-E", "zsh*", env: nil, returns: [0, 1], timeout: 900).and_return(pkg_info)
- allow(@provider).to receive(:package_name).and_return("zsh")
- expect(@provider.current_installed_version).to eq("4.3.6_7")
- end
-
- it "does not set the current version number when the package is not installed" do
- pkg_info = OpenStruct.new(stdout: "")
- expect(@provider).to receive(:shell_out_compacted!).with("pkg_info", "-E", "zsh*", env: nil, returns: [0, 1], timeout: 900).and_return(pkg_info)
- allow(@provider).to receive(:package_name).and_return("zsh")
- expect(@provider.current_installed_version).to be_nil
- end
-
- it "should return the port path for a valid port name" do
- whereis = OpenStruct.new(stdout: "zsh: /usr/ports/shells/zsh")
- expect(@provider).to receive(:shell_out_compacted!).with("whereis", "-s", "zsh", env: nil, timeout: 900).and_return(whereis)
- allow(@provider).to receive(:port_name).and_return("zsh")
- expect(@provider.port_path).to eq("/usr/ports/shells/zsh")
- end
-
- # Not happy with the form of these tests as they are far too closely tied to the implementation and so very fragile.
- it "should return the ports candidate version when given a valid port path" do
- allow(@provider).to receive(:port_path).and_return("/usr/ports/shells/zsh")
- make_v = OpenStruct.new(stdout: "4.3.6\n", exitstatus: 0)
- expect(@provider).to receive(:shell_out_compacted!).with("make", "-V", "PORTVERSION", { cwd: "/usr/ports/shells/zsh", returns: [0, 1], env: nil, timeout: 900 }).and_return(make_v)
- expect(@provider.ports_candidate_version).to eq("4.3.6")
- end
-
- it "should figure out the package name when we have ports" do
- allow(::File).to receive(:exist?).with("/usr/ports/Makefile").and_return(true)
- allow(@provider).to receive(:port_path).and_return("/usr/ports/shells/zsh")
- make_v = OpenStruct.new(stdout: "zsh-4.3.6_7\n", exitstatus: 0)
- expect(@provider).to receive(:shell_out_compacted!).with("make", "-V", "PKGNAME", { cwd: "/usr/ports/shells/zsh", env: nil, returns: [0, 1], timeout: 900 }).and_return(make_v)
- # @provider.should_receive(:ports_makefile_variable_value).with("PKGNAME").and_return("zsh-4.3.6_7")
- expect(@provider.package_name).to eq("zsh")
- end
- end
-
- describe Chef::Provider::Package::Freebsd::Pkg, "install_package" do
- before(:each) do
- @cmd_result = OpenStruct.new(status: true)
-
- @provider.current_resource = @current_resource
- allow(@provider).to receive(:package_name).and_return("zsh")
- allow(@provider).to receive(:latest_link_name).and_return("zsh")
- allow(@provider).to receive(:port_path).and_return("/usr/ports/shells/zsh")
- end
-
- it "should run pkg_add -r with the package name" do
- expect(@provider).to receive(:shell_out_compacted!).with("pkg_add", "-r", "zsh", env: nil, timeout: 900).and_return(@cmd_result)
- @provider.install_package("zsh", "4.3.6_7")
- end
- end
-
- describe Chef::Provider::Package::Freebsd::Pkg, "port path" do
- before do
- # @node = Chef::Node.new
- @new_resource = Chef::Resource::Package.new("zsh")
- @new_resource.cookbook_name = "adventureclub"
- @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
- end
-
- it "should figure out the port path from the package_name using whereis" do
- whereis = OpenStruct.new(stdout: "zsh: /usr/ports/shells/zsh")
- expect(@provider).to receive(:shell_out_compacted!).with("whereis", "-s", "zsh", env: nil, timeout: 900).and_return(whereis)
- expect(@provider.port_path).to eq("/usr/ports/shells/zsh")
- end
-
- it "should use the package_name as the port path when it starts with /" do
- new_resource = Chef::Resource::Package.new("/usr/ports/www/wordpress")
- provider = Chef::Provider::Package::Freebsd::Pkg.new(new_resource, @run_context)
- expect(provider).not_to receive(:popen4)
- expect(provider.port_path).to eq("/usr/ports/www/wordpress")
- end
-
- it "should use the package_name as a relative path from /usr/ports when it contains / but doesn't start with it" do
- # @new_resource = double( "Chef::Resource::Package",
- # :package_name => "www/wordpress",
- # :cookbook_name => "xenoparadox")
- new_resource = Chef::Resource::Package.new("www/wordpress")
- provider = Chef::Provider::Package::Freebsd::Pkg.new(new_resource, @run_context)
- expect(provider).not_to receive(:popen4)
- expect(provider.port_path).to eq("/usr/ports/www/wordpress")
- end
- end
-
- describe Chef::Provider::Package::Freebsd::Pkg, "ruby-iconv (package with a dash in the name)" do
- before(:each) do
- @new_resource = Chef::Resource::Package.new("ruby-iconv")
- @current_resource = Chef::Resource::Package.new("ruby-iconv")
- @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
- @provider.current_resource = @current_resource
- allow(@provider).to receive(:port_path).and_return("/usr/ports/converters/ruby-iconv")
- allow(@provider).to receive(:package_name).and_return("ruby18-iconv")
- allow(@provider).to receive(:latest_link_name).and_return("ruby18-iconv")
-
- @install_result = OpenStruct.new(status: true)
- end
-
- it "should run pkg_add -r with the package name" do
- expect(@provider).to receive(:shell_out_compacted!).with("pkg_add", "-r", "ruby18-iconv", env: nil, timeout: 900).and_return(@install_result)
- @provider.install_package("ruby-iconv", "1.0")
- end
- end
-
- describe Chef::Provider::Package::Freebsd::Pkg, "remove_package" do
- before(:each) do
- @pkg_delete = OpenStruct.new(status: true)
- @new_resource.version "4.3.6_7"
- @current_resource.version "4.3.6_7"
- @provider.current_resource = @current_resource
- allow(@provider).to receive(:package_name).and_return("zsh")
- end
-
- it "should run pkg_delete with the package name and version" do
- expect(@provider).to receive(:shell_out_compacted!).with("pkg_delete", "zsh-4.3.6_7", env: nil, timeout: 900).and_return(@pkg_delete)
- @provider.remove_package("zsh", "4.3.6_7")
- end
- end
-
- # CHEF-4371
- # There are some port names that contain special characters such as +'s. This breaks the regular expression used to determine what
- # version of a package is currently installed and to get the port_path.
- # Example package name: bonnie++
-
- describe Chef::Provider::Package::Freebsd::Pkg, "bonnie++ (package with a plus in the name :: CHEF-4371)" do
- before(:each) do
- @new_resource = Chef::Resource::Package.new("bonnie++")
- @current_resource = Chef::Resource::Package.new("bonnie++")
- @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
- @provider.current_resource = @current_resource
- end
-
- it "should return the port path for a valid port name" do
- whereis = OpenStruct.new(stdout: "bonnie++: /usr/ports/benchmarks/bonnie++")
- expect(@provider).to receive(:shell_out_compacted!).with("whereis", "-s", "bonnie++", env: nil, timeout: 900).and_return(whereis)
- allow(@provider).to receive(:port_name).and_return("bonnie++")
- expect(@provider.port_path).to eq("/usr/ports/benchmarks/bonnie++")
- end
-
- it "should return the version number when it is installed" do
- pkg_info = OpenStruct.new(stdout: "bonnie++-1.96")
- expect(@provider).to receive(:shell_out_compacted!).with("pkg_info", "-E", "bonnie++*", env: nil, returns: [0, 1], timeout: 900).and_return(pkg_info)
- allow(@provider).to receive(:package_name).and_return("bonnie++")
- expect(@provider.current_installed_version).to eq("1.96")
- end
- end
-
- # A couple of examples to show up the difficulty of determining the command to install the binary package given the port:
- # PORT DIRECTORY INSTALLED PACKAGE NAME COMMAND TO INSTALL PACKAGE
- # /usr/ports/lang/perl5.8 perl-5.8.8_1 pkg_add -r perl
- # /usr/ports/databases/mysql50-server mysql-server-5.0.45_1 pkg_add -r mysql50-server
- #
- # So, in one case it appears the command to install the package can be derived from the name of the port directory and in the
- # other case it appears the command can be derived from the package name. Very confusing!
- # Well, luckily, after much poking around, I discovered that the two can be disambiguated through the use of the LATEST_LINK
- # variable which is set by the ports Makefile
- #
- # PORT DIRECTORY LATEST_LINK INSTALLED PACKAGE NAME COMMAND TO INSTALL PACKAGE
- # /usr/ports/lang/perl5.8 perl perl-5.8.8_1 pkg_add -r perl
- # /usr/ports/databases/mysql50-server mysql50-server mysql-server-5.0.45_1 pkg_add -r mysql50-server
- #
- # The variable LATEST_LINK is named that way because the directory that "pkg_add -r" downloads from is called "Latest" and
- # contains the "latest" versions of package as symbolic links to the files in the "All" directory.
-
- describe Chef::Provider::Package::Freebsd::Pkg, "install_package latest link fixes" do
- it "should install the perl binary package with the correct name" do
- @new_resource = Chef::Resource::Package.new("perl5.8")
- @current_resource = Chef::Resource::Package.new("perl5.8")
- @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
- @provider.current_resource = @current_resource
- allow(@provider).to receive(:package_name).and_return("perl")
- allow(@provider).to receive(:latest_link_name).and_return("perl")
-
- cmd = OpenStruct.new(status: true)
- expect(@provider).to receive(:shell_out_compacted!).with("pkg_add", "-r", "perl", env: nil, timeout: 900).and_return(cmd)
- @provider.install_package("perl5.8", "5.8.8_1")
- end
-
- it "should install the mysql50-server binary package with the correct name" do
-
- @new_resource = Chef::Resource::Package.new("mysql50-server")
- @current_resource = Chef::Resource::Package.new("mysql50-server")
- @provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
- @provider.current_resource = @current_resource
- allow(@provider).to receive(:package_name).and_return("mysql-server")
- allow(@provider).to receive(:latest_link_name).and_return("mysql50-server")
-
- cmd = OpenStruct.new(status: true)
- expect(@provider).to receive(:shell_out_compacted!).with("pkg_add", "-r", "mysql50-server", env: nil, timeout: 900).and_return(cmd)
- @provider.install_package("mysql50-server", "5.0.45_1")
- end
- end
-end
diff --git a/spec/unit/provider/package/freebsd/pkgng_spec.rb b/spec/unit/provider/package/freebsd/pkgng_spec.rb
index 13e5dd17fd..bc78a178eb 100644
--- a/spec/unit/provider/package/freebsd/pkgng_spec.rb
+++ b/spec/unit/provider/package/freebsd/pkgng_spec.rb
@@ -62,7 +62,6 @@ describe Chef::Provider::Package::Freebsd::Port do
describe "determining current installed version" do
before(:each) do
- allow(@provider).to receive(:supports_pkgng?)
@pkg_info = OpenStruct.new(stdout: "zsh-3.1.7\nVersion : 3.1.7\n")
end
diff --git a/spec/unit/provider/package/freebsd/port_spec.rb b/spec/unit/provider/package/freebsd/port_spec.rb
index af5216dc04..069c4e8dec 100644
--- a/spec/unit/provider/package/freebsd/port_spec.rb
+++ b/spec/unit/provider/package/freebsd/port_spec.rb
@@ -65,23 +65,11 @@ describe Chef::Provider::Package::Freebsd::Port do
@pkg_info = OpenStruct.new(stdout: "zsh-3.1.7\n")
end
- it "should check 'pkg_info' if system uses pkg_* tools" do
- allow(@new_resource).to receive(:supports_pkgng?)
- expect(@new_resource).to receive(:supports_pkgng?).and_return(false)
- expect(@provider).to receive(:shell_out_compacted!).with("pkg_info", "-E", "zsh*", env: nil, returns: [0, 1], timeout: 900).and_return(@pkg_info)
+ it "should check 'pkg info' to determine the current version" do
+ expect(@provider).to receive(:shell_out_compacted!).with("pkg", "info", "zsh", env: nil, returns: [0, 70], timeout: 900).and_return(@pkg_info)
expect(@provider.current_installed_version).to eq("3.1.7")
end
- it "should check 'pkg info' if make supports WITH_PKGNG if freebsd version is < 1000017" do
- pkg_enabled = OpenStruct.new(stdout: "yes\n")
- [1000016, 1000000, 901503, 902506, 802511].each do |freebsd_version|
- @node.automatic_attrs[:os_version] = freebsd_version
- expect(@new_resource).to receive(:shell_out_compacted!).with("make", "-V", "WITH_PKGNG", env: nil).and_return(pkg_enabled)
- expect(@provider).to receive(:shell_out_compacted!).with("pkg", "info", "zsh", env: nil, returns: [0, 70], timeout: 900).and_return(@pkg_info)
- expect(@provider.current_installed_version).to eq("3.1.7")
- end
- end
-
it "should check 'pkg info' if the freebsd version is greater than or equal to 1000017" do
freebsd_version = 1000017
@node.automatic_attrs[:os_version] = freebsd_version
diff --git a/spec/unit/provider/package/rpm_spec.rb b/spec/unit/provider/package/rpm_spec.rb
index 284e201e92..1c4f9d31ee 100644
--- a/spec/unit/provider/package/rpm_spec.rb
+++ b/spec/unit/provider/package/rpm_spec.rb
@@ -162,17 +162,16 @@ describe Chef::Provider::Package::Rpm do
let(:rpm_q_stdout) { "imagemagick-c++ 0.5.4.7-7.el6_5" }
it "runs rpm -u with the package source to upgrade" do
- expect(provider).to receive(:shell_out_compacted!).with("rpm", "-U", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to receive(:shell_out_compacted!).with("rpm", "-U", "--oldpackage", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.action_install
end
end
context "when an older version is desired" do
let(:new_resource) do
- Chef::Resource::RpmPackage.new(package_name).tap do |r|
- r.source(package_source)
- r.allow_downgrade(true)
- end
+ r = Chef::Resource::RpmPackage.new(package_name)
+ r.source(package_source)
+ r
end
let(:rpm_q_stdout) { "imagemagick-c++ 21.4-19.el6_5" }
@@ -182,6 +181,12 @@ describe Chef::Provider::Package::Rpm do
provider.action_install
end
+ it "if downgrades are not allowed it should not downgrade" do
+ new_resource.allow_downgrade(false)
+ expect(provider).not_to receive(:shell_out_compacted!)
+ provider.action_install
+ end
+
end
end
@@ -203,7 +208,7 @@ describe Chef::Provider::Package::Rpm do
let(:rpm_q_stdout) { "imagemagick-c++ 0.5.4.7-7.el6_5" }
it "runs rpm -u with the package source to upgrade" do
- expect(provider).to receive(:shell_out_compacted!).with("rpm", "-U", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to receive(:shell_out_compacted!).with("rpm", "-U", "--oldpackage", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.action_upgrade
end
end
@@ -223,6 +228,12 @@ describe Chef::Provider::Package::Rpm do
provider.action_upgrade
end
+ it "should run rpm -u --oldpackage with the package source to downgrade" do
+ new_resource.allow_downgrade(false)
+ expect(provider).not_to receive(:shell_out_compacted!).with("rpm", "-U", any_args)
+ provider.action_upgrade
+ end
+
end
end
@@ -421,7 +432,7 @@ describe Chef::Provider::Package::Rpm do
expect(new_resource.source).to eq("/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm")
current_resource.version("21.4-19.el5")
provider.current_resource = current_resource
- expect(provider).to receive(:shell_out_compacted!).with("rpm", "-U", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to receive(:shell_out_compacted!).with("rpm", "-U", "--oldpackage", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.upgrade_package("/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", "6.5.4.7-7.el6_5")
end
end
diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb
index 50f2bb0b5f..c17eeba1bb 100644
--- a/spec/unit/provider/package/zypper_spec.rb
+++ b/spec/unit/provider/package/zypper_spec.rb
@@ -120,14 +120,14 @@ describe Chef::Provider::Package::Zypper do
describe "install_package" do
it "should run zypper install with the package name and version" do
shell_out_expectation!(
- "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
it "should run zypper install with gpg checks" do
shell_out_expectation!(
- "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -135,7 +135,7 @@ describe Chef::Provider::Package::Zypper do
it "setting the property should disable gpg checks" do
new_resource.gpg_check false
shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -143,15 +143,15 @@ describe Chef::Provider::Package::Zypper do
it "setting the config variable should disable gpg checks" do
Chef::Config[:zypper_check_gpg] = false
shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
- it "setting the property should allow downgrade" do
- new_resource.allow_downgrade true
+ it "setting the property should disallow downgrade" do
+ new_resource.allow_downgrade false
shell_out_expectation!(
- "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -159,7 +159,7 @@ describe Chef::Provider::Package::Zypper do
it "should add user provided options to the command" do
new_resource.options "--user-provided"
shell_out_expectation!(
- "zypper", "--non-interactive", "install", "--user-provided", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "install", "--user-provided", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -167,7 +167,7 @@ describe Chef::Provider::Package::Zypper do
it "should add user provided global options" do
new_resource.global_options "--user-provided"
shell_out_expectation!(
- "zypper", "--user-provided", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--user-provided", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -175,7 +175,7 @@ describe Chef::Provider::Package::Zypper do
it "should add multiple user provided global options" do
new_resource.global_options "--user-provided1 --user-provided2"
shell_out_expectation!(
- "zypper", "--user-provided1", "--user-provided2", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--user-provided1", "--user-provided2", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -184,35 +184,35 @@ describe Chef::Provider::Package::Zypper do
describe "upgrade_package" do
it "should run zypper update with the package name and version" do
shell_out_expectation!(
- "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
it "should run zypper update without gpg checks when setting the property" do
new_resource.gpg_check false
shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
it "should run zypper update without gpg checks when setting the config variable" do
Chef::Config[:zypper_check_gpg] = false
shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
it "should add user provided options to the command" do
new_resource.options "--user-provided"
shell_out_expectation!(
- "zypper", "--non-interactive", "install", "--user-provided", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "install", "--user-provided", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
it "should add user provided global options" do
new_resource.global_options "--user-provided"
shell_out_expectation!(
- "zypper", "--user-provided", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--user-provided", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
@@ -435,7 +435,7 @@ describe Chef::Provider::Package::Zypper do
describe "install_package" do
it "should run zypper install with the package name and version" do
shell_out_expectation!(
- "zypper", "install", "--auto-agree-with-licenses", "-y", "emacs"
+ "zypper", "install", "--auto-agree-with-licenses", "--oldpackage", "-y", "emacs"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -444,7 +444,7 @@ describe Chef::Provider::Package::Zypper do
describe "upgrade_package" do
it "should run zypper update with the package name and version" do
shell_out_expectation!(
- "zypper", "install", "--auto-agree-with-licenses", "-y", "emacs"
+ "zypper", "install", "--auto-agree-with-licenses", "--oldpackage", "-y", "emacs"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
@@ -463,7 +463,7 @@ describe Chef::Provider::Package::Zypper do
describe "when installing multiple packages" do # https://github.com/chef/chef/issues/3570
it "should install an array of package names and versions" do
shell_out_expectation!(
- "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0", "vim=2.0"
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0", "vim=2.0"
)
provider.install_package(%w{emacs vim}, ["1.0", "2.0"])
end
diff --git a/spec/unit/resource/chef_gem_spec.rb b/spec/unit/resource/chef_gem_spec.rb
index d4c94b0ac7..a8429d0812 100644
--- a/spec/unit/resource/chef_gem_spec.rb
+++ b/spec/unit/resource/chef_gem_spec.rb
@@ -73,10 +73,7 @@ describe Chef::Resource::ChefGem, "gem_binary" do
Chef::Recipe.new("hjk", "test", run_context)
end
- let(:chef_gem_compile_time) { nil }
-
let(:resource) do
- Chef::Config[:chef_gem_compile_time] = chef_gem_compile_time
Chef::Resource::ChefGem.new("foo", run_context)
end
diff --git a/spec/unit/resource/freebsd_package_spec.rb b/spec/unit/resource/freebsd_package_spec.rb
index 154bd09616..3df1a9c139 100644
--- a/spec/unit/resource/freebsd_package_spec.rb
+++ b/spec/unit/resource/freebsd_package_spec.rb
@@ -67,37 +67,11 @@ describe Chef::Resource::FreebsdPackage do
end
end
- describe "if freebsd_version is greater than or equal to 1000017" do
+ describe "if ports is not specified" do
it "is Freebsd::Pkgng" do
- [1000017, 1000018, 1000500, 1001001, 1100000].each do |freebsd_version|
- node.automatic_attrs[:os_version] = freebsd_version
- resource.after_created
- expect(resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkgng)
- end
- end
- end
-
- describe "if pkgng enabled" do
- it "is Freebsd::Pkgng" do
- pkg_enabled = OpenStruct.new(stdout: "yes\n")
- allow(resource).to receive(:shell_out!).with("make", "-V", "WITH_PKGNG", env: nil).and_return(pkg_enabled)
resource.after_created
expect(resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkgng)
end
end
-
- describe "if freebsd_version is less than 1000017 and pkgng not enabled" do
- it "is Freebsd::Pkg" do
- pkg_enabled = OpenStruct.new(stdout: "\n")
- allow(resource).to receive(:shell_out!).with("make", "-V", "WITH_PKGNG", env: nil).and_return(pkg_enabled)
-
- [1000016, 1000000, 901503, 902506, 802511].each do |freebsd_version|
- node.automatic_attrs[:os_version] = freebsd_version
- expect(Chef).to receive(:deprecated).with(:freebsd_package_provider, kind_of(String))
- resource.after_created
- expect(resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkg)
- end
- end
- end
end
end
diff --git a/spec/unit/knife/osc_user_list_spec.rb b/spec/unit/resource/macosx_service.rb
index 10682eb96f..aebe5e0dd3 100644
--- a/spec/unit/knife/osc_user_list_spec.rb
+++ b/spec/unit/resource/macosx_service.rb
@@ -1,6 +1,6 @@
#
-# Author:: Steven Danna
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
+# Author:: Tim Smith (tsmith@chef.io>)
+# Copyright:: Copyright 2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,20 +18,20 @@
require "spec_helper"
-# DEPRECATION NOTE
-# This code only remains to support users still operating with
-# Open Source Chef Server 11 and should be removed once support
-# for OSC 11 ends. New development should occur in user_list_spec.rb.
+describe Chef::Resource::MacosxService do
+ let(:resource) { Chef::Resource::MacosxService.new("chef") }
-describe Chef::Knife::OscUserList do
- before(:each) do
- Chef::Knife::OscUserList.load_deps
- @knife = Chef::Knife::OscUserList.new
+ it "sets the resource_name to :macosx_service" do
+ expect(resource.resource_name).to eql(:macosx_service)
end
- it "lists the users" do
- expect(Chef::User).to receive(:list)
- expect(@knife).to receive(:format_list_for_display)
- @knife.run
+ it "accepts a String for the session_type property" do
+ resource.session_type "foo"
+ expect(resource.session_type).to eql("foo")
+ end
+
+ it "accepts a String for the plist property" do
+ resource.plist "foo"
+ expect(resource.plist).to eql("foo")
end
end
diff --git a/spec/unit/resource/ohai_spec.rb b/spec/unit/resource/ohai_spec.rb
index a18929da15..d0a8f7a77e 100644
--- a/spec/unit/resource/ohai_spec.rb
+++ b/spec/unit/resource/ohai_spec.rb
@@ -26,10 +26,6 @@ describe Chef::Resource::Ohai do
expect(resource.resource_name).to eql(:ohai)
end
- it "the ohai_name property is the name_property" do
- expect(resource.ohai_name).to eql("fakey_fakerton")
- end
-
it "sets the default action as :reload" do
expect(resource.action).to eql([:reload])
end
diff --git a/spec/unit/resource/remote_directory_spec.rb b/spec/unit/resource/remote_directory_spec.rb
index f010ebdf96..9eab495f77 100644
--- a/spec/unit/resource/remote_directory_spec.rb
+++ b/spec/unit/resource/remote_directory_spec.rb
@@ -36,51 +36,64 @@ describe Chef::Resource::RemoteDirectory do
expect { resource.action :delete }.not_to raise_error
end
- it "accepts a string for the remote directory source" do
+ it "accepts a String for the cookbook property" do
+ resource.cookbook "foo"
+ expect(resource.cookbook).to eql("foo")
+ end
+
+ it "accepts a String for the source property" do
resource.source "foo"
expect(resource.source).to eql("foo")
end
- it "has the basename of the remote directory resource as the default source" do
+ it "uses the basename of the pat property as the default value of the source property" do
resource.path "/foo/bar"
expect(resource.source).to eql("bar")
end
- it "accepts a number for the remote files backup" do
+ it "files_backup property defaults to 5" do
+ expect(resource.files_backup).to eql(5)
+ end
+
+ it "accepts an Integer for the files_backup property" do
resource.files_backup 1
expect(resource.files_backup).to eql(1)
end
- it "accepts false for the remote files backup" do
+ it "accepts false for the files_backup property" do
resource.files_backup false
expect(resource.files_backup).to eql(false)
end
- it "accepts 3 or 4 digits for the files_mode" do
+ it "accepts 3 or 4 digits for the files_mode property" do
resource.files_mode 100
expect(resource.files_mode).to eql(100)
resource.files_mode 1000
expect(resource.files_mode).to eql(1000)
end
- it "accepts a string or number for the files group" do
+ it "accepts a String or number for the files_group property" do
resource.files_group "heart"
expect(resource.files_group).to eql("heart")
resource.files_group 1000
expect(resource.files_group).to eql(1000)
end
- it "accepts a string or number for the files owner" do
+ it "accepts a String or number for the files_owner property" do
resource.files_owner "heart"
expect(resource.files_owner).to eql("heart")
resource.files_owner 1000
expect(resource.files_owner).to eql(1000)
end
- it "overwrites by default" do
+ it "overwrite property has the default value of true" do
expect(resource.overwrite).to be true
end
+ it "recursive property has the default value of true" do
+ expect(resource.recursive).to be true
+ end
+
describe "when it has cookbook, files owner, files mode, and source" do
before do
resource.path("/var/path/")
@@ -98,7 +111,7 @@ describe Chef::Resource::RemoteDirectory do
expect(state[:files_mode]).to eq("0664")
end
- it "returns the path as its identity" do
+ it "returns the path as its identity" do
expect(resource.identity).to eq("/var/path/")
end
end
diff --git a/spec/unit/resource/route_spec.rb b/spec/unit/resource/route_spec.rb
index d4248755b5..dd79d04024 100644
--- a/spec/unit/resource/route_spec.rb
+++ b/spec/unit/resource/route_spec.rb
@@ -56,8 +56,13 @@ describe Chef::Resource::Route do
expect(resource.device).to eql("eth0")
end
- it "allows you to specify the route type" do
- resource.route_type "host"
+ it "allows you to specify the route type as a symbol" do
+ resource.route_type :host
+ expect(resource.route_type).to eql(:host)
+ end
+
+ it "allows you to specify the route type as a string" do
+ resource.route_type :host
expect(resource.route_type).to eql(:host)
end
diff --git a/spec/unit/resource/service_spec.rb b/spec/unit/resource/service_spec.rb
index 963c2b2d89..7c2b46a0dc 100644
--- a/spec/unit/resource/service_spec.rb
+++ b/spec/unit/resource/service_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: AJ Christensen (<aj@hjksolutions.com>)
# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,7 +26,7 @@ describe Chef::Resource::Service do
expect(resource.provider).to eq(nil)
end
- it "sets the service_name to the first argument to new" do
+ it "sets the service_name property as the name_property" do
expect(resource.service_name).to eql("chef")
end
@@ -45,16 +45,17 @@ describe Chef::Resource::Service do
expect { resource.action :unmask }.not_to raise_error
end
- it "sets the pattern to be the service name by default" do
- expect(resource.pattern).to eql("chef")
+ it "Uses the service_name property as the default for the pattern property" do
+ resource.service_name "something"
+ expect(resource.pattern).to eql("something")
end
- it "accepts a string for the service name" do
+ it "accepts a String for the service name property" do
resource.service_name "something"
expect(resource.service_name).to eql("something")
end
- it "accepts a string for the service pattern" do
+ it "accepts a String for the service pattern" do
resource.pattern ".*"
expect(resource.pattern).to eql(".*")
end
@@ -65,127 +66,119 @@ describe Chef::Resource::Service do
end.to raise_error(ArgumentError)
end
- it "accepts a string for the service start command" do
- resource.start_command "/etc/init.d/chef start"
- expect(resource.start_command).to eql("/etc/init.d/chef start")
- end
-
- it "does not accept a regexp for the service start command" do
- expect do
- resource.start_command /.*/
- end.to raise_error(ArgumentError)
- end
-
- it "accepts a string for the service stop command" do
- resource.stop_command "/etc/init.d/chef stop"
- expect(resource.stop_command).to eql("/etc/init.d/chef stop")
- end
-
- it "does not accept a regexp for the service stop command" do
- expect do
- resource.stop_command /.*/
- end.to raise_error(ArgumentError)
- end
-
- it "accepts a string for the service status command" do
- resource.status_command "/etc/init.d/chef status"
- expect(resource.status_command).to eql("/etc/init.d/chef status")
- end
-
- it "does not accept a regexp for the service status command" do
- expect do
- resource.status_command /.*/
- end.to raise_error(ArgumentError)
- end
-
- it "accepts a string for the service restart command" do
- resource.restart_command "/etc/init.d/chef restart"
- expect(resource.restart_command).to eql("/etc/init.d/chef restart")
+ it "accepts a String for the user property" do
+ resource.user "fakey_fakerton"
+ expect(resource.user).to eql("fakey_fakerton")
end
- it "does not accept a regexp for the service restart command" do
- expect do
- resource.restart_command /.*/
- end.to raise_error(ArgumentError)
+ it "accepts an Array for the run_levels property" do
+ resource.run_levels ["foo"]
+ expect(resource.run_levels).to eql(["foo"])
end
- it "accepts a string for the service reload command" do
- resource.reload_command "/etc/init.d/chef reload"
- expect(resource.reload_command).to eql("/etc/init.d/chef reload")
- end
-
- it "does not accept a regexp for the service reload command" do
- expect do
- resource.reload_command /.*/
- end.to raise_error(ArgumentError)
+ it "accepts a Hash for the parameters property" do
+ param_hash = { something: nil }
+ resource.parameters param_hash
+ expect(resource.parameters).to eql(param_hash)
end
- it "accepts a string for the service init command" do
+ it "accepts a String for the init_command property" do
resource.init_command "/etc/init.d/chef"
expect(resource.init_command).to eql("/etc/init.d/chef")
end
- it "does not accept a regexp for the service init command" do
+ it "does not accept a regexp for the init_command property" do
expect do
resource.init_command /.*/
end.to raise_error(ArgumentError)
end
- it "accepts an array for options" do
+ it "accepts an array for options property" do
resource.options ["-r", "-s"]
expect(resource.options).to eql(["-r", "-s"])
end
- it "accepts a string for options" do
+ it "accepts a String for options property" do
resource.options "-r"
expect(resource.options).to eql(["-r"])
end
- it "accepts a string with multiple flags for options" do
+ it "accepts a String with multiple flags for options property" do
resource.options "-r -s"
expect(resource.options).to eql(["-r", "-s"])
end
- it "does not accept a boolean for options" do
+ it "does not accept a boolean for options property" do
expect do
resource.options true
end.to raise_error(ArgumentError)
end
- %w{enabled running}.each do |attrib|
- it "accepts true for #{attrib}" do
- resource.send(attrib, true)
- expect(resource.send(attrib)).to eql(true)
+ %w{restart_command start_command stop_command status_command reload_command}.each do |prop|
+ it "accepts a String for the #{prop} property" do
+ resource.send(prop, "service foo bar")
+ expect(resource.send(prop)).to eql("service foo bar")
end
- it "accepts false for #{attrib}" do
- resource.send(attrib, false)
- expect(resource.send(attrib)).to eql(false)
+ it "accepts false for #{prop} property" do
+ resource.send(prop, false)
+ expect(resource.send(prop)).to eql(false)
end
- it "does not accept a string for #{attrib}" do
- expect { resource.send(attrib, "poop") }.to raise_error(ArgumentError)
+ it "does not accept a regexp for the #{prop} property" do
+ expect { resource.send(prop, /.*/) }.to raise_error(ArgumentError)
end
+ end
- it "defaults all the feature support to nil" do
- support_hash = { status: nil, restart: nil, reload: nil }
- expect(resource.supports).to eq(support_hash)
+ it "accepts a String for priority property" do
+ resource.priority "1"
+ expect(resource.priority).to eql("1")
+ end
+
+ it "accepts an Integer for priority property" do
+ resource.priority 1
+ expect(resource.priority).to eql(1)
+ end
+
+ it "accepts an Integer for timeout property" do
+ resource.timeout 1
+ expect(resource.timeout).to eql(1)
+ end
+
+ %w{enabled running}.each do |prop|
+ it "accepts true for #{prop} property" do
+ resource.send(prop, true)
+ expect(resource.send(prop)).to eql(true)
end
- it "allows you to set what features this resource supports as a array" do
- support_array = [ :status, :restart ]
- support_hash = { status: true, restart: true }
- resource.supports(support_array)
- expect(resource.supports).to eq(support_hash)
+ it "accepts false for #{prop} property" do
+ resource.send(prop, false)
+ expect(resource.send(prop)).to eql(false)
end
- it "allows you to set what features this resource supports as a hash" do
- support_hash = { status: true, restart: true }
- resource.supports(support_hash)
- expect(resource.supports).to eq(support_hash)
+ it "does not accept a String for #{prop} property" do
+ expect { resource.send(prop, "poop") }.to raise_error(ArgumentError)
end
end
+ it "defaults all the feature support to nil" do
+ support_hash = { status: nil, restart: nil, reload: nil }
+ expect(resource.supports).to eq(support_hash)
+ end
+
+ it "allows you to set what features this resource supports as an array" do
+ support_array = [ :status, :restart ]
+ support_hash = { status: true, restart: true }
+ resource.supports(support_array)
+ expect(resource.supports).to eq(support_hash)
+ end
+
+ it "allows you to set what features this resource supports as a hash" do
+ support_hash = { status: true, restart: true }
+ resource.supports(support_hash)
+ expect(resource.supports).to eq(support_hash)
+ end
+
describe "when it has pattern and supports" do
before do
resource.service_name("superfriend")
@@ -199,7 +192,7 @@ describe Chef::Resource::Service do
expect(state[:running]).to eql(false)
end
- it "returns the service name as its identity" do
+ it "returns the service_name property as its identity" do
expect(resource.identity).to eq("superfriend")
end
end
diff --git a/spec/unit/resource/windows_certificate.rb b/spec/unit/resource/windows_certificate.rb
new file mode 100644
index 0000000000..97e404a2d5
--- /dev/null
+++ b/spec/unit/resource/windows_certificate.rb
@@ -0,0 +1,76 @@
+#
+# 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::WindowsCertificate do
+ let(:resource) { Chef::Resource::WindowsCertificate.new("foobar") }
+
+ it "sets resource name as :windows_certificate" do
+ expect(resource.resource_name).to eql(:windows_certificate)
+ end
+
+ it "the source property is the name_property" do
+ expect(resource.source).to eql("foobar")
+ end
+
+ it "the store_name property defaults to 'MY'" do
+ expect(resource.store_name).to eql("MY")
+ end
+
+ it 'the store_name property accepts "TRUSTEDPUBLISHER", "TrustedPublisher", "CLIENTAUTHISSUER", "REMOTE DESKTOP", "ROOT", "TRUSTEDDEVICES", "WEBHOSTING", "CA", "AUTHROOT", "TRUSTEDPEOPLE", "MY", "SMARTCARDROOT", "TRUST", or "DISALLOWED"' do
+ expect { resource.store_name("TRUSTEDPUBLISHER") }.not_to raise_error
+ expect { resource.store_name("TrustedPublisher") }.not_to raise_error
+ expect { resource.store_name("CLIENTAUTHISSUER") }.not_to raise_error
+ expect { resource.store_name("REMOTE DESKTOP") }.not_to raise_error
+ expect { resource.store_name("ROOT") }.not_to raise_error
+ expect { resource.store_name("TRUSTEDDEVICES") }.not_to raise_error
+ expect { resource.store_name("WEBHOSTING") }.not_to raise_error
+ expect { resource.store_name("CA") }.not_to raise_error
+ expect { resource.store_name("AUTHROOT") }.not_to raise_error
+ expect { resource.store_name("TRUSTEDPEOPLE") }.not_to raise_error
+ expect { resource.store_name("MY") }.not_to raise_error
+ expect { resource.store_name("SMARTCARDROOT") }.not_to raise_error
+ expect { resource.store_name("TRUST") }.not_to raise_error
+ expect { resource.store_name("DISALLOWED") }.not_to raise_error
+ end
+
+ it "the resource is marked sensitive if pfx_password is specified" do
+ resource.pfx_password("1234")
+ expect(resource.sensitive).to be true
+ end
+
+ it "the user_store property defaults to false" do
+ expect(resource.user_store).to be false
+ end
+
+ it "sets the default action as :create" do
+ expect(resource.action).to eql([:create])
+ end
+
+ it "supports :create, :acl_add, :delete, and :verify actions" do
+ expect { resource.action :create }.not_to raise_error
+ expect { resource.action :acl_add }.not_to raise_error
+ expect { resource.action :delete }.not_to raise_error
+ expect { resource.action :verify }.not_to raise_error
+ end
+
+ it "sets sensitive to true if the pfx_password property is set" do
+ resource.pfx_password "foo"
+ expect(resource.sensitive).to be_truthy
+ end
+end
diff --git a/spec/unit/resource/windows_feature.rb b/spec/unit/resource/windows_feature.rb
index f01bc3b864..eec895fad9 100644
--- a/spec/unit/resource/windows_feature.rb
+++ b/spec/unit/resource/windows_feature.rb
@@ -50,6 +50,10 @@ describe Chef::Resource::WindowsFeature do
expect(resource.timeout).to eql(600)
end
+ it "install_method property defaults to :windows_feature_dism" do
+ expect(resource.install_method).to eql(:windows_feature_dism)
+ end
+
it "install_method accepts :windows_feature_dism, :windows_feature_powershell, and :windows_feature_servermanagercmd" do
expect { resource.install_method :windows_feature_dism }.not_to raise_error
expect { resource.install_method :windows_feature_powershell }.not_to raise_error
diff --git a/spec/unit/resource/windows_firewall_rule_spec.rb b/spec/unit/resource/windows_firewall_rule_spec.rb
new file mode 100644
index 0000000000..629e91d74f
--- /dev/null
+++ b/spec/unit/resource/windows_firewall_rule_spec.rb
@@ -0,0 +1,401 @@
+# Author:: Tor Magnus Rakvåg (tor.magnus@outlook.com)
+# Copyright:: 2018, Intility AS
+# 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::WindowsFirewallRule do
+ let(:resource) { Chef::Resource::WindowsFirewallRule.new("rule") }
+ let(:provider) { resource.provider_for_action(:enable) }
+
+ it "has a resource name of :windows_firewall_rule" do
+ expect(resource.resource_name).to eql(:windows_firewall_rule)
+ end
+
+ it "the name_property is 'rule_name'" do
+ expect(resource.rule_name).to eql("rule")
+ end
+
+ it "the default action is :create" do
+ expect(resource.action).to eql([:create])
+ end
+
+ it "supports :create and :delete actions" do
+ expect { resource.action :create }.not_to raise_error
+ expect { resource.action :delete }.not_to raise_error
+ end
+
+ it "the rule_name property accepts strings" do
+ resource.rule_name("rule2")
+ expect(resource.rule_name).to eql("rule2")
+ end
+
+ it "the description property accepts strings" do
+ resource.description("firewall rule")
+ expect(resource.description).to eql("firewall rule")
+ end
+
+ it "the local_address property accepts strings" do
+ resource.local_address("192.168.1.1")
+ expect(resource.local_address).to eql("192.168.1.1")
+ end
+
+ it "the local_port property accepts integers" do
+ resource.local_port(8080)
+ expect(resource.local_port).to eql(["8080"])
+ end
+
+ it "the local_port property accepts strings" do
+ resource.local_port("8080")
+ expect(resource.local_port).to eql(["8080"])
+ end
+
+ it "the local_port property accepts comma separated lists without spaces" do
+ resource.local_port("8080,8081")
+ expect(resource.local_port).to eql(%w{8080 8081})
+ end
+
+ it "the local_port property accepts comma separated lists with spaces" do
+ resource.local_port("8080, 8081")
+ expect(resource.local_port).to eql(%w{8080 8081})
+ end
+
+ it "the local_port property accepts arrays and coerces to a sorta array of strings" do
+ resource.local_port([8081, 8080])
+ expect(resource.local_port).to eql(%w{8080 8081})
+ end
+
+ it "the remote_address property accepts strings" do
+ resource.remote_address("8.8.4.4")
+ expect(resource.remote_address).to eql("8.8.4.4")
+ end
+
+ it "the remote_port property accepts strings" do
+ resource.remote_port("8081")
+ expect(resource.remote_port).to eql(["8081"])
+ end
+
+ it "the remote_port property accepts integers" do
+ resource.remote_port(8081)
+ expect(resource.remote_port).to eql(["8081"])
+ end
+
+ it "the remote_port property accepts comma separated lists without spaces" do
+ resource.remote_port("8080,8081")
+ expect(resource.remote_port).to eql(%w{8080 8081})
+ end
+
+ it "the remote_port property accepts comma separated lists with spaces" do
+ resource.remote_port("8080, 8081")
+ expect(resource.remote_port).to eql(%w{8080 8081})
+ end
+
+ it "the remote_port property accepts arrays and coerces to a sorta array of strings" do
+ resource.remote_port([8081, 8080])
+ expect(resource.remote_port).to eql(%w{8080 8081})
+ end
+
+ it "the direction property accepts :inbound and :outbound" do
+ resource.direction(:inbound)
+ expect(resource.direction).to eql(:inbound)
+ resource.direction(:outbound)
+ expect(resource.direction).to eql(:outbound)
+ end
+
+ it "the direction property coerces strings to symbols" do
+ resource.direction("Inbound")
+ expect(resource.direction).to eql(:inbound)
+ end
+
+ it "the protocol property accepts strings" do
+ resource.protocol("TCP")
+ expect(resource.protocol).to eql("TCP")
+ end
+
+ it "the firewall_action property accepts :allow, :block and :notconfigured" do
+ resource.firewall_action(:allow)
+ expect(resource.firewall_action).to eql(:allow)
+ resource.firewall_action(:block)
+ expect(resource.firewall_action).to eql(:block)
+ resource.firewall_action(:notconfigured)
+ expect(resource.firewall_action).to eql(:notconfigured)
+ end
+
+ it "the firewall_action property coerces strings to symbols" do
+ resource.firewall_action("Allow")
+ expect(resource.firewall_action).to eql(:allow)
+ end
+
+ it "the profile property accepts :public, :private, :domain, :any and :notapplicable" do
+ resource.profile(:public)
+ expect(resource.profile).to eql(:public)
+ resource.profile(:private)
+ expect(resource.profile).to eql(:private)
+ resource.profile(:domain)
+ expect(resource.profile).to eql(:domain)
+ resource.profile(:any)
+ expect(resource.profile).to eql(:any)
+ resource.profile(:notapplicable)
+ expect(resource.profile).to eql(:notapplicable)
+ end
+
+ it "the profile property coerces strings to symbols" do
+ resource.profile("Public")
+ expect(resource.profile).to eql(:public)
+ end
+
+ it "the program property accepts strings" do
+ resource.program("C:/Test/test.exe")
+ expect(resource.program).to eql("C:/Test/test.exe")
+ end
+
+ it "the service property accepts strings" do
+ resource.service("Spooler")
+ expect(resource.service).to eql("Spooler")
+ end
+
+ it "the interface_type property accepts :any, :wireless, :wired and :remoteaccess" do
+ resource.interface_type(:any)
+ expect(resource.interface_type).to eql(:any)
+ resource.interface_type(:wireless)
+ expect(resource.interface_type).to eql(:wireless)
+ resource.interface_type(:wired)
+ expect(resource.interface_type).to eql(:wired)
+ resource.interface_type(:remoteaccess)
+ expect(resource.interface_type).to eql(:remoteaccess)
+ end
+
+ it "the interface_type property coerces strings to symbols" do
+ resource.interface_type("Any")
+ expect(resource.interface_type).to eql(:any)
+ end
+
+ it "the enabled property accepts true and false" do
+ resource.enabled(true)
+ expect(resource.enabled).to eql(true)
+ resource.enabled(false)
+ expect(resource.enabled).to eql(false)
+ end
+
+ it "aliases :localip to :local_address" do
+ resource.localip("192.168.30.30")
+ expect(resource.local_address).to eql("192.168.30.30")
+ end
+
+ it "aliases :remoteip to :remote_address" do
+ resource.remoteip("8.8.8.8")
+ expect(resource.remote_address).to eql("8.8.8.8")
+ end
+
+ it "aliases :localport to :local_port" do
+ resource.localport("80")
+ expect(resource.local_port).to eql(["80"])
+ end
+
+ it "aliases :remoteport to :remote_port" do
+ resource.remoteport("8080")
+ expect(resource.remote_port).to eql(["8080"])
+ end
+
+ it "aliases :interfacetype to :interface_type" do
+ resource.interfacetype(:any)
+ expect(resource.interface_type).to eql(:any)
+ end
+
+ describe "#firewall_command" do
+ before do
+ resource.rule_name("test_rule")
+ end
+
+ context "#new" do
+ it "build a minimal command" do
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets a description" do
+ resource.description("New description")
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'New description' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets LocalAddress" do
+ resource.local_address("127.0.0.1")
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -LocalAddress '127.0.0.1' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets LocalPort" do
+ resource.local_port("80")
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -LocalPort 80 -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets RemoteAddress" do
+ resource.remote_address("8.8.8.8")
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -RemoteAddress '8.8.8.8' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets RemotePort" do
+ resource.remote_port("443")
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -RemotePort 443 -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Direction" do
+ resource.direction(:outbound)
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -Direction 'outbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Protocol" do
+ resource.protocol("UDP")
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'UDP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Action" do
+ resource.firewall_action(:block)
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'block' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Profile" do
+ resource.profile(:private)
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'private' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Program" do
+ resource.program("C:/calc.exe")
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -Program 'C:/calc.exe' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Service" do
+ resource.service("Spooler")
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -Service 'Spooler' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets InterfaceType" do
+ resource.interface_type(:wired)
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'wired' -Enabled 'true'")
+ end
+
+ it "sets Enabled" do
+ resource.enabled(false)
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule' -DisplayName 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'false'")
+ end
+
+ it "sets all properties" do
+ resource.rule_name("test_rule_the_second")
+ resource.description("some other rule")
+ resource.local_address("192.168.40.40")
+ resource.local_port("80")
+ resource.remote_address("8.8.4.4")
+ resource.remote_port("8081")
+ resource.direction(:outbound)
+ resource.protocol("UDP")
+ resource.firewall_action(:notconfigured)
+ resource.profile(:domain)
+ resource.program('%WINDIR%\System32\lsass.exe')
+ resource.service("SomeService")
+ resource.interface_type(:remoteaccess)
+ resource.enabled(false)
+ expect(provider.firewall_command("New")).to eql("New-NetFirewallRule -Name 'test_rule_the_second' -DisplayName 'test_rule_the_second' -Description 'some other rule' -LocalAddress '192.168.40.40' -LocalPort 80 -RemoteAddress '8.8.4.4' -RemotePort 8081 -Direction 'outbound' -Protocol 'UDP' -Action 'notconfigured' -Profile 'domain' -Program '%WINDIR%\\System32\\lsass.exe' -Service 'SomeService' -InterfaceType 'remoteaccess' -Enabled 'false'")
+ end
+ end
+
+ context "#set" do
+ it "build a minimal command" do
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets a description" do
+ resource.description("New description")
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'New description' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets LocalAddress" do
+ resource.local_address("127.0.0.1")
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -LocalAddress '127.0.0.1' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets LocalPort" do
+ resource.local_port("80")
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -LocalPort 80 -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets RemoteAddress" do
+ resource.remote_address("8.8.8.8")
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -RemoteAddress '8.8.8.8' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets RemotePort" do
+ resource.remote_port("443")
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -RemotePort 443 -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Direction" do
+ resource.direction(:outbound)
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -Direction 'outbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Protocol" do
+ resource.protocol("UDP")
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'UDP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Action" do
+ resource.firewall_action(:block)
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'block' -Profile 'any' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Profile" do
+ resource.profile(:private)
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'private' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Program" do
+ resource.program("C:/calc.exe")
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -Program 'C:/calc.exe' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets Service" do
+ resource.service("Spooler")
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -Service 'Spooler' -InterfaceType 'any' -Enabled 'true'")
+ end
+
+ it "sets InterfaceType" do
+ resource.interface_type(:wired)
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'wired' -Enabled 'true'")
+ end
+
+ it "sets Enabled" do
+ resource.enabled(false)
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule' -Description 'Firewall rule' -Direction 'inbound' -Protocol 'TCP' -Action 'allow' -Profile 'any' -InterfaceType 'any' -Enabled 'false'")
+ end
+
+ it "sets all properties" do
+ resource.rule_name("test_rule_the_second")
+ resource.description("some other rule")
+ resource.local_address("192.168.40.40")
+ resource.local_port("80")
+ resource.remote_address("8.8.4.4")
+ resource.remote_port("8081")
+ resource.direction(:outbound)
+ resource.protocol("UDP")
+ resource.firewall_action(:notconfigured)
+ resource.profile(:domain)
+ resource.program('%WINDIR%\System32\lsass.exe')
+ resource.service("SomeService")
+ resource.interface_type(:remoteaccess)
+ resource.enabled(false)
+ expect(provider.firewall_command("Set")).to eql("Set-NetFirewallRule -Name 'test_rule_the_second' -Description 'some other rule' -LocalAddress '192.168.40.40' -LocalPort 80 -RemoteAddress '8.8.4.4' -RemotePort 8081 -Direction 'outbound' -Protocol 'UDP' -Action 'notconfigured' -Profile 'domain' -Program '%WINDIR%\\System32\\lsass.exe' -Service 'SomeService' -InterfaceType 'remoteaccess' -Enabled 'false'")
+ end
+ end
+ end
+end
diff --git a/spec/unit/resource/windows_service_spec.rb b/spec/unit/resource/windows_service_spec.rb
index 8648b52a17..b44a86d04a 100644
--- a/spec/unit/resource/windows_service_spec.rb
+++ b/spec/unit/resource/windows_service_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Bryan McLellan <btm@loftninjas.org>
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2018, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,14 +19,6 @@
require "spec_helper"
describe Chef::Resource::WindowsService, "initialize" do
- static_provider_resolution(
- resource: Chef::Resource::WindowsService,
- provider: Chef::Provider::Service::Windows,
- os: "windows",
- name: :windows_service,
- action: :start
- )
-
let(:resource) { Chef::Resource::WindowsService.new("fakey_fakerton") }
it "sets the resource_name to :windows_service" do
@@ -56,9 +48,32 @@ describe Chef::Resource::WindowsService, "initialize" do
expect { resource.action :unmask }.not_to raise_error
end
- it "supports setting startup_type" do
- resource.startup_type(:manual)
- expect(resource.startup_type).to eql(:manual)
+ [:automatic, :manual, :disabled].each do |type|
+ it "supports setting startup_type property to #{type.inspect}" do
+ resource.startup_type type
+ expect(resource.startup_type).to eql(type)
+ end
+ end
+
+ { 2 => :automatic, 3 => :manual, 4 => :disabled }.each_pair do |k, v|
+ it "it coerces startup_type property #{k} to #{v.inspect}" do
+ resource.startup_type k
+ expect(resource.startup_type).to eql(v)
+ end
+ end
+
+ %w{automatic manual disabled}.each do |type|
+ it "it coerces startup_type property #{type} to :#{type}" do
+ resource.startup_type type
+ expect(resource.startup_type).to eql(type.to_sym)
+ end
+ end
+
+ [:automatic, :manual, :disabled].each do |type|
+ it "supports setting startup_type property to #{type.inspect}" do
+ resource.startup_type type
+ expect(resource.startup_type).to eql(type)
+ end
end
it "allows the action to be 'configure_startup'" do
@@ -69,7 +84,7 @@ describe Chef::Resource::WindowsService, "initialize" do
# Properties that are Strings
%i{description service_name binary_path_name load_order_group dependencies
run_as_user run_as_password display_name}.each do |prop|
- it "support setting #{prop}" do
+ it "support setting #{prop} property with a String" do
resource.send("#{prop}=", "some value")
expect(resource.send(prop)).to eq("some value")
end
@@ -77,7 +92,7 @@ describe Chef::Resource::WindowsService, "initialize" do
# Properties that are Integers
%i{desired_access error_control service_type}.each do |prop|
- it "support setting #{prop}" do
+ it "support setting #{prop} property with an Integer" do
resource.send("#{prop}=", 1)
expect(resource.send(prop)).to eq(1)
end
diff --git a/spec/unit/resource/windows_share.rb b/spec/unit/resource/windows_share.rb
new file mode 100644
index 0000000000..ee1c24529f
--- /dev/null
+++ b/spec/unit/resource/windows_share.rb
@@ -0,0 +1,39 @@
+#
+# 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::WindowsShare do
+ let(:resource) { Chef::Resource::WindowsShare.new("foobar") }
+
+ it "sets resource name as :windows_share" do
+ expect(resource.resource_name).to eql(:windows_share)
+ end
+
+ it "the share_name property is the name_property" do
+ expect(resource.share_name).to eql("foobar")
+ end
+
+ it "sets the default action as :create" do
+ expect(resource.action).to eql([:create])
+ end
+
+ it "supports :create and :delete actions" do
+ expect { resource.action :create }.not_to raise_error
+ expect { resource.action :delete }.not_to raise_error
+ end
+end
diff --git a/spec/unit/resource/windows_workgroup_spec.rb b/spec/unit/resource/windows_workgroup_spec.rb
index 3d7acec2fb..0ea0d8b291 100644
--- a/spec/unit/resource/windows_workgroup_spec.rb
+++ b/spec/unit/resource/windows_workgroup_spec.rb
@@ -19,6 +19,7 @@ require "spec_helper"
describe Chef::Resource::WindowsWorkgroup do
let(:resource) { Chef::Resource::WindowsWorkgroup.new("example") }
+ let(:provider) { resource.provider_for_action(:join) }
it "sets resource name as :windows_workgroup" do
expect(resource.resource_name).to eql(:windows_workgroup)
@@ -28,6 +29,16 @@ describe Chef::Resource::WindowsWorkgroup do
expect(resource.workgroup_name).to eql("example")
end
+ it "converts the legacy :immediate reboot property to :reboot_now" do
+ resource.reboot(:immediate)
+ expect(resource.reboot).to eql(:reboot_now)
+ end
+
+ it "converts the legacy :delayed reboot property to :request_reboot" do
+ resource.reboot(:delayed)
+ expect(resource.reboot).to eql(:request_reboot)
+ end
+
it "sets the default action as :join" do
expect(resource.action).to eql([:join])
end
@@ -44,4 +55,20 @@ describe Chef::Resource::WindowsWorkgroup do
expect { resource.reboot :never }.not_to raise_error
expect { resource.reboot :nopenope }.to raise_error(ArgumentError)
end
+
+ describe "#join_command" do
+ context "if password property is not specified" do
+ it "contructs a command without credentials" do
+ expect(provider.join_command).to eql("Add-Computer -WorkgroupName example -Force")
+ end
+ end
+
+ context "if password property is specified" do
+ it "contructs a command without credentials" do
+ resource.password("1234")
+ resource.user("admin")
+ expect(provider.join_command).to eql("$pswd = ConvertTo-SecureString '1234' -AsPlainText -Force;$credential = New-Object System.Management.Automation.PSCredential (\"admin\",$pswd);Add-Computer -WorkgroupName example -Credential $credential -Force")
+ end
+ end
+ end
end
diff --git a/spec/unit/run_context/cookbook_compiler_spec.rb b/spec/unit/run_context/cookbook_compiler_spec.rb
index e93088cd5f..c3a4c1b98f 100644
--- a/spec/unit/run_context/cookbook_compiler_spec.rb
+++ b/spec/unit/run_context/cookbook_compiler_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -108,6 +108,10 @@ describe Chef::RunContext::CookbookCompiler do
compiler.compile_libraries
expect(LibraryLoadOrder.load_order).to eq(["dependency1", "dependency2", "test-with-deps", "circular-dep2", "circular-dep1", "test-with-circular-deps"])
+
+ # additionally test that we only load them once
+ compiler.compile_libraries
+ expect(LibraryLoadOrder.load_order).to eq(["dependency1", "dependency2", "test-with-deps", "circular-dep2", "circular-dep1", "test-with-circular-deps"])
end
end