summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml40
-rw-r--r--CHANGELOG.md47
-rw-r--r--Dockerfile2
-rw-r--r--Gemfile6
-rw-r--r--Gemfile.lock122
-rw-r--r--MAINTAINERS.md1
-rw-r--r--MAINTAINERS.toml9
-rw-r--r--RELEASE_NOTES.md253
-rw-r--r--VERSION2
-rw-r--r--acceptance/Gemfile.lock10
-rw-r--r--acceptance/data-collector/.acceptance/data-collector-test/metadata.rb2
-rw-r--r--acceptance/data-collector/test/integration/default/serverspec/default_spec.rb4
-rw-r--r--appveyor.yml1
-rw-r--r--chef-config/lib/chef-config/config.rb18
-rw-r--r--chef-config/lib/chef-config/version.rb2
-rw-r--r--chef.gemspec3
-rw-r--r--kitchen-tests/.kitchen.travis.yml8
-rw-r--r--kitchen-tests/.kitchen.yml1
-rw-r--r--kitchen-tests/Berksfile9
-rw-r--r--kitchen-tests/Berksfile.lock72
-rw-r--r--kitchen-tests/Gemfile.lock29
-rw-r--r--kitchen-tests/cookbooks/audit_test/metadata.rb2
-rw-r--r--kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/metadata.rb2
-rw-r--r--kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/recipes/default.rb6
-rw-r--r--kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/metadata.rb2
-rw-r--r--kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/recipes/default.rb6
-rw-r--r--kitchen-tests/cookbooks/base/metadata.rb2
-rw-r--r--kitchen-tests/cookbooks/base/recipes/default.rb4
-rw-r--r--kitchen-tests/cookbooks/base/recipes/packages.rb6
-rw-r--r--kitchen-tests/cookbooks/base/recipes/tests.rb6
-rw-r--r--kitchen-tests/cookbooks/webapp/metadata.rb2
-rw-r--r--kitchen-tests/cookbooks/webapp/templates/index.html.erb (renamed from kitchen-tests/cookbooks/webapp/templates/default/index.html.erb)0
-rw-r--r--kitchen-tests/cookbooks/webapp/templates/index.php.erb (renamed from kitchen-tests/cookbooks/webapp/templates/default/index.php.erb)0
-rw-r--r--lib/chef/application.rb33
-rw-r--r--lib/chef/application/exit_code.rb87
-rw-r--r--lib/chef/application/windows_service.rb14
-rw-r--r--lib/chef/chef_fs/chef_fs_data_store.rb2
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb4
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/cookbook_artifacts_dir.rb8
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb39
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb6
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/versioned_cookbooks_dir.rb6
-rw-r--r--lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb7
-rw-r--r--lib/chef/client.rb47
-rw-r--r--lib/chef/config_fetcher.rb8
-rw-r--r--lib/chef/cookbook/cookbook_version_loader.rb85
-rw-r--r--lib/chef/cookbook/file_system_file_vendor.rb2
-rw-r--r--lib/chef/cookbook/gem_installer.rb16
-rw-r--r--lib/chef/cookbook/manifest_v0.rb68
-rw-r--r--lib/chef/cookbook/manifest_v2.rb41
-rw-r--r--lib/chef/cookbook/metadata.rb113
-rw-r--r--lib/chef/cookbook/remote_file_vendor.rb6
-rw-r--r--lib/chef/cookbook/synchronizer.rb45
-rw-r--r--lib/chef/cookbook_manifest.rb156
-rw-r--r--lib/chef/cookbook_site_streaming_uploader.rb16
-rw-r--r--lib/chef/cookbook_uploader.rb2
-rw-r--r--lib/chef/cookbook_version.rb215
-rw-r--r--lib/chef/data_bag_item.rb3
-rw-r--r--lib/chef/data_collector/messages.rb2
-rw-r--r--lib/chef/decorator/unchain.rb16
-rw-r--r--lib/chef/deprecated.rb20
-rw-r--r--lib/chef/dsl/declare_resource.rb2
-rw-r--r--lib/chef/event_dispatch/base.rb16
-rw-r--r--lib/chef/exceptions.rb8
-rw-r--r--lib/chef/formatters/error_description.rb19
-rw-r--r--lib/chef/guard_interpreter/default_guard_interpreter.rb6
-rw-r--r--lib/chef/http/socketless_chef_zero_client.rb1
-rw-r--r--lib/chef/knife.rb5
-rw-r--r--lib/chef/knife/configure.rb4
-rw-r--r--lib/chef/knife/configure_client.rb4
-rw-r--r--lib/chef/knife/cookbook_create.rb435
-rw-r--r--lib/chef/knife/cookbook_download.rb7
-rw-r--r--lib/chef/knife/cookbook_show.rb10
-rw-r--r--lib/chef/knife/cookbook_site_vendor.rb46
-rw-r--r--lib/chef/knife/core/custom_manifest_loader.rb69
-rw-r--r--lib/chef/knife/core/subcommand_loader.rb34
-rw-r--r--lib/chef/knife/search.rb18
-rw-r--r--lib/chef/knife/ssh.rb30
-rw-r--r--lib/chef/mixin/command.rb194
-rw-r--r--lib/chef/mixin/command/unix.rb220
-rw-r--r--lib/chef/mixin/command/windows.rb71
-rw-r--r--lib/chef/mixin/path_sanity.rb36
-rw-r--r--lib/chef/mixin/shell_out.rb40
-rw-r--r--lib/chef/mixins.rb1
-rw-r--r--lib/chef/node.rb4
-rw-r--r--lib/chef/platform/rebooter.rb3
-rw-r--r--lib/chef/policy_builder/expand_node_object.rb3
-rw-r--r--lib/chef/policy_builder/policyfile.rb13
-rw-r--r--lib/chef/property.rb14
-rw-r--r--lib/chef/provider.rb147
-rw-r--r--lib/chef/provider/apt_repository.rb2
-rw-r--r--lib/chef/provider/apt_update.rb2
-rw-r--r--lib/chef/provider/cron.rb30
-rw-r--r--lib/chef/provider/deploy.rb2
-rw-r--r--lib/chef/provider/env.rb2
-rw-r--r--lib/chef/provider/erl_call.rb46
-rw-r--r--lib/chef/provider/group.rb2
-rw-r--r--lib/chef/provider/ifconfig.rb2
-rw-r--r--lib/chef/provider/ifconfig/redhat.rb2
-rw-r--r--lib/chef/provider/launchd.rb4
-rw-r--r--lib/chef/provider/lwrp_base.rb9
-rw-r--r--lib/chef/provider/mdadm.rb4
-rw-r--r--lib/chef/provider/ohai.rb2
-rw-r--r--lib/chef/provider/osx_profile.rb1
-rw-r--r--lib/chef/provider/package.rb16
-rw-r--r--lib/chef/provider/package/aix.rb1
-rw-r--r--lib/chef/provider/package/cab.rb1
-rw-r--r--lib/chef/provider/package/dnf.rb2
-rw-r--r--lib/chef/provider/package/ips.rb1
-rw-r--r--lib/chef/provider/package/msu.rb1
-rw-r--r--lib/chef/provider/package/pacman.rb1
-rw-r--r--lib/chef/provider/package/portage.rb1
-rw-r--r--lib/chef/provider/package/rpm.rb1
-rw-r--r--lib/chef/provider/package/rubygems.rb20
-rw-r--r--lib/chef/provider/package/solaris.rb1
-rw-r--r--lib/chef/provider/package/windows/msi.rb2
-rw-r--r--lib/chef/provider/package/yum.rb6
-rw-r--r--lib/chef/provider/package/zypper.rb14
-rw-r--r--lib/chef/provider/route.rb2
-rw-r--r--lib/chef/provider/service.rb5
-rw-r--r--lib/chef/provider/service/debian.rb36
-rw-r--r--lib/chef/provider/service/freebsd.rb1
-rw-r--r--lib/chef/provider/service/gentoo.rb1
-rw-r--r--lib/chef/provider/service/init.rb1
-rw-r--r--lib/chef/provider/service/insserv.rb4
-rw-r--r--lib/chef/provider/service/openbsd.rb1
-rw-r--r--lib/chef/provider/service/redhat.rb4
-rw-r--r--lib/chef/provider/service/simple.rb1
-rw-r--r--lib/chef/provider/service/solaris.rb1
-rw-r--r--lib/chef/provider/service/upstart.rb22
-rw-r--r--lib/chef/provider/subversion.rb2
-rw-r--r--lib/chef/provider/systemd_unit.rb2
-rw-r--r--lib/chef/provider/template/content.rb25
-rw-r--r--lib/chef/provider/user.rb2
-rw-r--r--lib/chef/provider/user/linux.rb1
-rw-r--r--lib/chef/provider/user/pw.rb8
-rw-r--r--lib/chef/provider/windows_task.rb418
-rw-r--r--lib/chef/provider/yum_repository.rb2
-rw-r--r--lib/chef/providers.rb1
-rw-r--r--lib/chef/resource.rb33
-rw-r--r--lib/chef/resource/action_class.rb2
-rw-r--r--lib/chef/resource/chocolatey_package.rb5
-rw-r--r--lib/chef/resource/dnf_package.rb2
-rw-r--r--lib/chef/resource/execute.rb1
-rw-r--r--lib/chef/resource/gem_package.rb16
-rw-r--r--lib/chef/resource/launchd.rb16
-rw-r--r--lib/chef/resource/lwrp_base.rb2
-rw-r--r--lib/chef/resource/mount.rb2
-rw-r--r--lib/chef/resource/package.rb2
-rw-r--r--lib/chef/resource/systemd_unit.rb5
-rw-r--r--lib/chef/resource/windows_package.rb5
-rw-r--r--lib/chef/resource/windows_task.rb237
-rw-r--r--lib/chef/resource/yum_package.rb2
-rw-r--r--lib/chef/resource/zypper_package.rb2
-rw-r--r--lib/chef/resource_collection/resource_set.rb46
-rw-r--r--lib/chef/resource_resolver.rb5
-rw-r--r--lib/chef/resources.rb1
-rw-r--r--lib/chef/run_context/cookbook_compiler.rb54
-rw-r--r--lib/chef/search/query.rb18
-rw-r--r--lib/chef/version.rb2
-rw-r--r--omnibus/Gemfile.lock26
-rw-r--r--omnibus/config/software/chef-gem-inspec.rb10
-rw-r--r--omnibus/config/software/chef.rb2
-rw-r--r--omnibus/files/chef-gem/build-chef-gem.rb2
-rw-r--r--omnibus_overrides.rb2
-rw-r--r--spec/data/cookbooks/openldap/templates/default/openldap_nested_variable_stuff.erb1
-rw-r--r--spec/data/lwrp/providers/buck_passer.rb2
-rw-r--r--spec/data/lwrp/providers/buck_passer_2.rb2
-rw-r--r--spec/data/lwrp/providers/embedded_resource_accesses_providers_scope.rb2
-rw-r--r--spec/data/lwrp/providers/inline_compiler.rb2
-rw-r--r--spec/data/root_alias_cookbooks/dup_attr/attributes.rb1
-rw-r--r--spec/data/root_alias_cookbooks/dup_attr/attributes/default.rb1
-rw-r--r--spec/data/root_alias_cookbooks/dup_attr/metadata.rb2
-rw-r--r--spec/data/root_alias_cookbooks/dup_attr/recipe.rb3
-rw-r--r--spec/data/root_alias_cookbooks/dup_recipe/attributes.rb1
-rw-r--r--spec/data/root_alias_cookbooks/dup_recipe/metadata.rb2
-rw-r--r--spec/data/root_alias_cookbooks/dup_recipe/recipe.rb3
-rw-r--r--spec/data/root_alias_cookbooks/dup_recipe/recipes/default.rb3
-rw-r--r--spec/data/root_alias_cookbooks/simple/attributes.rb1
-rw-r--r--spec/data/root_alias_cookbooks/simple/metadata.rb2
-rw-r--r--spec/data/root_alias_cookbooks/simple/recipe.rb3
-rw-r--r--spec/functional/rebooter_spec.rb1
-rw-r--r--spec/functional/resource/cron_spec.rb4
-rw-r--r--spec/functional/resource/template_spec.rb33
-rw-r--r--spec/functional/root_alias_spec.rb78
-rw-r--r--spec/functional/shell_spec.rb62
-rw-r--r--spec/integration/client/client_spec.rb76
-rw-r--r--spec/integration/client/exit_code_spec.rb106
-rw-r--r--spec/integration/knife/chef_repository_file_system_spec.rb97
-rw-r--r--spec/integration/knife/cookbook_download_spec.rb24
-rw-r--r--spec/integration/knife/cookbook_show_spec.rb35
-rw-r--r--spec/integration/knife/search_node_spec.rb39
-rw-r--r--spec/integration/knife/serve_spec.rb80
-rw-r--r--spec/integration/recipes/lwrp_inline_resources_spec.rb18
-rw-r--r--spec/integration/recipes/notifies_spec.rb29
-rw-r--r--spec/support/shared/context/client.rb9
-rw-r--r--spec/support/shared/integration/knife_support.rb2
-rw-r--r--spec/unit/application/exit_code_spec.rb93
-rw-r--r--spec/unit/application_spec.rb68
-rw-r--r--spec/unit/client_spec.rb103
-rw-r--r--spec/unit/config_fetcher_spec.rb4
-rw-r--r--spec/unit/cookbook/cookbook_version_loader_spec.rb41
-rw-r--r--spec/unit/cookbook/file_vendor_spec.rb29
-rw-r--r--spec/unit/cookbook/gem_installer_spec.rb85
-rw-r--r--spec/unit/cookbook/manifest_v0_spec.rb133
-rw-r--r--spec/unit/cookbook/manifest_v2_spec.rb70
-rw-r--r--spec/unit/cookbook/metadata_spec.rb137
-rw-r--r--spec/unit/cookbook/synchronizer_spec.rb11
-rw-r--r--spec/unit/cookbook/syntax_check_spec.rb1
-rw-r--r--spec/unit/cookbook_loader_spec.rb36
-rw-r--r--spec/unit/cookbook_manifest_spec.rb56
-rw-r--r--spec/unit/cookbook_site_streaming_uploader_spec.rb4
-rw-r--r--spec/unit/cookbook_spec.rb24
-rw-r--r--spec/unit/cookbook_uploader_spec.rb2
-rw-r--r--spec/unit/cookbook_version_file_specificity_spec.rb83
-rw-r--r--spec/unit/cookbook_version_spec.rb147
-rw-r--r--spec/unit/data_bag_item_spec.rb4
-rw-r--r--spec/unit/data_collector/messages_spec.rb137
-rw-r--r--spec/unit/formatters/error_description_spec.rb59
-rw-r--r--spec/unit/http/socketless_chef_zero_client_spec.rb3
-rw-r--r--spec/unit/knife/configure_client_spec.rb2
-rw-r--r--spec/unit/knife/cookbook_create_spec.rb221
-rw-r--r--spec/unit/knife/cookbook_download_spec.rb74
-rw-r--r--spec/unit/knife/cookbook_show_spec.rb51
-rw-r--r--spec/unit/knife/core/cookbook_scm_repo_spec.rb2
-rw-r--r--spec/unit/knife/core/custom_manifest_loader_spec.rb41
-rw-r--r--spec/unit/knife/core/subcommand_loader_spec.rb6
-rw-r--r--spec/unit/knife/core/ui_spec.rb3
-rw-r--r--spec/unit/knife_spec.rb4
-rw-r--r--spec/unit/lwrp_spec.rb109
-rw-r--r--spec/unit/mixin/command_spec.rb107
-rw-r--r--spec/unit/mixin/path_sanity_spec.rb14
-rw-r--r--spec/unit/mixin/shell_out_spec.rb102
-rw-r--r--spec/unit/node_spec.rb6
-rw-r--r--spec/unit/policy_builder/policyfile_spec.rb24
-rw-r--r--spec/unit/property_spec.rb78
-rw-r--r--spec/unit/provider/cron_spec.rb54
-rw-r--r--spec/unit/provider/erl_call_spec.rb18
-rw-r--r--spec/unit/provider/package/rubygems_spec.rb121
-rw-r--r--spec/unit/provider/package/windows/msi_spec.rb2
-rw-r--r--spec/unit/provider/package/yum_spec.rb14
-rw-r--r--spec/unit/provider/package/zypper_spec.rb109
-rw-r--r--spec/unit/provider/service/debian_service_spec.rb34
-rw-r--r--spec/unit/provider/service/upstart_service_spec.rb37
-rw-r--r--spec/unit/provider/subversion_spec.rb4
-rw-r--r--spec/unit/provider/user/pw_spec.rb20
-rw-r--r--spec/unit/provider/windows_task_spec.rb392
-rw-r--r--spec/unit/provider_spec.rb7
-rw-r--r--spec/unit/resource/conditional_spec.rb4
-rw-r--r--spec/unit/resource/package_spec.rb9
-rw-r--r--spec/unit/resource/windows_task_spec.rb213
-rw-r--r--spec/unit/resource_collection/resource_set_spec.rb16
-rw-r--r--spec/unit/resource_collection_spec.rb3
-rw-r--r--spec/unit/run_context/cookbook_compiler_spec.rb4
-rw-r--r--spec/unit/search/query_spec.rb23
-rwxr-xr-xtasks/bin/bundle-platform20
-rw-r--r--tasks/bin/bundle-platform.bat2
-rw-r--r--tasks/bin/bundler_patch.rb27
-rwxr-xr-xtasks/bin/gem-version-diff37
-rw-r--r--tasks/bundle.rb50
-rw-r--r--tasks/bundle_util.rb110
-rw-r--r--tasks/dependencies.rb1
262 files changed, 4239 insertions, 4414 deletions
diff --git a/.travis.yml b/.travis.yml
index 30e0756539..e25c8535bf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,7 +25,7 @@ before_script:
branches:
only:
- master
- - 11-stable
+ - chef-12
env:
global:
@@ -115,24 +115,6 @@ matrix:
- sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
- cd kitchen-tests
script:
- - bundle exec kitchen test webapp-ubuntu-1204
- after_failure:
- - cat .kitchen/logs/kitchen.log
- env:
- - UBUNTU=12.04
- - KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.4.1
- services: docker
- sudo: required
- gemfile: kitchen-tests/Gemfile
- before_install:
- - gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2)
- - gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
- bundler_args: --without ci development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen
- before_script:
- - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
- - cd kitchen-tests
- script:
- bundle exec kitchen test webapp-ubuntu-1404
after_failure:
- cat .kitchen/logs/kitchen.log
@@ -188,7 +170,6 @@ matrix:
- cd kitchen-tests
script:
- bundle exec kitchen test webapp-debian-8
- bundler_args: --without ci development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen
after_failure:
- cat .kitchen/logs/kitchen.log
env:
@@ -323,6 +304,25 @@ matrix:
- cat /tmp/out.txt
- sudo cat /var/log/squid3/cache.log
- sudo cat /var/log/squid3/access.log
+ allow_failures:
+ - rvm: 2.4.1
+ services: docker
+ sudo: required
+ gemfile: kitchen-tests/Gemfile
+ before_install:
+ - gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2)
+ - gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
+ bundler_args: --without ci development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen
+ before_script:
+ - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
+ - cd kitchen-tests
+ script:
+ - travis_wait bundle exec kitchen test webapp-amazonlinux
+ after_failure:
+ - cat .kitchen/logs/kitchen.log
+ env:
+ - AMAZONLINUX=LATEST
+ - KITCHEN_YAML=.kitchen.travis.yml
notifications:
on_change: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b356451dfa..3a48982222 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,50 +1,7 @@
This changelog reflects the current state of chef's master branch on github and may not reflect the current released version of chef, which is [![Gem Version](https://badge.fury.io/rb/chef.svg)](https://badge.fury.io/rb/chef).
-## [v13.0.78](https://github.com/chef/chef/tree/v13.0.78) (2017-03-30)
-[Full Changelog](https://github.com/chef/chef/compare/v12.19.36...v13.0.78)
-
-**Closed issues:**
-
-- powershell\_script's default guard\_interpreter should be :powershell\_script [\#5953](https://github.com/chef/chef/issues/5953)
-- powershell\_out stdout contains '\r\n' at the end of the output [\#5947](https://github.com/chef/chef/issues/5947)
-- `group` resource not idempotent on Windows \(12.19.36\) [\#5857](https://github.com/chef/chef/issues/5857)
-- Chef doesn't have access to a file created by itself, under the ownership of SYSTEM? [\#5844](https://github.com/chef/chef/issues/5844)
-
-**Merged pull requests:**
-
-- disable building nokogiri on windows for now [\#5958](https://github.com/chef/chef/pull/5958) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: Make ActionClass a class [\#5952](https://github.com/chef/chef/pull/5952) ([lamont-granquist](https://github.com/lamont-granquist))
-- Fix action class weirdness in Chef-13 [\#5946](https://github.com/chef/chef/pull/5946) ([lamont-granquist](https://github.com/lamont-granquist))
-- Make ResourceReporter smarter to get resource identity and state [\#5941](https://github.com/chef/chef/pull/5941) ([afiune](https://github.com/afiune))
-- Chef-13: Simplify DSL creation [\#5934](https://github.com/chef/chef/pull/5934) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: Remove deprecated Chef::Client attrs [\#5932](https://github.com/chef/chef/pull/5932) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: remove method\_missing from the DSL [\#5930](https://github.com/chef/chef/pull/5930) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: remove node\_map back-compat [\#5926](https://github.com/chef/chef/pull/5926) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: remove deprecated run\_context methods [\#5925](https://github.com/chef/chef/pull/5925) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: remove Chef::ShellOut [\#5923](https://github.com/chef/chef/pull/5923) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: remove more deprecated provider\_resolver code [\#5920](https://github.com/chef/chef/pull/5920) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: remove old platform mapping code [\#5914](https://github.com/chef/chef/pull/5914) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: remove the old rake tasks [\#5913](https://github.com/chef/chef/pull/5913) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: raise on properties redefining inherited methods [\#5912](https://github.com/chef/chef/pull/5912) ([lamont-granquist](https://github.com/lamont-granquist))
-- fix node\#debug\_value access through arrays [\#5911](https://github.com/chef/chef/pull/5911) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: Nillable properties [\#5907](https://github.com/chef/chef/pull/5907) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: freeze merged node attribute [\#5905](https://github.com/chef/chef/pull/5905) ([lamont-granquist](https://github.com/lamont-granquist))
-- bump ruby to 2.3.3 [\#5902](https://github.com/chef/chef/pull/5902) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: Remove declare\_resource create\_if\_missing API [\#5900](https://github.com/chef/chef/pull/5900) ([lamont-granquist](https://github.com/lamont-granquist))
-- Properly use chef-shell in SoloSession by deprecating old behavior into SoloLegacySession [\#5898](https://github.com/chef/chef/pull/5898) ([afiune](https://github.com/afiune))
-- Chef-13: properly deep dup Node\#to\_hash [\#5896](https://github.com/chef/chef/pull/5896) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: remove method\_missing access to node object. [\#5895](https://github.com/chef/chef/pull/5895) ([lamont-granquist](https://github.com/lamont-granquist))
-- Jeremymv2/cheffs optimizations [\#5890](https://github.com/chef/chef/pull/5890) ([jeremymv2](https://github.com/jeremymv2))
-- Changed EOP to 'EOP' to avoid content expansion [\#5888](https://github.com/chef/chef/pull/5888) ([afiune](https://github.com/afiune))
-- Compress debs and rpms with xz [\#5884](https://github.com/chef/chef/pull/5884) ([thommay](https://github.com/thommay))
-- Chef-13: Chef::Resource cleanup [\#5882](https://github.com/chef/chef/pull/5882) ([lamont-granquist](https://github.com/lamont-granquist))
-- Fix apt\_repository for latest os version 16.10 [\#5874](https://github.com/chef/chef/pull/5874) ([afiune](https://github.com/afiune))
-- Chef-13: convert additional resource methods to properties [\#5871](https://github.com/chef/chef/pull/5871) ([lamont-granquist](https://github.com/lamont-granquist))
-- Add the ability to blacklist attributes from being saved to the chef server [\#5868](https://github.com/chef/chef/pull/5868) ([robmul](https://github.com/robmul))
-- Chef-13: remove supports API from Chef::Resource [\#5863](https://github.com/chef/chef/pull/5863) ([lamont-granquist](https://github.com/lamont-granquist))
-- HTTP: add debug long for non-JSON response [\#5858](https://github.com/chef/chef/pull/5858) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13 remove resource cloning and 3694 warnings [\#5856](https://github.com/chef/chef/pull/5856) ([lamont-granquist](https://github.com/lamont-granquist))
-- Chef-13: support why-run by default [\#5853](https://github.com/chef/chef/pull/5853) ([lamont-granquist](https://github.com/lamont-granquist))
+## [v13.0.117](https://github.com/chef/chef/tree/v13.0.117) (2017-04-12)
+[Full Changelog](https://github.com/chef/chef/compare/v13.0.113...v13.0.117)
## [v12.19.33](https://github.com/chef/chef/tree/v12.19.33) (2017-02-16)
[Full Changelog](https://github.com/chef/chef/compare/v12.18.31...v12.19.33)
diff --git a/Dockerfile b/Dockerfile
index cf1f1a64dd..d18adede4b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,7 +2,7 @@ FROM busybox
MAINTAINER Chef Software, Inc. <docker@chef.io>
ARG CHANNEL=stable
-ARG VERSION=12.19.36
+ARG VERSION=13.0.113
RUN wget "http://packages.chef.io/files/${CHANNEL}/chef/${VERSION}/el/5/chef-${VERSION}-1.el5.x86_64.rpm" -O /tmp/chef-client.rpm && \
rpm2cpio /tmp/chef-client.rpm | cpio -idmv && \
diff --git a/Gemfile b/Gemfile
index 49fc34986c..c18357639b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -11,17 +11,17 @@ source "https://rubygems.org"
# of bundler versions prior to 1.12.0 (https://github.com/bundler/bundler/commit/193a14fe5e0d56294c7b370a0e59f93b2c216eed)
gem "chef", path: "."
-# tracking master of ohai for chef-13.0 development, this should be able to be deleted after release
-gem "ohai", git: "https://github.com/chef/ohai.git"
+gem "ohai", "~> 13"
gem "chef-config", path: File.expand_path("../chef-config", __FILE__) if File.exist?(File.expand_path("../chef-config", __FILE__))
gem "rake"
gem "bundler"
-gem "cheffish" # required for rspec tests
+gem "cheffish", "~> 13" # required for rspec tests
group(:omnibus_package) do
gem "appbundler"
gem "rb-readline"
+ gem "inspec"
# nokogiri has no ruby-2.4 version for windows so it cannot go into our Gemfile.lock
# gem "nokogiri", ">= 1.7.1"
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 5d96b6cc18..12db299c07 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,6 +1,6 @@
GIT
remote: https://github.com/chef/chef-server
- revision: e530dd27a696ec154394f360411ae874adc4e3af
+ revision: 07fea253ceea254af8fbd9c602a04017751cae21
specs:
oc-chef-pedant (2.2.0)
activesupport (>= 4.2.7.1, < 6.0)
@@ -36,25 +36,8 @@ GIT
retriable (>= 1.4)
GIT
- remote: https://github.com/chef/ohai.git
- revision: 05cf05cb76ae22af9a8466e0226d0092b74c8414
- specs:
- ohai (13.0.0)
- chef-config (>= 12.5.0.alpha.1, < 14)
- ffi (~> 1.9)
- ffi-yajl (~> 2.2)
- ipaddress
- mixlib-cli
- mixlib-config (~> 2.0)
- mixlib-log (>= 1.7.1, < 2.0)
- mixlib-shellout (~> 2.0)
- plist (~> 3.1)
- systemu (~> 2.6.4)
- wmi-lite (~> 1.0)
-
-GIT
remote: https://github.com/poise/halite.git
- revision: 09c4ef7c6b8188ec2b9a929de8d9f6aa3f620553
+ revision: b9b3f61682abe1c656f57b7edbbf43d918c5c16b
specs:
halite (1.5.1.pre)
bundler
@@ -64,7 +47,7 @@ GIT
GIT
remote: https://github.com/poise/poise-boiler.git
- revision: d547f77ca7335af7943f681e1d0dd68c825cf429
+ revision: 40763eaded9384b1d8d3e3db6f883613b0a3ebe2
specs:
poise-boiler (1.14.1.pre)
bundler
@@ -97,7 +80,7 @@ GIT
GIT
remote: https://github.com/poise/poise.git
- revision: c42a55afe2ff897801b274eb47594135ac856b12
+ revision: 47cd0e2296fed918b30b0889ed127c824cc32d30
specs:
poise (2.7.3.pre)
halite (~> 1.0)
@@ -113,16 +96,17 @@ GIT
PATH
remote: .
specs:
- chef (13.0.79)
+ chef (13.0.118)
addressable
bundler (>= 1.10)
- chef-config (= 13.0.79)
- chef-zero (>= 4.8)
+ chef-config (= 13.0.118)
+ chef-zero (>= 13.0)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
ffi-yajl (~> 2.2)
highline (~> 1.6, >= 1.6.9)
iniparse (~> 1.4)
+ iso8601 (~> 0.9.1)
mixlib-archive (~> 0.4)
mixlib-authentication (~> 1.4)
mixlib-cli (~> 1.7)
@@ -142,17 +126,18 @@ PATH
specinfra (~> 2.10)
syslog-logger (~> 1.6)
uuidtools (~> 2.1.5)
- chef (13.0.79-universal-mingw32)
+ chef (13.0.118-universal-mingw32)
addressable
bundler (>= 1.10)
- chef-config (= 13.0.79)
- chef-zero (>= 4.8)
+ chef-config (= 13.0.118)
+ chef-zero (>= 13.0)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
highline (~> 1.6, >= 1.6.9)
iniparse (~> 1.4)
+ iso8601 (~> 0.9.1)
mixlib-archive (~> 0.4)
mixlib-authentication (~> 1.4)
mixlib-cli (~> 1.7)
@@ -186,7 +171,7 @@ PATH
PATH
remote: chef-config
specs:
- chef-config (13.0.79)
+ chef-config (13.0.118)
addressable
fuzzyurl
mixlib-config (~> 2.0)
@@ -205,31 +190,32 @@ GEM
mixlib-cli (~> 1.4)
artifactory (2.8.1)
ast (2.3.0)
- aws-sdk (2.8.14)
- aws-sdk-resources (= 2.8.14)
- aws-sdk-core (2.8.14)
+ aws-sdk (2.9.5)
+ aws-sdk-resources (= 2.9.5)
+ aws-sdk-core (2.9.5)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-resources (2.8.14)
- aws-sdk-core (= 2.8.14)
+ aws-sdk-resources (2.9.5)
+ aws-sdk-core (= 2.9.5)
aws-sigv4 (1.0.0)
backports (3.7.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
+ blankslate (2.1.2.4)
builder (3.2.3)
byebug (9.0.6)
chef-api (0.7.0)
logify (~> 0.1)
mime-types
chef-sugar (3.4.0)
- chef-zero (5.3.2)
+ chef-zero (13.0.0)
ffi-yajl (~> 2.2)
hashie (>= 2.0, < 4.0)
mixlib-log (~> 1.3)
rack (~> 2.0)
uuidtools (~> 2.1)
- cheffish (5.0.1)
- chef-zero (~> 5.0)
+ cheffish (13.0.0)
+ chef-zero (~> 13.0)
net-ssh
chefspec (5.4.0)
chef (>= 12.0)
@@ -257,13 +243,16 @@ GEM
debug_inspector (0.0.2)
diff-lcs (1.3)
docile (1.1.5)
- domain_name (0.5.20170223)
+ docker-api (1.33.3)
+ excon (>= 0.38.0)
+ json
+ domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
erubis (2.7.0)
ethon (0.10.1)
ffi (>= 1.3.0)
excon (0.55.0)
- faraday (0.11.0)
+ faraday (0.12.0.1)
multipart-post (>= 1.2, < 3)
faraday-http-cache (2.0.0)
faraday (~> 0.8)
@@ -309,7 +298,25 @@ GEM
httpclient (2.8.3)
i18n (0.8.1)
iniparse (1.4.2)
+ inspec (1.19.1)
+ addressable (~> 2.4)
+ faraday (>= 0.9.0)
+ hashie (~> 3.4)
+ json (>= 1.8, < 3.0)
+ method_source (~> 0.8)
+ mixlib-log
+ parallel (~> 1.9)
+ pry (~> 0)
+ rainbow (~> 2)
+ rspec (~> 3)
+ rspec-its (~> 1.2)
+ rubyzip (~> 1.1)
+ sslshake (~> 1)
+ thor (~> 0.19)
+ toml (~> 0.1)
+ train (>= 0.22.0, < 1.0)
ipaddress (0.8.3)
+ iso8601 (0.9.1)
jmespath (1.3.1)
json (2.0.3)
kitchen-docker (2.6.0)
@@ -323,7 +330,7 @@ GEM
kitchen-sync (2.1.2)
net-sftp
test-kitchen (>= 1.0.0)
- kitchen-vagrant (1.0.2)
+ kitchen-vagrant (1.1.0)
test-kitchen (~> 1.4)
knife-windows (1.9.0)
winrm (~> 2.1)
@@ -382,10 +389,25 @@ GEM
nokogiri (1.7.1-x86-mingw32)
mini_portile2 (~> 2.1.0)
nori (2.6.0)
- octokit (4.6.2)
+ octokit (4.7.0)
sawyer (~> 0.8.0, >= 0.5.3)
+ ohai (13.0.1)
+ chef-config (>= 12.5.0.alpha.1, < 14)
+ ffi (~> 1.9)
+ ffi-yajl (~> 2.2)
+ ipaddress
+ mixlib-cli
+ mixlib-config (~> 2.0)
+ mixlib-log (>= 1.7.1, < 2.0)
+ mixlib-shellout (~> 2.0)
+ plist (~> 3.1)
+ systemu (~> 2.6.4)
+ wmi-lite (~> 1.0)
+ parallel (1.11.1)
parser (2.4.0.0)
ast (~> 2.2)
+ parslet (1.5.0)
+ blankslate (~> 2.0)
plist (3.2.0)
poise-profiler (1.0.1)
halite (~> 1.0)
@@ -477,7 +499,8 @@ GEM
net-ssh (>= 2.7, < 5.0)
net-telnet
sfl
- stove (5.0.0)
+ sslshake (1.1.0)
+ stove (5.1.0)
chef-api (~> 0.5)
logify (~> 0.2)
syslog-logger (1.6.8)
@@ -492,7 +515,17 @@ GEM
thor (~> 0.19, < 0.19.2)
thor (0.19.1)
thread_safe (0.3.6)
+ toml (0.1.2)
+ parslet (~> 1.5.0)
tomlrb (1.2.4)
+ train (0.23.0)
+ docker-api (~> 1.26)
+ json (>= 1.8, < 3.0)
+ mixlib-shellout (~> 2.0)
+ net-scp (~> 1.2)
+ net-ssh (>= 2.9, < 5.0)
+ winrm (~> 2.0)
+ winrm-fs (~> 1.0)
travis (1.8.8)
backports
faraday (~> 0.9)
@@ -537,7 +570,7 @@ GEM
ffi-win32-extensions
windows-api (0.4.4)
win32-api (>= 1.4.5)
- winrm (2.1.3)
+ winrm (2.2.1)
builder (>= 2.1.2)
erubis (~> 2.7)
gssapi (~> 1.2)
@@ -571,19 +604,20 @@ DEPENDENCIES
chef!
chef-config!
chef-sugar
- cheffish
+ cheffish (~> 13)
chefspec
chefstyle!
cucumber (>= 2.4.0)
foodcritic
github_changelog_generator!
halite!
+ inspec
knife-windows
mixlib-install
netrc
oc-chef-pedant!
octokit
- ohai!
+ ohai (~> 13)
poise!
poise-boiler!
pry
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index c87879ac16..ae689483c7 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -46,6 +46,7 @@ To mention the team, use @chef/client-core
* [Tim Smith](https://github.com/tas50)
* [Tom Duffield](https://github.com/tduffield)
* [Tyler Ball](https://github.com/tyler-ball)
+* [Josh Hudson](https://github.com/itmustbejj)
## Chef Provisioning
diff --git a/MAINTAINERS.toml b/MAINTAINERS.toml
index 10e7655cd8..83de2c6bc6 100644
--- a/MAINTAINERS.toml
+++ b/MAINTAINERS.toml
@@ -51,7 +51,8 @@ Maintainers for the Chef client, Ohai, mixlibs, ChefDK, ChefSpec, Foodcritic, ch
"stevendanna",
"tas50",
"tduffield",
- "tyler-ball"
+ "tyler-ball",
+ "itmustbejj"
]
[Org.Components.Provisioning]
@@ -366,3 +367,9 @@ The specific components of Chef related to a given platform - including (but not
GitHub = "mikedodge04"
Twitter = "mikedodge04"
IRC = "mikedodge04"
+
+ [people.itmustbejj]
+ Name = "Josh Hudson"
+ GitHub = "itmustbejj"
+ Twitter = "itmustbejj"
+ IRC = "itmustbejj"
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index a1e5ceab45..e01bfc9097 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -2,7 +2,101 @@ _This file holds "in progress" release notes for the current release under devel
# Chef Client Release Notes 13.0:
-## Back Compat Breaks
+## Rubygems provider sources behavior changed.
+
+The behavior of `gem_package` and `chef_gem` is now to always apply the `Chef::Config[:rubygems_uri]` sources, which may be a
+String uri or an Array of Strings. If additional sources are put on the resource with the `source` property those are added
+to the configured `:rubygems_uri` sources.
+
+This should enable easier setup of rubygems mirrors particularly in "airgapped" environments through the use of the global config
+variable. It also means that an admin may force all rubygems.org traffic to an internal mirror, while still being able to
+consume external cookbooks which have resources which add other mirrors unchanged (in a non-airgapped environment).
+
+In the case where a resource must force the use of only the specified source(s), then the `include_default_source` property
+has been added -- setting it to false will remove the `Chef::Config[:rubygems_url]` setting from the list of sources for
+that resource.
+
+The behavior of the `clear_sources` property is now to only add `--clear-sources` and has no magic side effects on the source options.
+
+## Ruby version upgraded to 2.4.1
+
+We've upgraded to the latest stable release of the Ruby programming
+language. See the Ruby [2.4.0 Release Notes](https://www.ruby-lang.org/en/news/2016/12/25/ruby-2-4-0-released/) for an overview of what's new in the language.
+
+## Resource can now declare a default name
+
+The core `apt_update` resource can now be declared without any name argument, no need for `apt_update "this string doesn't matter but
+why do i have to type it?"`.
+
+This can be used by any other resource by just overriding the name property and supplying a default:
+
+```ruby
+ property :name, String, default: ""
+```
+
+Notifications to resources with empty strings as their name is also supported via either the bare resource name (`apt_update` --
+matches what the user types in the DSL) or with empty brackets (`apt_update[]` -- matches the resource notification pattern).
+
+## The knife ssh command applies the same fuzzifier as knife search node
+
+A bare name to knife search node will search for the name in `tags`, `roles`, `fqdn`, `addresses`, `policy_name` or `policy_group` fields and will
+match when given partial strings (available since Chef 11). The `knife ssh` search term has been similarly extended so that the
+search API matches in both cases. The node search fuzzifier has also been extracted out to a `fuzz` option to Chef::Search::Query for re-use
+elsewhere.
+
+## Cookbook root aliases
+
+Rather than `attributes/default.rb`, cookbooks can now use `attributes.rb` in
+the root of the cookbook. Similarly for a single default recipe, cookbooks can
+use `recipe.rb` in the root of the cookbook.
+
+## knife ssh can now connect to gateways with ssh key authentication
+
+The new `gateway_identity_file` option allows the operator to specify
+the key to access ssh gateways with.
+
+## Windows Task resource added
+
+The `windows_task` resource has been ported from the windows cookbook,
+and many bugs have been fixed.
+
+## Solaris SMF services can now been started recursively
+
+It is now possible to load Solaris services recursively, by ensuring the
+new `options` property of the `service` resource contains `-r`.
+
+## It's now possible to blacklist node attributes
+
+This is the inverse of the pre-existing whitelisting functionality.
+
+## The guard interpreter for `powershell_script` is Powershell, again
+
+When writing `not_if` or `only_if` statements, by default we now run
+those statements using powershell, rather than forcing the user to set
+`guard_interpreter` each time.
+
+## Zypper GPG checks by default
+
+Zypper now defaults to performing gpg checks of packages.
+
+## The InSpec gem is now shipped by default
+
+The `inspec` and `train` gems are shipped by default in the chef omnibus
+package, making it easier for users in airgapped environments to use
+InSpec.
+
+## Backwards Compatibility Breaks
+
+### Resource Cloning has been removed
+
+When Chef compiles resources, it will no longer attempt to merge the
+properties of previously compiled resources with the same name and type
+in to the new resource. See [the deprecation page](https://docs.chef.io/deprecations_resource_cloning.html) for further information.
+
+### It is an error to specify both `default` and `name_property` on a property
+
+Chef 12 made this work by picking the first option it found, but it was
+always an error and has now been disallowed.
### The path property of the execute resource has been removed
@@ -20,11 +114,11 @@ It is possible that this was being used as a no-op resource, but the log resourc
resource added. Omitting the code property or mixing up the code property with the command property are also common usage mistakes
that we need to catch and error on.
-### The chef_gem resource defaults to not run at compile time
+### The chef\_gem resource defaults to not run at compile time
The `compile_time true` flag may still be used to force compile time.
-### The Chef::Config[:chef_gem_compile_time] config option has been removed
+### The Chef::Config[:chef\_gem\_compile\_time] config option has been removed
In order to for community cookbooks to behave consistently across all users this optional flag has been removed.
@@ -138,22 +232,155 @@ so we have removed support for it. No specific replacement for `pip` is being
included with Chef at this time, but a `pip`-based `python_package` resource is
available in the [`poise-python`](https://github.com/poise/poise-python) cookbooks.
-### Ruby version upgraded to 2.4.1
+### Removal of run_command and popen4 APIs
-We've upgraded to the latest stable release of the Ruby programming
-language.
+All the APIs in chef/mixlib/command have been removed. They were deprecated by mixlib-shellout and the shell_out mixin API.
-### Resource can now declare a default name
+### Iconv has been removed from the ruby libraries and chef omnibus build
-The core `apt_update` resource can now be declared without any name argument, no need for `apt_update "this string doesn't matter but
-why do i have to type it?"`.
+The ruby Iconv library was replaced by the Encoding library in ruby 1.9.x and since the deprecation of ruby 1.8.7 there has been no need
+for the Iconv library but we have carried it forwards as a dependency since removing it might break some chef code out there which used
+this library. It has now been removed from the ruby build. This also removes LGPLv3 code from the omnibus build and reduces build
+headaches from porting iconv to every platform we ship chef-client on.
-This can be used by any other resource by just overriding the name property and supplying a default:
+This will also affect nokogiri, but that gem natively supports UTF-8, UTF-16LE/BE, ISO-8851-1(Latin-1), ASCII and "HTML" encodings. Users
+who really need to write something like Shift-JIS inside of XML will need to either maintain their own nokogiri installs or will need to
+convert to using UTF-8.
+
+### Deprecated cookbook metadata has been removed
+
+The `recommends`, `suggests`, `conflicts`, `replaces` and `grouping`
+metadata fields are no longer supported, and have been removed, since
+they were never used. Chef will ignore them in existing `metadata.rb`
+files, but we recommend that you remove them. This was proposed in RFC 85.
+
+### All unignored cookbook files will now be uploaded.
+
+We now treat every file under a cookbook directory as belonging to a
+cookbook, unless that file is ignored with a `chefignore` file. This is
+a change from the previous behaviour where only files in certain
+directories, such as `recipes` or `templates`, were treated as special.
+This change allows chef to support new classes of files, such as Ohai
+plugins or Inspec tests, without having to make changes to the cookbook
+format to support them.
+
+### DSL-based custom resources and providers no longer get module constants
+
+Up until now, creating a `mycook/resources/thing.rb` would create a `Chef::Resources::MycookThing` name to access the resource class object.
+This const is no longer created for resources and providers. You can access resource classes through the resolver API like:
```ruby
- property :name, String, default: ""
+Chef::Resource.resource_for_node(:mycook_thing, node)
```
-Notifications to resources with empty strings as their name is also supported via either the bare resource name (`apt_update` --
-matches what the user types in the DSL) or with empty brackets (`apt_update[]` -- matches the resource notification pattern).
+Accessing a provider class is a bit more complex, as you need a resource against which to run a resolution like so:
+
+```ruby
+Chef::ProviderResolver.new(node, find_resource!("mycook_thing[name]"), :nothing).resolve
+```
+
+### Default values for resource properties are frozen
+
+A resource declaring something like:
+
+```ruby
+property :x, default: {}
+```
+
+will now see the default value set to be immutable. This prevents cases of
+modifying the default in one resource affecting others. If you want a per-resource
+mutable default value, define it inside a `lazy{}` helper like:
+
+```ruby
+property :x, default: lazy { {} }
+```
+
+### Resources which later modify their name during creation will have their name changed on the ResourceCollection and notifications
+
+```ruby
+some_resource "name_one" do
+ name "name_two"
+end
+```
+
+The fix for sending notifications to multipackage resources involved changing the API which inserts resources into the resource collection slightly
+so that it no longer directly takes the string which is typed into the DSL but reads the (possibly coerced) name off of the resource after it is
+built. The end result is that the above resource will be named `some_resource[name_two]` instead of `some_resource[name_one]`. Note that setting
+the name (*not* the `name_property`, but actually renaming the resource) is very uncommon. The fix is to simply name the resource correctly in
+the first place (`some_resource "name_two" do ...`)
+
+### `use_inline_resources` is always enabled
+
+The `use_inline_resources` provider mode is always enabled when using the
+`action :name do ... end` syntax. You can remove the `use_inline_resources`
+line.
+
+### `knife cookbook site vendor` has been removed
+
+Please use `knife cookbook site install` instead.
+
+### `knife cookbook create` has been removed
+
+Please use `chef generate cookbook` from the ChefDK instead.
+
+### Verify commands no longer support "%{file}"
+
+Chef has always recommended `%{path}`, and `%{file}` has now been
+removed.
+
+### The `partial_search` recipe method has been removed
+
+The `partial_search` method has been fully replaced by the
+`filter_result` argument to `search`, and has now been removed.
+
+### The logger and formatter settings are more predictable
+
+The default now is the formatter. There is no more automatic switching to the logger when logging or when output
+is sent to a pipe. The logger needs to be specifically requested with `--force-logger` or it will not show up.
+
+The `--force-formatter` option does still exist, although it will probably be deprecated in the future.
+
+If your logfiles switch to the formatter, you need to include `--force-logger` for your daemonized runs.
+
+Redirecting output to a file with `chef-client > /tmp/chef.out` now captures the same output as invoking it directly on the command
+line with no redirection.
+
+### Path Sanity disabled by default and modified
+
+The chef client itself no long modifies its `ENV['PATH']` variable directly. When using the `shell_out` API now, in addition to
+setting up LANG/LANGUAGE/LC_ALL variables that API will also inject certain system paths and the ruby bindir and gemdirs into
+the PATH (or Path on Windows). The `shell_out_with_systems_locale` API still does not mangle any environment variables. During
+the Chef-13 lifecycle changes will be made to prep Chef-14 to switch so that `shell_out` by default behaves like
+`shell_out_with_systems_locale`. A new flag will get introduced to call `shell_out(..., internal: [true|false])` to either
+get the forced locale and path settings ("internal") or not. When that is introduced in Chef 13.x the default will be `true`
+(backwards-compat with 13.0) and that default will change in 14.0 to 'false'.
+
+The PATH changes have also been tweaked so that the ruby bindir and gemdir PATHS are prepended instead of appended to the PATH.
+Some system directories are still appended.
+
+Some examples of changes:
+
+* `which ruby` in 12.x will return any system ruby and fall back to the embedded ruby if using omnibus
+* `which ruby` in 13.x will return any system ruby and will not find the embedded ruby if using omnibus
+* `shell_out_with_systems_locale("which ruby")` behaves the same as `which ruby` above
+* `shell_out("which ruby")` in 12.x will return any system ruby and fall back to the embedded ruby if using omnibus
+* `shell_out("which ruby")` in 13.x will always return the omnibus ruby first (but will find the system ruby if not using omnibus)
+
+The PATH in `shell_out` can also be overridden:
+
+* `shell_out("which ruby", env: { "PATH" => nil })` - behaves like shell_out_with_systems_locale()
+* `shell_out("which ruby", env: { "PATH" => [...include PATH string here...] })` - set it arbitrarily however you need
+
+Since most providers which launch custom user commands use `shell_out_with_systems_locale` (service, execute, script, etc) the behavior
+will be that those commands that used to be having embedded omnibus paths injected into them no longer will. Generally this will
+fix more problems than it solves, but may causes issues for some use cases.
+
+### Default guard clauses (`not_if`/`only_if`) do not change the PATH or other env vars
+
+The implementation switched to `shell_out_with_systems_locale` to match `execute` resource, etc.
+
+### Chef Client will now exit using the RFC062 defined exit codes
+
+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.
diff --git a/VERSION b/VERSION
index bb76221f15..61dc2d245c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-13.0.79 \ No newline at end of file
+13.0.118 \ No newline at end of file
diff --git a/acceptance/Gemfile.lock b/acceptance/Gemfile.lock
index dfb3e68b67..eb139cc225 100644
--- a/acceptance/Gemfile.lock
+++ b/acceptance/Gemfile.lock
@@ -12,13 +12,13 @@ GEM
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
artifactory (2.8.1)
- aws-sdk (2.8.14)
- aws-sdk-resources (= 2.8.14)
- aws-sdk-core (2.8.14)
+ aws-sdk (2.9.1)
+ aws-sdk-resources (= 2.9.1)
+ aws-sdk-core (2.9.1)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-resources (2.8.14)
- aws-sdk-core (= 2.8.14)
+ aws-sdk-resources (2.9.1)
+ aws-sdk-core (= 2.9.1)
aws-sigv4 (1.0.0)
berkshelf (5.6.4)
addressable (~> 2.3, >= 2.3.4)
diff --git a/acceptance/data-collector/.acceptance/data-collector-test/metadata.rb b/acceptance/data-collector/.acceptance/data-collector-test/metadata.rb
index dbd376aa83..34402c8af1 100644
--- a/acceptance/data-collector/.acceptance/data-collector-test/metadata.rb
+++ b/acceptance/data-collector/.acceptance/data-collector-test/metadata.rb
@@ -1,7 +1,7 @@
name 'data-collector-test'
maintainer 'Adam Leff'
maintainer_email 'adamleff@chef.io'
-license 'Apache 2.0'
+license 'Apache-2.0'
description 'Installs/Configures data-collector-test'
long_description 'Installs/Configures data-collector-test'
version '0.1.0'
diff --git a/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb b/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb
index 59c1f8d21b..040fbcbcca 100644
--- a/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb
+++ b/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb
@@ -108,6 +108,8 @@ shared_examples_for "run_converge.success payload check" do
node
node_name
organization_name
+ policy_name
+ policy_group
resources
run_id
run_list
@@ -145,6 +147,8 @@ shared_examples_for "run_converge.failure payload check" do
node
node_name
organization_name
+ policy_name
+ policy_group
resources
run_id
run_list
diff --git a/appveyor.yml b/appveyor.yml
index bb15c065a7..c4d7dfcffc 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -15,6 +15,7 @@ skip_tags: true
branches:
only:
- master
+ - chef-12
install:
- systeminfo
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb
index 9166437101..0666dd869d 100644
--- a/chef-config/lib/chef-config/config.rb
+++ b/chef-config/lib/chef-config/config.rb
@@ -250,7 +250,7 @@ module ChefConfig
default(:policy_path) { derive_path_from_chef_repo_path("policies") }
# Turn on "path sanity" by default. See also: http://wiki.opscode.com/display/chef/User+Environment+PATH+Sanity
- default :enforce_path_sanity, true
+ default :enforce_path_sanity, false
# Formatted Chef Client output is a beta feature, disabled by default:
default :formatter, "null"
@@ -450,6 +450,10 @@ module ChefConfig
# most of our testing scenarios)
default :minimal_ohai, false
+ # When consuming Ohai plugins from cookbook segments, we place those plugins in this directory.
+ # Subsequent chef client runs will wipe and re-populate the directory to ensure cleanliness
+ default(:ohai_segment_plugin_path) { PathHelper.join(config_dir, "ohai", "cookbook_plugins") }
+
###
# Policyfile Settings
#
@@ -641,11 +645,10 @@ module ChefConfig
# generation (server generates client keys).
default(:local_key_generation) { true }
- # Zypper package provider gpg checks. Set to true to enable package
- # gpg signature checking. This will be default in the
- # future. Setting to false disables the warnings.
- # Leaving this set to nil or false is a security hazard!
- default :zypper_check_gpg, nil
+ # Zypper package provider gpg checks. Set to false to disable package
+ # gpg signature checking globally. This will warn you that it is a
+ # bad thing to do.
+ default :zypper_check_gpg, true
# Report Handlers
default :report_handlers, []
@@ -1051,7 +1054,8 @@ module ChefConfig
# break Chef community cookbooks and is very highly discouraged.
default :ruby_encoding, Encoding::UTF_8
- default :rubygems_url, "https://rubygems.org"
+ # can be set to a string or array of strings for URIs to set as rubygems sources
+ default :rubygems_url, "https://www.rubygems.org"
# If installed via an omnibus installer, this gives the path to the
# "embedded" directory which contains all of the software packaged with
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index 284c5e6da0..e5105b657e 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 = "13.0.79"
+ VERSION = "13.0.118"
end
#
diff --git a/chef.gemspec b/chef.gemspec
index a44c882089..93bfd26ea6 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -32,11 +32,12 @@ 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", ">= 4.8"
+ s.add_dependency "chef-zero", ">= 13.0"
s.add_dependency "plist", "~> 3.2"
s.add_dependency "iniparse", "~> 1.4"
s.add_dependency "addressable"
+ s.add_dependency "iso8601", "~> 0.9.1"
# Audit mode requires these, so they are non-developmental dependencies now
%w{rspec-core rspec-expectations rspec-mocks}.each { |gem| s.add_dependency gem, "~> 3.5" }
diff --git a/kitchen-tests/.kitchen.travis.yml b/kitchen-tests/.kitchen.travis.yml
index 6a66daffe6..3dcc5c64a7 100644
--- a/kitchen-tests/.kitchen.travis.yml
+++ b/kitchen-tests/.kitchen.travis.yml
@@ -83,14 +83,6 @@ platforms:
- RUN yum makecache
- RUN sed -i -e "s/Defaults.*requiretty.*/Defaults !requiretty/g" /etc/sudoers
-- name: ubuntu-12.04
- driver:
- image: ubuntu-upstart:12.04
- pid_one_command: /sbin/init
- intermediate_instructions:
- - RUN /usr/bin/apt-get update
- - RUN /usr/bin/apt-get -y install zlib1g-dev sudo net-tools wget ca-certificates
-
- name: ubuntu-14.04
driver:
image: ubuntu-upstart:14.04
diff --git a/kitchen-tests/.kitchen.yml b/kitchen-tests/.kitchen.yml
index 33841b0b94..87981781db 100644
--- a/kitchen-tests/.kitchen.yml
+++ b/kitchen-tests/.kitchen.yml
@@ -22,7 +22,6 @@ provisioner:
diff_disabled: true
platforms:
- - name: ubuntu-12.04
- name: ubuntu-14.04
- name: ubuntu-16.04
- name: centos-7.2
diff --git a/kitchen-tests/Berksfile b/kitchen-tests/Berksfile
index 09e4cea33a..9a2df463fc 100644
--- a/kitchen-tests/Berksfile
+++ b/kitchen-tests/Berksfile
@@ -7,7 +7,8 @@ cookbook "php", "~> 1.5.0"
cookbook "resolver", github: "chef-cookbooks/resolver"
-cookbook "awesome_customers_ubuntu_wrapper", path: "cookbooks/awesome_customers_ubuntu_wrapper"
-cookbook "awesome_customers_ubuntu", github: "lamont-granquist/awesome_customers_ubuntu", branch: "lcg/bump-mysql-version"
-cookbook "awesome_customers_rhel_wrapper", path: "cookbooks/awesome_customers_rhel_wrapper"
-cookbook "awesome_customers_rhel", github: "lamont-granquist/awesome_customers_rhel", branch: "lcg/bump-mysql-version"
+# Disabled pending updating these test cases for Chef 13.
+# cookbook "awesome_customers_ubuntu_wrapper", path: "cookbooks/awesome_customers_ubuntu_wrapper"
+# cookbook "awesome_customers_ubuntu", github: "lamont-granquist/awesome_customers_ubuntu", branch: "lcg/bump-mysql-version"
+# cookbook "awesome_customers_rhel_wrapper", path: "cookbooks/awesome_customers_rhel_wrapper"
+# cookbook "awesome_customers_rhel", github: "lamont-granquist/awesome_customers_rhel", branch: "lcg/bump-mysql-version"
diff --git a/kitchen-tests/Berksfile.lock b/kitchen-tests/Berksfile.lock
index 620c23e5ba..3d6e8d15c0 100644
--- a/kitchen-tests/Berksfile.lock
+++ b/kitchen-tests/Berksfile.lock
@@ -1,16 +1,4 @@
DEPENDENCIES
- awesome_customers_rhel
- git: https://github.com/lamont-granquist/awesome_customers_rhel.git
- revision: ed730957b1b75c8701c708e2deb0740ca8325322
- branch: lcg/bump-mysql-version
- awesome_customers_rhel_wrapper
- path: cookbooks/awesome_customers_rhel_wrapper
- awesome_customers_ubuntu
- git: https://github.com/lamont-granquist/awesome_customers_ubuntu.git
- revision: 9d40958413d0ed1ef1e68c74d41895158c724964
- branch: lcg/bump-mysql-version
- awesome_customers_ubuntu_wrapper
- path: cookbooks/awesome_customers_ubuntu_wrapper
base
path: cookbooks/base
php (~> 1.5.0)
@@ -19,26 +7,7 @@ DEPENDENCIES
revision: 4ab8cb0dfee3696fb8a1e4398e95bff9f33fd6ab
GRAPH
- apt (4.0.2)
- compat_resource (>= 12.10)
- awesome_customers_rhel (0.1.0)
- database (~> 6.0)
- firewall (~> 2.5)
- httpd (~> 0.4)
- mysql (~> 8.0)
- mysql2_chef_gem (~> 1.1)
- selinux (~> 0.9)
- awesome_customers_rhel_wrapper (0.1.0)
- awesome_customers_rhel (>= 0.0.0)
- awesome_customers_ubuntu (0.1.0)
- apt (~> 4.0)
- database (~> 6.0)
- firewall (~> 2.5)
- httpd (~> 0.4)
- mysql (~> 8.0)
- mysql2_chef_gem (~> 1.1)
- awesome_customers_ubuntu_wrapper (0.1.0)
- awesome_customers_ubuntu (>= 0.0.0)
+ apt (6.0.1)
base (0.1.0)
apt (>= 0.0.0)
build-essential (>= 0.0.0)
@@ -57,48 +26,29 @@ GRAPH
build-essential (8.0.0)
mingw (>= 1.1)
seven_zip (>= 0.0.0)
- chef-client (7.2.0)
+ chef-client (8.0.0)
cron (>= 1.7.0)
logrotate (>= 1.9.0)
windows (>= 1.42.0)
- chef-sugar (3.4.0)
chef_hostname (0.5.0)
compat_resource (12.16.3)
cron (4.1.0)
compat_resource (>= 0.0.0)
- database (6.1.1)
- postgresql (>= 1.0.0)
- firewall (2.5.4)
- chef-sugar (>= 0.0.0)
- httpd (0.4.5)
- compat_resource (>= 12.16.3)
iis (5.1.0)
windows (>= 2.0)
- inifile_chef_gem (0.1.0)
- build-essential (>= 0.0.0)
- iptables (4.0.0)
+ iptables (4.0.1)
logrotate (2.1.0)
compat_resource (>= 0.0.0)
- mariadb (1.3.0)
- apt (>= 0.0.0)
- yum (>= 0.0.0)
- yum-epel (>= 0.0.0)
- yum-scl (>= 0.0.0)
mingw (2.0.0)
seven_zip (>= 0.0.0)
multipackage (4.0.0)
compat_resource (>= 0.0.0)
- mysql (8.3.0)
- mysql2_chef_gem (1.1.0)
- build-essential (>= 0.0.0)
- mariadb (>= 0.0.0)
- mysql (>= 6.0)
+ mysql (8.3.1)
nscd (5.0.0)
ntp (3.3.1)
ohai (5.0.2)
- openssh (2.1.1)
+ openssh (2.2.0)
iptables (>= 1.0)
- openssl (7.0.1)
php (1.5.0)
build-essential (>= 0.0.0)
iis (>= 0.0.0)
@@ -106,25 +56,17 @@ GRAPH
windows (>= 0.0.0)
xml (>= 0.0.0)
yum-epel (>= 0.0.0)
- postgresql (6.1.1)
- build-essential (>= 2.0.0)
- compat_resource (>= 12.16.3)
- openssl (>= 4.0)
resolver (2.0.1)
- selinux (0.9.0)
+ selinux (1.0.3)
seven_zip (2.0.2)
windows (>= 1.2.2)
sudo (3.3.1)
ubuntu (2.0.1)
apt (>= 0.0.0)
users (4.0.3)
- windows (3.0.3)
+ windows (3.0.4)
ohai (>= 4.0.0)
xml (3.1.1)
build-essential (>= 0.0.0)
- yum (5.0.0)
yum-epel (2.1.1)
compat_resource (>= 12.16.3)
- yum-scl (0.2.0)
- inifile_chef_gem (>= 0.0.0)
- yum (>= 0.0.0)
diff --git a/kitchen-tests/Gemfile.lock b/kitchen-tests/Gemfile.lock
index a9981abe91..8881c6b839 100644
--- a/kitchen-tests/Gemfile.lock
+++ b/kitchen-tests/Gemfile.lock
@@ -1,16 +1,16 @@
GEM
remote: https://rubygems.org/
specs:
- addressable (2.5.0)
+ addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
artifactory (2.8.1)
- aws-sdk (2.8.13)
- aws-sdk-resources (= 2.8.13)
- aws-sdk-core (2.8.13)
+ aws-sdk (2.9.1)
+ aws-sdk-resources (= 2.9.1)
+ aws-sdk-core (2.9.1)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-resources (2.8.13)
- aws-sdk-core (= 2.8.13)
+ aws-sdk-resources (2.9.1)
+ aws-sdk-core (= 2.9.1)
aws-sigv4 (1.0.0)
berkshelf (5.6.4)
addressable (~> 2.3, >= 2.3.4)
@@ -73,7 +73,8 @@ GEM
hitimes (1.2.4)
hitimes (1.2.4-x86-mingw32)
httpclient (2.8.3)
- inspec (1.17.0)
+ inspec (1.18.0)
+ addressable (~> 2.5)
faraday (>= 0.9.0)
hashie (~> 3.4)
json (>= 1.8, < 3.0)
@@ -113,7 +114,7 @@ GEM
little-plugger (~> 1.1)
multi_json (~> 1.10)
method_source (0.8.2)
- mini_portile2 (2.1.0)
+ mini_portile (0.6.2)
minitar (0.6.1)
mixlib-archive (0.4.1)
mixlib-log
@@ -140,10 +141,10 @@ GEM
net-ssh-gateway (1.3.0)
net-ssh (>= 2.6.5)
nio4r (2.0.0)
- nokogiri (1.7.1)
- mini_portile2 (~> 2.1.0)
- nokogiri (1.7.1-x86-mingw32)
- mini_portile2 (~> 2.1.0)
+ nokogiri (1.6.6.4)
+ mini_portile (~> 0.6.0)
+ nokogiri (1.6.6.4-x86-mingw32)
+ mini_portile (~> 0.6.0)
nori (2.6.0)
octokit (4.6.2)
sawyer (~> 0.8.0, >= 0.5.3)
@@ -203,7 +204,7 @@ GEM
solve (3.1.0)
molinillo (>= 0.5)
semverse (>= 1.1, < 3.0)
- sslshake (1.0.13)
+ sslshake (1.1.0)
test-kitchen (1.16.0)
mixlib-install (>= 1.2, < 3.0)
mixlib-shellout (>= 1.2, < 3.0)
@@ -217,7 +218,7 @@ GEM
hitimes
toml (0.1.2)
parslet (~> 1.5.0)
- train (0.22.1)
+ train (0.23.0)
docker-api (~> 1.26)
json (>= 1.8, < 3.0)
mixlib-shellout (~> 2.0)
diff --git a/kitchen-tests/cookbooks/audit_test/metadata.rb b/kitchen-tests/cookbooks/audit_test/metadata.rb
index 3fbda5dbe1..2b34ce28d0 100644
--- a/kitchen-tests/cookbooks/audit_test/metadata.rb
+++ b/kitchen-tests/cookbooks/audit_test/metadata.rb
@@ -1,7 +1,7 @@
name "audit_test"
maintainer "The Authors"
maintainer_email "you@example.com"
-license "all_rights"
+license "Apache-2.0"
description "Installs/Configures audit_test"
long_description "Installs/Configures audit_test"
version "0.1.0"
diff --git a/kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/metadata.rb b/kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/metadata.rb
index 641f2f91e3..49dbb50869 100644
--- a/kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/metadata.rb
+++ b/kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/metadata.rb
@@ -1,7 +1,7 @@
name "awesome_customers_rhel_wrapper"
maintainer "The Authors"
maintainer_email "you@example.com"
-license "all_rights"
+license "Apache-2.0"
description "Installs/Configures awesome_customers_rhel"
long_description "Installs/Configures awesome_customers_rhel"
version "0.1.0"
diff --git a/kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/recipes/default.rb b/kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/recipes/default.rb
index 058ee61617..c58db5fe29 100644
--- a/kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/recipes/default.rb
+++ b/kitchen-tests/cookbooks/awesome_customers_rhel_wrapper/recipes/default.rb
@@ -1,6 +1,8 @@
#
-# Cookbook Name:: awesome_customers_rhel
+# Cookbook:: awesome_customers_rhel
# Recipe:: default
#
-# Copyright (c) 2016 The Authors, All Rights Reserved.
+# Copyright:: 2014-2017, Chef Software, Inc.
+#
+
include_recipe "awesome_customers_rhel::default"
diff --git a/kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/metadata.rb b/kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/metadata.rb
index 429fce2f64..d07a2c2c13 100644
--- a/kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/metadata.rb
+++ b/kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/metadata.rb
@@ -1,7 +1,7 @@
name "awesome_customers_ubuntu_wrapper"
maintainer "The Authors"
maintainer_email "you@example.com"
-license "all_rights"
+license "Apache-2.0"
description "Installs/Configures awesome_customers_ubuntu"
long_description "Installs/Configures awesome_customers_ubuntu"
version "0.1.0"
diff --git a/kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/recipes/default.rb b/kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/recipes/default.rb
index 93012d295f..f6fd388f16 100644
--- a/kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/recipes/default.rb
+++ b/kitchen-tests/cookbooks/awesome_customers_ubuntu_wrapper/recipes/default.rb
@@ -1,6 +1,8 @@
#
-# Cookbook Name:: awesome_customers_ubuntu
+# Cookbook:: awesome_customers_ubuntu
# Recipe:: default
#
-# Copyright (c) 2016 The Authors, All Rights Reserved.
+# Copyright:: 2016-2017, Chef Software, Inc.
+#
+
include_recipe "awesome_customers_ubuntu::default"
diff --git a/kitchen-tests/cookbooks/base/metadata.rb b/kitchen-tests/cookbooks/base/metadata.rb
index 32ea03916f..d29665d598 100644
--- a/kitchen-tests/cookbooks/base/metadata.rb
+++ b/kitchen-tests/cookbooks/base/metadata.rb
@@ -1,7 +1,7 @@
name "base"
maintainer ""
maintainer_email ""
-license ""
+license "Apache-2.0"
description "Installs/Configures base"
long_description "Installs/Configures base"
version "0.1.0"
diff --git a/kitchen-tests/cookbooks/base/recipes/default.rb b/kitchen-tests/cookbooks/base/recipes/default.rb
index c25673bef5..d8dbb9fe41 100644
--- a/kitchen-tests/cookbooks/base/recipes/default.rb
+++ b/kitchen-tests/cookbooks/base/recipes/default.rb
@@ -1,8 +1,8 @@
#
-# Cookbook Name:: webapp
+# Cookbook:: webapp
# Recipe:: default
#
-# Copyright (C) 2014
+# Copyright:: 2014-2017, Chef Software, Inc.
#
hostname "chef-travis-ci.chef.io"
diff --git a/kitchen-tests/cookbooks/base/recipes/packages.rb b/kitchen-tests/cookbooks/base/recipes/packages.rb
index c4457e5945..bb5fa7bb71 100644
--- a/kitchen-tests/cookbooks/base/recipes/packages.rb
+++ b/kitchen-tests/cookbooks/base/recipes/packages.rb
@@ -1,3 +1,9 @@
+#
+# Cookbook:: webapp
+# Recipe:: packages
+#
+# Copyright:: 2014-2017, Chef Software, Inc.
+#
# this is just a list of package that exist on every O/S we test, and often aren't installed by default. you don't
# have to get too clever here, you can delete packages if they don't exist everywhere we test.
diff --git a/kitchen-tests/cookbooks/base/recipes/tests.rb b/kitchen-tests/cookbooks/base/recipes/tests.rb
index 9d9d813865..8b90b48c5d 100644
--- a/kitchen-tests/cookbooks/base/recipes/tests.rb
+++ b/kitchen-tests/cookbooks/base/recipes/tests.rb
@@ -1,8 +1,8 @@
#
-# Cookbook Name:: webapp
-# Recipe:: default
+# Cookbook:: webapp
+# Recipe:: tests
#
-# Copyright (C) 2014
+# Copyright:: 2014-2017, Chef Software, Inc.
#
#
diff --git a/kitchen-tests/cookbooks/webapp/metadata.rb b/kitchen-tests/cookbooks/webapp/metadata.rb
index 5124aa4f6f..f560159fd8 100644
--- a/kitchen-tests/cookbooks/webapp/metadata.rb
+++ b/kitchen-tests/cookbooks/webapp/metadata.rb
@@ -1,7 +1,7 @@
name "webapp"
maintainer ""
maintainer_email ""
-license ""
+license "Apache-2.0"
description "Installs/Configures webapp"
long_description "Installs/Configures webapp"
version "0.1.0"
diff --git a/kitchen-tests/cookbooks/webapp/templates/default/index.html.erb b/kitchen-tests/cookbooks/webapp/templates/index.html.erb
index 6da0629b9e..6da0629b9e 100644
--- a/kitchen-tests/cookbooks/webapp/templates/default/index.html.erb
+++ b/kitchen-tests/cookbooks/webapp/templates/index.html.erb
diff --git a/kitchen-tests/cookbooks/webapp/templates/default/index.php.erb b/kitchen-tests/cookbooks/webapp/templates/index.php.erb
index b08b076614..b08b076614 100644
--- a/kitchen-tests/cookbooks/webapp/templates/default/index.php.erb
+++ b/kitchen-tests/cookbooks/webapp/templates/index.php.erb
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index 86078300c2..096ce9c392 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -48,6 +48,7 @@ class Chef
configure_chef
configure_logging
configure_encoding
+ emit_warnings
end
# Get this party started
@@ -79,6 +80,10 @@ class Chef
end
end
+ def emit_warnings
+ Chef::Log.warn "Chef::Config[:zypper_check_gpg] is set to false which disables security checking on zypper packages" unless Chef::Config[:zypper_check_gpg]
+ end
+
# Parse configuration (options and config file)
def configure_chef
parse_options
@@ -139,16 +144,9 @@ class Chef
# unattended, the `force_formatter` option is provided.
#
# === Auto Log Level
- # When `log_level` is set to `:auto` (default), the log level will be `:warn`
- # when the primary output mode is an output formatter (see
- # +using_output_formatter?+) and `:info` otherwise.
+ # The `log_level` of `:auto` means `:warn` in the formatter and `:info` in
+ # the logger.
#
- # === Automatic STDOUT Logging
- # When `force_logger` is configured (e.g., Chef 10 mode), a second logger
- # with output on STDOUT is added when running in a console (STDOUT is a tty)
- # and the configured log_location isn't STDOUT. This accounts for the case
- # that a user has configured a log_location in client.rb, but is running
- # chef-client by hand to troubleshoot a problem.
def configure_logging
configure_log_location
Chef::Log.init(MonoLogger.new(Chef::Config[:log_location]))
@@ -175,22 +173,21 @@ class Chef
end
end
+ # Based on config and whether or not STDOUT is a tty, should we setup a
+ # secondary logger for stdout?
+ def want_additional_logger?
+ ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && !Chef::Config[:daemonize]
+ end
+
def configure_stdout_logger
stdout_logger = MonoLogger.new(STDOUT)
stdout_logger.formatter = Chef::Log.logger.formatter
Chef::Log.loggers << stdout_logger
end
- # Based on config and whether or not STDOUT is a tty, should we setup a
- # secondary logger for stdout?
- def want_additional_logger?
- ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && (!Chef::Config[:daemonize]) && (Chef::Config[:force_logger])
- end
-
- # Use of output formatters is assumed if `force_formatter` is set or if
- # `force_logger` is not set and STDOUT is to a console (tty)
+ # Use of output formatters is assumed if `force_formatter` is set or if `force_logger` is not set
def using_output_formatter?
- Chef::Config[:force_formatter] || (!Chef::Config[:force_logger] && STDOUT.tty?)
+ Chef::Config[:force_formatter] || !Chef::Config[:force_logger]
end
def auto_log_level?
diff --git a/lib/chef/application/exit_code.rb b/lib/chef/application/exit_code.rb
index 610a356a7c..917aa16e62 100644
--- a/lib/chef/application/exit_code.rb
+++ b/lib/chef/application/exit_code.rb
@@ -45,47 +45,17 @@ class Chef
class << self
def normalize_exit_code(exit_code = nil)
- if normalization_not_configured?
- normalize_legacy_exit_code_with_warning(exit_code)
- elsif normalization_disabled?
- normalize_legacy_exit_code(exit_code)
+ normalized_exit_code = normalize_legacy_exit_code(exit_code)
+ if valid_exit_codes.include? normalized_exit_code
+ normalized_exit_code
else
- normalize_exit_code_to_rfc(exit_code)
+ Chef::Log.warn(non_standard_exit_code_warning(normalized_exit_code))
+ VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE]
end
end
- def enforce_rfc_062_exit_codes?
- !normalization_disabled? && !normalization_not_configured?
- end
-
- def notify_reboot_exit_code_deprecation
- return if normalization_disabled?
- notify_on_deprecation(reboot_deprecation_warning)
- end
-
- def notify_deprecated_exit_code
- return if normalization_disabled?
- notify_on_deprecation(deprecation_warning)
- end
-
private
- def normalization_disabled?
- Chef::Config[:exit_status] == :disabled
- end
-
- def normalization_not_configured?
- Chef::Config[:exit_status].nil?
- end
-
- def normalize_legacy_exit_code_with_warning(exit_code)
- normalized_exit_code = normalize_legacy_exit_code(exit_code)
- unless valid_exit_codes.include? normalized_exit_code
- notify_on_deprecation(deprecation_warning)
- end
- normalized_exit_code
- end
-
def normalize_legacy_exit_code(exit_code)
case exit_code
when Integer
@@ -93,15 +63,6 @@ class Chef
when Exception
lookup_exit_code_by_exception(exit_code)
else
- default_exit_code
- end
- end
-
- def normalize_exit_code_to_rfc(exit_code)
- normalized_exit_code = normalize_legacy_exit_code_with_warning(exit_code)
- if valid_exit_codes.include? normalized_exit_code
- normalized_exit_code
- else
VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE]
end
end
@@ -111,15 +72,6 @@ class Chef
VALID_RFC_062_EXIT_CODES[:SIGINT_RECEIVED]
elsif sigterm_received?(exception)
VALID_RFC_062_EXIT_CODES[:SIGTERM_RECEIVED]
- elsif normalization_disabled? || normalization_not_configured?
- if legacy_exit_code?(exception)
- # We have lots of "Chef::Application.fatal!('', 2)
- # This maintains that behavior at initial introduction
- # and when the RFC exit_status compliance is disabled.
- VALID_RFC_062_EXIT_CODES[:SIGINT_RECEIVED]
- else
- VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE]
- end
elsif reboot_scheduled?(exception)
VALID_RFC_062_EXIT_CODES[:REBOOT_SCHEDULED]
elsif reboot_needed?(exception)
@@ -135,12 +87,6 @@ class Chef
end
end
- def legacy_exit_code?(exception)
- resolve_exception_array(exception).any? do |e|
- e.is_a? Chef::Exceptions::DeprecatedExitCode
- end
- end
-
def reboot_scheduled?(exception)
resolve_exception_array(exception).any? do |e|
e.is_a? Chef::Exceptions::Reboot
@@ -204,26 +150,11 @@ class Chef
# the current exit code assignment.
end
- def deprecation_warning
- "Chef RFC 062 (https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md) defines the" \
+ def non_standard_exit_code_warning(exit_code)
+ "Chef attempted to exit with a non-standard exit code of #{exit_code}." \
+ " Chef RFC 062 (https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md) defines the" \
" exit codes that should be used with Chef. Chef::Application::ExitCode defines valid exit codes" \
- " In a future release, non-standard exit codes will be redefined as" \
- " GENERIC_FAILURE unless `exit_status` is set to `:disabled` in your client.rb."
- end
-
- def reboot_deprecation_warning
- "Per RFC 062 (https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md)" \
- ", when a reboot is requested Chef Client will exit with an exit code of 35, REBOOT_SCHEDULED." \
- " To maintain the current behavior (an exit code of 0), you will need to set `exit_status` to" \
- " `:disabled` in your client.rb"
- end
-
- def default_exit_code
- if normalization_disabled? || normalization_not_configured?
- DEPRECATED_RFC_062_EXIT_CODES[:DEPRECATED_FAILURE]
- else
- VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE]
- end
+ " Non-standard exit codes are redefined as GENERIC_FAILURE."
end
end
diff --git a/lib/chef/application/windows_service.rb b/lib/chef/application/windows_service.rb
index 7bc68a586d..fa4b3fd27e 100644
--- a/lib/chef/application/windows_service.rb
+++ b/lib/chef/application/windows_service.rb
@@ -1,6 +1,6 @@
#
# Author:: Christopher Maier (<maier@lambda.local>)
-# Copyright:: Copyright 2011-2016, Chef Software, Inc.
+# Copyright:: Copyright 2011-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -256,13 +256,13 @@ class Chef
# Based on config and whether or not STDOUT is a tty, should we setup a
# secondary logger for stdout?
def want_additional_logger?
- ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && (!Chef::Config[:daemonize]) && (Chef::Config[:force_logger])
+ ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && !Chef::Config[:daemonize]
end
# Use of output formatters is assumed if `force_formatter` is set or if
- # `force_logger` is not set and STDOUT is to a console (tty)
+ # `force_logger` is not set
def using_output_formatter?
- Chef::Config[:force_formatter] || (!Chef::Config[:force_logger] && STDOUT.tty?)
+ Chef::Config[:force_formatter] || !Chef::Config[:force_logger]
end
def auto_log_level?
@@ -318,11 +318,11 @@ class Chef
Chef::Config.merge!(config)
rescue SocketError
- Chef::Application.fatal!("Error getting config file #{Chef::Config[:config_file]}", Chef::Exceptions::DeprecatedExitCode.new)
+ Chef::Application.fatal!("Error getting config file #{Chef::Config[:config_file]}")
rescue Chef::Exceptions::ConfigurationError => error
- Chef::Application.fatal!("Error processing config file #{Chef::Config[:config_file]} with error #{error.message}", Chef::Exceptions::DeprecatedExitCode.new)
+ Chef::Application.fatal!("Error processing config file #{Chef::Config[:config_file]} with error #{error.message}")
rescue Exception => error
- Chef::Application.fatal!("Unknown error processing config file #{Chef::Config[:config_file]} with error #{error.message}", Chef::Exceptions::DeprecatedExitCode.new)
+ Chef::Application.fatal!("Unknown error processing config file #{Chef::Config[:config_file]} with error #{error.message}")
end
end
diff --git a/lib/chef/chef_fs/chef_fs_data_store.rb b/lib/chef/chef_fs/chef_fs_data_store.rb
index 46fe5c4dd3..0c8f12f1be 100644
--- a/lib/chef/chef_fs/chef_fs_data_store.rb
+++ b/lib/chef/chef_fs/chef_fs_data_store.rb
@@ -768,7 +768,7 @@ class Chef
end
elsif path.length == 2 && path[0] != "cookbooks"
- path[1] = path[1][0..-6]
+ path[1] = path[1].gsub(/\.(rb|json)/, "")
end
path
diff --git a/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb b/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb
index 5030a0733f..63ce71ef40 100644
--- a/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb
@@ -103,11 +103,11 @@ class Chef
end
def get_json(path)
- Chef::ServerAPI.new(chef_server_url, :client_name => chef_username, :signing_key_filename => chef_private_key, :api_version => "0").get(path)
+ chef_rest.get(path)
end
def chef_rest
- Chef::ServerAPI.new(chef_server_url, :client_name => chef_username, :signing_key_filename => chef_private_key)
+ Chef::ServerAPI.new(chef_server_url, :client_name => chef_username, :signing_key_filename => chef_private_key, :api_version => "0")
end
def api_path
diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbook_artifacts_dir.rb b/lib/chef/chef_fs/file_system/chef_server/cookbook_artifacts_dir.rb
index 0b82a64a0a..e4df7858a7 100644
--- a/lib/chef/chef_fs/file_system/chef_server/cookbook_artifacts_dir.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/cookbook_artifacts_dir.rb
@@ -56,7 +56,7 @@ class Chef
# to make this work. So instead, we make a temporary cookbook
# symlinking back to real cookbook, and upload the proxy.
def upload_cookbook(other, options)
- cookbook_name, dash, identifier = other.name.rpartition("-")
+ cookbook_name, _, identifier = other.name.rpartition("-")
Dir.mktmpdir do |temp_cookbooks_path|
proxy_cookbook_path = "#{temp_cookbooks_path}/#{cookbook_name}"
@@ -73,7 +73,7 @@ class Chef
cookbook_to_upload.freeze_version if options[:freeze]
# Instantiate a new uploader based on the proxy loader
- uploader = Chef::CookbookUploader.new(cookbook_to_upload, force: options[:force], rest: root.chef_rest, policy_mode: true)
+ uploader = Chef::CookbookUploader.new(cookbook_to_upload, force: options[:force], rest: chef_rest, policy_mode: true)
with_actual_cookbooks_dir(temp_cookbooks_path) do
uploader.upload_cookbooks
@@ -92,6 +92,10 @@ class Chef
end
end
+ def chef_rest
+ Chef::ServerAPI.new(root.chef_rest.url, root.chef_rest.options.merge(version_class: Chef::CookbookManifestVersions))
+ end
+
def can_have_child?(name, is_dir)
is_dir && name.include?("-")
end
diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb b/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb
index 8f5faf2183..64488ed705 100644
--- a/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb
@@ -49,18 +49,6 @@ class Chef
attr_reader :cookbook_name, :version
- COOKBOOK_SEGMENT_INFO = {
- :attributes => { :ruby_only => true },
- :definitions => { :ruby_only => true },
- :recipes => { :ruby_only => true },
- :libraries => { :recursive => true },
- :templates => { :recursive => true },
- :files => { :recursive => true },
- :resources => { :ruby_only => true, :recursive => true },
- :providers => { :ruby_only => true, :recursive => true },
- :root_files => {},
- }
-
def add_child(child)
@children << child
end
@@ -80,34 +68,29 @@ class Chef
end
def can_have_child?(name, is_dir)
- # A cookbook's root may not have directories unless they are segment directories
- return name != "root_files" && COOKBOOK_SEGMENT_INFO.keys.include?(name.to_sym) if is_dir
+ return name != "root_files" if is_dir
true
end
def children
if @children.nil?
@children = []
- manifest = chef_object.manifest
- COOKBOOK_SEGMENT_INFO.each do |segment, segment_info|
- next unless manifest.has_key?(segment)
-
- # Go through each file in the manifest for the segment, and
- # add cookbook subdirs and files for it.
- manifest[segment].each do |segment_file|
- parts = segment_file[:path].split("/")
+ manifest = chef_object.cookbook_manifest
+ manifest.by_parent_directory.each do |segment, files|
+ files.each do |file|
+ parts = file[:path].split("/")
# Get or create the path to the file
container = self
parts[0, parts.length - 1].each do |part|
old_container = container
container = old_container.children.find { |child| part == child.name }
if !container
- container = CookbookSubdir.new(part, old_container, segment_info[:ruby_only], segment_info[:recursive])
+ container = CookbookSubdir.new(part, old_container, false, true)
old_container.add_child(container)
end
end
# Create the file itself
- container.add_child(CookbookFile.new(parts[parts.length - 1], container, segment_file))
+ container.add_child(CookbookFile.new(parts[parts.length - 1], container, file))
end
end
@children = @children.sort_by { |c| c.name }
@@ -165,7 +148,11 @@ class Chef
end
def rest
- parent.rest
+ Chef::ServerAPI.new(parent.rest.url, parent.rest.options.merge(version_class: Chef::CookbookManifestVersions))
+ end
+
+ def chef_rest
+ Chef::ServerAPI.new(parent.chef_rest.url, parent.chef_rest.options.merge(version_class: Chef::CookbookManifestVersions))
end
def chef_object
@@ -187,7 +174,7 @@ class Chef
old_retry_count = Chef::Config[:http_retry_count]
begin
Chef::Config[:http_retry_count] = 0
- @chef_object ||= Chef::CookbookVersion.from_hash(root.get_json(api_path))
+ @chef_object ||= Chef::CookbookVersion.from_hash(chef_rest.get(api_path))
ensure
Chef::Config[:http_retry_count] = old_retry_count
end
diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb b/lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb
index 631562d7ef..4e8e68e364 100644
--- a/lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb
@@ -74,13 +74,17 @@ class Chef
def upload_cookbook(other, options)
cookbook_to_upload = other.chef_object
cookbook_to_upload.freeze_version if options[:freeze]
- uploader = Chef::CookbookUploader.new(cookbook_to_upload, :force => options[:force], :rest => root.chef_rest)
+ uploader = Chef::CookbookUploader.new(cookbook_to_upload, :force => options[:force], :rest => chef_rest)
with_actual_cookbooks_dir(other.parent.file_path) do
uploader.upload_cookbooks
end
end
+ def chef_rest
+ Chef::ServerAPI.new(root.chef_rest.url, root.chef_rest.options.merge(version_class: Chef::CookbookManifestVersions))
+ end
+
# Work around the fact that CookbookUploader doesn't understand chef_repo_path (yet)
def with_actual_cookbooks_dir(actual_cookbook_path)
old_cookbook_path = Chef::Config.cookbook_path
diff --git a/lib/chef/chef_fs/file_system/chef_server/versioned_cookbooks_dir.rb b/lib/chef/chef_fs/file_system/chef_server/versioned_cookbooks_dir.rb
index 172405763a..8da3718136 100644
--- a/lib/chef/chef_fs/file_system/chef_server/versioned_cookbooks_dir.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/versioned_cookbooks_dir.rb
@@ -78,7 +78,7 @@ class Chef
cookbook_to_upload.freeze_version if options[:freeze]
# Instantiate a new uploader based on the proxy loader
- uploader = Chef::CookbookUploader.new(cookbook_to_upload, :force => options[:force], :rest => root.chef_rest)
+ uploader = Chef::CookbookUploader.new(cookbook_to_upload, :force => options[:force], :rest => chef_rest)
with_actual_cookbooks_dir(temp_cookbooks_path) do
uploader.upload_cookbooks
@@ -97,6 +97,10 @@ class Chef
end
end
+ def chef_rest
+ Chef::ServerAPI.new(root.chef_rest.url, root.chef_rest.options.merge(version_class: Chef::CookbookManifestVersions))
+ end
+
def can_have_child?(name, is_dir)
is_dir && name =~ Chef::ChefFS::FileSystem::ChefServer::VersionedCookbookDir::VALID_VERSIONED_COOKBOOK_NAME
end
diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb
index 31b538b9ce..b296901dd1 100644
--- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb
+++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb
@@ -97,9 +97,9 @@ class Chef
end
def can_have_child?(name, is_dir)
- if is_dir
+ if is_dir && !%w{ root_files .. . }.include?(name)
# Only the given directories will be uploaded.
- return Chef::ChefFS::FileSystem::ChefServer::CookbookDir::COOKBOOK_SEGMENT_INFO.keys.include?(name.to_sym) && name != "root_files"
+ return true
elsif name == Chef::Cookbook::CookbookVersionLoader::UPLOADED_COOKBOOK_VERSION_FILE
return false
end
@@ -128,8 +128,7 @@ class Chef
protected
def make_child_entry(child_name)
- segment_info = Chef::ChefFS::FileSystem::ChefServer::CookbookDir::COOKBOOK_SEGMENT_INFO[child_name.to_sym] || {}
- ChefRepositoryFileSystemCookbookEntry.new(child_name, self, nil, segment_info[:ruby_only], segment_info[:recursive])
+ ChefRepositoryFileSystemCookbookEntry.new(child_name, self, nil, false, true)
end
def cookbook_version
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index b219fdfdd6..9f8a34e85e 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -280,6 +280,8 @@ class Chef
run_context = setup_run_context
+ load_required_recipe(@rest, run_context) unless Chef::Config[:solo_legacy_mode]
+
if Chef::Config[:audit_mode] != :audit_only
converge_error = converge_and_save(run_context)
end
@@ -372,7 +374,7 @@ class Chef
# @api private
def default_formatter
- if (STDOUT.tty? && !Chef::Config[:force_logger]) || Chef::Config[:force_formatter]
+ if !Chef::Config[:force_logger] || Chef::Config[:force_formatter]
[:doc]
else
[:null]
@@ -515,6 +517,49 @@ class Chef
end
#
+ # Adds a required recipe as specified by the Chef Server
+ #
+ # @return The modified run context
+ #
+ # @api private
+ #
+ # TODO: @rest doesn't appear to be used anywhere outside
+ # of client.register except for here. If it's common practice
+ # to create your own rest client, perhaps we should do that
+ # here but it seems more appropriate to reuse one that we
+ # know is already created. for ease of testing, we'll pass
+ # the existing rest client in as a parameter
+ #
+ def load_required_recipe(rest, run_context)
+ required_recipe_contents = rest.get("required_recipe")
+ Chef::Log.info("Required Recipe found, loading it")
+ Chef::FileCache.store("required_recipe", required_recipe_contents)
+ required_recipe_file = Chef::FileCache.load("required_recipe", false)
+
+ # TODO: add integration tests with resource reporting turned on
+ # (presumably requires changes to chef-zero)
+ #
+ # Chef::Recipe.new takes a cookbook name and a recipe name along
+ # with the run context. These names are eventually used in the
+ # resource reporter, and if the cookbook name cannot be found in the
+ # cookbook collection then we will fail with an exception. Cases where
+ # we currently also fail:
+ # - specific recipes
+ # - chef-apply would fail if resource reporting was enabled
+ #
+ recipe = Chef::Recipe.new(nil, nil, run_context)
+ recipe.from_file(required_recipe_file)
+ run_context
+ rescue Net::HTTPServerException => e
+ case e.response
+ when Net::HTTPNotFound
+ Chef::Log.debug("Required Recipe not configured on the server, skipping it")
+ else
+ raise
+ end
+ end
+
+ #
# The PolicyBuilder strategy for figuring out run list and cookbooks.
#
# @return [Chef::PolicyBuilder::Policyfile, Chef::PolicyBuilder::ExpandNodeObject]
diff --git a/lib/chef/config_fetcher.rb b/lib/chef/config_fetcher.rb
index ee1b64956a..e14428157c 100644
--- a/lib/chef/config_fetcher.rb
+++ b/lib/chef/config_fetcher.rb
@@ -25,7 +25,7 @@ class Chef
begin
Chef::JSONCompat.from_json(config_data)
rescue Chef::Exceptions::JSON::ParseError => error
- Chef::Application.fatal!("Could not parse the provided JSON file (#{config_location}): " + error.message, Chef::Exceptions::DeprecatedExitCode.new)
+ Chef::Application.fatal!("Could not parse the provided JSON file (#{config_location}): " + error.message)
end
end
@@ -40,15 +40,15 @@ class Chef
def fetch_remote_config
http.get("")
rescue SocketError, SystemCallError, Net::HTTPServerException => error
- Chef::Application.fatal!("Cannot fetch config '#{config_location}': '#{error.class}: #{error.message}", Chef::Exceptions::DeprecatedExitCode.new)
+ Chef::Application.fatal!("Cannot fetch config '#{config_location}': '#{error.class}: #{error.message}")
end
def read_local_config
::File.read(config_location)
rescue Errno::ENOENT
- Chef::Application.fatal!("Cannot load configuration from #{config_location}", Chef::Exceptions::DeprecatedExitCode.new)
+ Chef::Application.fatal!("Cannot load configuration from #{config_location}")
rescue Errno::EACCES
- Chef::Application.fatal!("Permissions are incorrect on #{config_location}. Please chmod a+r #{config_location}", Chef::Exceptions::DeprecatedExitCode.new)
+ Chef::Application.fatal!("Permissions are incorrect on #{config_location}. Please chmod a+r #{config_location}")
end
def config_missing?
diff --git a/lib/chef/cookbook/cookbook_version_loader.rb b/lib/chef/cookbook/cookbook_version_loader.rb
index b9de9a7482..35dac27fa5 100644
--- a/lib/chef/cookbook/cookbook_version_loader.rb
+++ b/lib/chef/cookbook/cookbook_version_loader.rb
@@ -9,15 +9,6 @@ class Chef
class Cookbook
class CookbookVersionLoader
- FILETYPES_SUBJECT_TO_IGNORE = [ :attribute_filenames,
- :definition_filenames,
- :recipe_filenames,
- :template_filenames,
- :file_filenames,
- :library_filenames,
- :resource_filenames,
- :provider_filenames]
-
UPLOADED_COOKBOOK_VERSION_FILE = ".uploaded-cookbook-version.json".freeze
attr_reader :cookbook_settings
@@ -44,16 +35,7 @@ class Chef
@relative_path = /#{Regexp.escape(@cookbook_path)}\/(.+)$/
@metadata_loaded = false
@cookbook_settings = {
- :all_files => {},
- :attribute_filenames => {},
- :definition_filenames => {},
- :recipe_filenames => {},
- :template_filenames => {},
- :file_filenames => {},
- :library_filenames => {},
- :resource_filenames => {},
- :provider_filenames => {},
- :root_filenames => {},
+ :all_files => {},
}
@metadata_filenames = []
@@ -84,16 +66,6 @@ class Chef
remove_ignored_files
- load_as(:attribute_filenames, "attributes", "*.rb")
- load_as(:definition_filenames, "definitions", "*.rb")
- load_as(:recipe_filenames, "recipes", "*.rb")
- load_recursively_as(:library_filenames, "libraries", "*")
- load_recursively_as(:template_filenames, "templates", "*")
- load_recursively_as(:file_filenames, "files", "*")
- load_recursively_as(:resource_filenames, "resources", "*.rb")
- load_recursively_as(:provider_filenames, "providers", "*.rb")
- load_root_files
-
if empty?
Chef::Log.warn "Found a directory #{cookbook_name} in the cookbook path, but it contains no cookbook files. skipping."
end
@@ -126,16 +98,6 @@ class Chef
Chef::CookbookVersion.new(cookbook_name, *cookbook_paths).tap do |c|
c.all_files = cookbook_settings[:all_files].values
- c.attribute_filenames = cookbook_settings[:attribute_filenames].values
- c.definition_filenames = cookbook_settings[:definition_filenames].values
- c.recipe_filenames = cookbook_settings[:recipe_filenames].values
- c.template_filenames = cookbook_settings[:template_filenames].values
- c.file_filenames = cookbook_settings[:file_filenames].values
- c.library_filenames = cookbook_settings[:library_filenames].values
- c.resource_filenames = cookbook_settings[:resource_filenames].values
- c.provider_filenames = cookbook_settings[:provider_filenames].values
- c.root_filenames = cookbook_settings[:root_filenames].values
- c.metadata_filenames = metadata_filenames
c.metadata = metadata
c.freeze_version if @frozen
@@ -253,51 +215,6 @@ class Chef
end
end
- def load_root_files
- select_files_by_glob(File.join(Chef::Util::PathHelper.escape_glob_dir(cookbook_path), "*"), File::FNM_DOTMATCH).each do |file|
- file = Chef::Util::PathHelper.cleanpath(file)
- next if File.directory?(file)
- next if File.basename(file) == UPLOADED_COOKBOOK_VERSION_FILE
- name = Chef::Util::PathHelper.relative_path_from(@cookbook_path, file)
- cookbook_settings[:root_filenames][name] = file
- end
- end
-
- def load_recursively_as(category, category_dir, glob)
- glob_pattern = File.join(Chef::Util::PathHelper.escape_glob_dir(cookbook_path, category_dir), "**", glob)
- select_files_by_glob(glob_pattern, File::FNM_DOTMATCH).each do |file|
- file = Chef::Util::PathHelper.cleanpath(file)
- name = Chef::Util::PathHelper.relative_path_from(@cookbook_path, file)
- cookbook_settings[category][name] = file
- end
- end
-
- def load_as(category, *path_glob)
- glob_pattern = File.join(Chef::Util::PathHelper.escape_glob_dir(cookbook_path), *path_glob)
- select_files_by_glob(glob_pattern).each do |file|
- file = Chef::Util::PathHelper.cleanpath(file)
- name = Chef::Util::PathHelper.relative_path_from(@cookbook_path, file)
- cookbook_settings[category][name] = file
- end
- end
-
- # Mimic Dir.glob inside a cookbook by running `File.fnmatch?` against
- # `cookbook_settings[:all_files]`.
- #
- # @param pattern [String] a glob string passed to `File.fnmatch?`
- # @param option [Integer] Option flag to control globbing behavior. These
- # are constants defined on `File`, such as `File::FNM_DOTMATCH`.
- # `File.fnmatch?` and `Dir.glob` only take one option argument, if you
- # need to combine options, you must `|` the constants together. To make
- # `File.fnmatch?` behave like `Dir.glob`, `File::FNM_PATHNAME` is
- # always enabled.
- def select_files_by_glob(pattern, option = 0)
- combined_opts = option | File::FNM_PATHNAME
- cookbook_settings[:all_files].values.select do |path|
- File.fnmatch?(pattern, path, combined_opts)
- end
- end
-
def remove_ignored_files
cookbook_settings[:all_files].reject! do |relative_path, full_path|
chefignore.ignored?(relative_path)
diff --git a/lib/chef/cookbook/file_system_file_vendor.rb b/lib/chef/cookbook/file_system_file_vendor.rb
index 8088ed00cd..1f43095ea3 100644
--- a/lib/chef/cookbook/file_system_file_vendor.rb
+++ b/lib/chef/cookbook/file_system_file_vendor.rb
@@ -35,7 +35,7 @@ class Chef
attr_reader :repo_paths
def initialize(manifest, *repo_paths)
- @cookbook_name = manifest[:cookbook_name]
+ @cookbook_name = manifest.name
@repo_paths = repo_paths.flatten
raise ArgumentError, "You must specify at least one repo path" if repo_paths.empty?
end
diff --git a/lib/chef/cookbook/gem_installer.rb b/lib/chef/cookbook/gem_installer.rb
index df73ce3ee4..5b1426e4e8 100644
--- a/lib/chef/cookbook/gem_installer.rb
+++ b/lib/chef/cookbook/gem_installer.rb
@@ -1,5 +1,5 @@
#--
-# Copyright:: Copyright (c) 2010-2016 Chef Software, Inc.
+# Copyright:: Copyright (c) 2010-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -36,10 +36,12 @@ class Chef
# Installs the gems into the omnibus gemset.
#
def install
- cookbook_gems = []
+ cookbook_gems = Hash.new { |h, k| h[k] = [] }
cookbook_collection.each do |cookbook_name, cookbook_version|
- cookbook_gems += cookbook_version.metadata.gems
+ cookbook_version.metadata.gems.each do |args|
+ cookbook_gems[args.first] += args[1..-1]
+ end
end
events.cookbook_gem_start(cookbook_gems)
@@ -48,9 +50,11 @@ class Chef
begin
Dir.mktmpdir("chef-gem-bundle") do |dir|
File.open("#{dir}/Gemfile", "w+") do |tf|
- tf.puts "source '#{Chef::Config[:rubygems_url]}'"
- cookbook_gems.each do |args|
- tf.puts "gem(*#{args.inspect})"
+ Array(Chef::Config[:rubygems_url] || "https://www.rubygems.org").each do |s|
+ tf.puts "source '#{s}'"
+ end
+ cookbook_gems.each do |gem_name, args|
+ tf.puts "gem(*#{([gem_name] + args).inspect})"
end
tf.close
Chef::Log.debug("generated Gemfile contents:")
diff --git a/lib/chef/cookbook/manifest_v0.rb b/lib/chef/cookbook/manifest_v0.rb
new file mode 100644
index 0000000000..fd2d62a6d4
--- /dev/null
+++ b/lib/chef/cookbook/manifest_v0.rb
@@ -0,0 +1,68 @@
+# Author:: Daniel DeLeo (<dan@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.
+
+require "chef/json_compat"
+require "chef/mixin/versioned_api"
+
+class Chef
+ class Cookbook
+ class ManifestV0
+ extend Chef::Mixin::VersionedAPI
+
+ minimum_api_version 0
+
+ COOKBOOK_SEGMENTS = %w{ resources providers recipes definitions libraries attributes files templates root_files }
+
+ def self.from_hash(hash)
+ response = Mash.new(hash)
+ response[:all_files] = COOKBOOK_SEGMENTS.inject([]) do |memo, segment|
+ next memo if hash[segment].nil? || hash[segment].empty?
+ hash[segment].each do |file|
+ file["name"] = "#{segment}/#{file["name"]}" unless segment == "root_files"
+ memo << file
+ end
+ response.delete(segment)
+ memo
+ end
+ response
+ end
+
+ def self.to_hash(manifest)
+ result = manifest.manifest.dup
+ result.delete("all_files")
+
+ files = manifest.by_parent_directory
+ files.keys.each_with_object(result) do |parent, memo|
+ if COOKBOOK_SEGMENTS.include?(parent)
+ memo[parent] ||= []
+ files[parent].each do |file|
+ file["name"] = file["name"].split("/")[1] unless parent == "root_files"
+ file.delete("full_path")
+ memo[parent] << file
+ end
+ end
+ end
+ # Ensure all segments are set to [] if they don't exist.
+ # See https://github.com/chef/chef/issues/6044
+ COOKBOOK_SEGMENTS.each do |segment|
+ result[segment] ||= []
+ end
+
+ result.merge({ "frozen?" => manifest.frozen_version?, "chef_type" => "cookbook_version" })
+ end
+ end
+ end
+end
diff --git a/lib/chef/cookbook/manifest_v2.rb b/lib/chef/cookbook/manifest_v2.rb
new file mode 100644
index 0000000000..59b5c9afb0
--- /dev/null
+++ b/lib/chef/cookbook/manifest_v2.rb
@@ -0,0 +1,41 @@
+# 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.
+
+require "chef/json_compat"
+require "chef/mixin/versioned_api"
+
+class Chef
+ class Cookbook
+ class ManifestV2
+ extend Chef::Mixin::VersionedAPI
+
+ minimum_api_version 2
+
+ def self.from_hash(hash)
+ Chef::Log.debug "processing manifest: #{hash}"
+ Mash.new hash
+ end
+
+ def self.to_hash(manifest)
+ result = manifest.manifest.dup
+ result["all_files"].map! { |file| file.delete("full_path"); file }
+ result["frozen?"] = manifest.frozen_version?
+ result["chef_type"] = "cookbook_version"
+ result.to_hash
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb
index a8ec901e97..5efadd6f62 100644
--- a/lib/chef/cookbook/metadata.rb
+++ b/lib/chef/cookbook/metadata.rb
@@ -44,13 +44,8 @@ class Chef
LICENSE = "license".freeze
PLATFORMS = "platforms".freeze
DEPENDENCIES = "dependencies".freeze
- RECOMMENDATIONS = "recommendations".freeze
- SUGGESTIONS = "suggestions".freeze
- CONFLICTING = "conflicting".freeze
PROVIDING = "providing".freeze
- REPLACING = "replacing".freeze
ATTRIBUTES = "attributes".freeze
- GROUPINGS = "groupings".freeze
RECIPES = "recipes".freeze
VERSION = "version".freeze
SOURCE_URL = "source_url".freeze
@@ -62,17 +57,12 @@ class Chef
COMPARISON_FIELDS = [ :name, :description, :long_description, :maintainer,
:maintainer_email, :license, :platforms, :dependencies,
- :recommendations, :suggestions, :conflicting, :providing,
- :replacing, :attributes, :groupings, :recipes, :version,
+ :providing, :attributes, :recipes, :version,
:source_url, :issues_url, :privacy, :chef_versions, :ohai_versions,
:gems ]
VERSION_CONSTRAINTS = { :depends => DEPENDENCIES,
- :recommends => RECOMMENDATIONS,
- :suggests => SUGGESTIONS,
- :conflicts => CONFLICTING,
:provides => PROVIDING,
- :replaces => REPLACING,
:chef_version => CHEF_VERSIONS,
:ohai_version => OHAI_VERSIONS }
@@ -81,13 +71,8 @@ class Chef
attr_reader :platforms
attr_reader :dependencies
- attr_reader :recommendations
- attr_reader :suggestions
- attr_reader :conflicting
attr_reader :providing
- attr_reader :replacing
attr_reader :attributes
- attr_reader :groupings
attr_reader :recipes
attr_reader :version
@@ -120,13 +105,8 @@ class Chef
@platforms = Mash.new
@dependencies = Mash.new
- @recommendations = Mash.new
- @suggestions = Mash.new
- @conflicting = Mash.new
@providing = Mash.new
- @replacing = Mash.new
@attributes = Mash.new
- @groupings = Mash.new
@recipes = Mash.new
@version = Version.new("0.0.0")
@source_url = ""
@@ -315,57 +295,6 @@ class Chef
@dependencies[cookbook]
end
- # Adds a recommendation for another cookbook, with version checking strings.
- #
- # === Parameters
- # cookbook<String>:: The cookbook
- # version<String>:: A version constraint of the form "OP VERSION",
- # where OP is one of < <= = > >= ~> and VERSION has
- # the form x.y.z or x.y.
- #
- # === Returns
- # versions<Array>:: Returns the list of versions for the platform
- def recommends(cookbook, *version_args)
- version = new_args_format(:recommends, cookbook, version_args)
- constraint = validate_version_constraint(:recommends, cookbook, version)
- @recommendations[cookbook] = constraint.to_s
- @recommendations[cookbook]
- end
-
- # Adds a suggestion for another cookbook, with version checking strings.
- #
- # === Parameters
- # cookbook<String>:: The cookbook
- # version<String>:: A version constraint of the form "OP VERSION",
- # where OP is one of < <= = > >= ~> and VERSION has the
- # formx.y.z or x.y.
- #
- # === Returns
- # versions<Array>:: Returns the list of versions for the platform
- def suggests(cookbook, *version_args)
- version = new_args_format(:suggests, cookbook, version_args)
- constraint = validate_version_constraint(:suggests, cookbook, version)
- @suggestions[cookbook] = constraint.to_s
- @suggestions[cookbook]
- end
-
- # Adds a conflict for another cookbook, with version checking strings.
- #
- # === Parameters
- # cookbook<String>:: The cookbook
- # version<String>:: A version constraint of the form "OP VERSION",
- # where OP is one of < <= = > >= ~> and VERSION has
- # the form x.y.z or x.y.
- #
- # === Returns
- # versions<Array>:: Returns the list of versions for the platform
- def conflicts(cookbook, *version_args)
- version = new_args_format(:conflicts, cookbook, version_args)
- constraint = validate_version_constraint(:conflicts, cookbook, version)
- @conflicting[cookbook] = constraint.to_s
- @conflicting[cookbook]
- end
-
# Adds a recipe, definition, or resource provided by this cookbook.
#
# Recipes are specified as normal
@@ -387,22 +316,6 @@ class Chef
@providing[cookbook]
end
- # Adds a cookbook that is replaced by this one, with version checking strings.
- #
- # === Parameters
- # cookbook<String>:: The cookbook we replace
- # version<String>:: A version constraint of the form "OP VERSION",
- # where OP is one of < <= = > >= ~> and VERSION has the form x.y.z or x.y.
- #
- # === Returns
- # versions<Array>:: Returns the list of versions for the platform
- def replaces(cookbook, *version_args)
- version = new_args_format(:replaces, cookbook, version_args)
- constraint = validate_version_constraint(:replaces, cookbook, version)
- @replacing[cookbook] = constraint.to_s
- @replacing[cookbook]
- end
-
# Metadata DSL to set a valid chef_version. May be declared multiple times
# with the result being 'OR'd such that if any statements match, the version
# is considered supported. Uses Gem::Requirement for its implementation.
@@ -519,18 +432,6 @@ class Chef
@attributes[name]
end
- def grouping(name, options)
- validate(
- options,
- {
- :title => { :kind_of => String },
- :description => { :kind_of => String },
- }
- )
- @groupings[name] = options
- @groupings[name]
- end
-
# Convert an Array of Gem::Dependency objects (chef_version/ohai_version) to an Array.
#
# Gem::Dependencey#to_s is not useful, and there is no #to_json defined on it or its component
@@ -575,13 +476,8 @@ class Chef
LICENSE => license,
PLATFORMS => platforms,
DEPENDENCIES => dependencies,
- RECOMMENDATIONS => recommendations,
- SUGGESTIONS => suggestions,
- CONFLICTING => conflicting,
PROVIDING => providing,
- REPLACING => replacing,
ATTRIBUTES => attributes,
- GROUPINGS => groupings,
RECIPES => recipes,
VERSION => version,
SOURCE_URL => source_url,
@@ -612,13 +508,8 @@ class Chef
@license = o[LICENSE] if o.has_key?(LICENSE)
@platforms = o[PLATFORMS] if o.has_key?(PLATFORMS)
@dependencies = handle_deprecated_constraints(o[DEPENDENCIES]) if o.has_key?(DEPENDENCIES)
- @recommendations = handle_deprecated_constraints(o[RECOMMENDATIONS]) if o.has_key?(RECOMMENDATIONS)
- @suggestions = handle_deprecated_constraints(o[SUGGESTIONS]) if o.has_key?(SUGGESTIONS)
- @conflicting = handle_deprecated_constraints(o[CONFLICTING]) if o.has_key?(CONFLICTING)
@providing = o[PROVIDING] if o.has_key?(PROVIDING)
- @replacing = handle_deprecated_constraints(o[REPLACING]) if o.has_key?(REPLACING)
@attributes = o[ATTRIBUTES] if o.has_key?(ATTRIBUTES)
- @groupings = o[GROUPINGS] if o.has_key?(GROUPINGS)
@recipes = o[RECIPES] if o.has_key?(RECIPES)
@version = o[VERSION] if o.has_key?(VERSION)
@source_url = o[SOURCE_URL] if o.has_key?(SOURCE_URL)
@@ -726,7 +617,7 @@ class Chef
if block_given?
super
else
- Chef::Log.debug "ignoring method #{method} on cookbook with name #{name}, possible typo or future metadata?"
+ Chef::Log.debug "ignoring method #{method} on cookbook with name #{name}, possible typo or the ghosts of metadata past or future?"
end
end
diff --git a/lib/chef/cookbook/remote_file_vendor.rb b/lib/chef/cookbook/remote_file_vendor.rb
index e63d094dc4..cfd7789311 100644
--- a/lib/chef/cookbook/remote_file_vendor.rb
+++ b/lib/chef/cookbook/remote_file_vendor.rb
@@ -30,7 +30,7 @@ class Chef
def initialize(manifest, rest)
@manifest = manifest
- @cookbook_name = @manifest[:cookbook_name] || @manifest[:name]
+ @cookbook_name = @manifest.name
@rest = rest
end
@@ -44,8 +44,8 @@ class Chef
raise "get_filename: Cannot determine segment/filename for incoming filename #{filename}"
end
- raise "No such segment #{segment} in cookbook #{@cookbook_name}" unless @manifest[segment]
- found_manifest_record = @manifest[segment].find { |manifest_record| manifest_record[:path] == filename }
+ raise "No such segment #{segment} in cookbook #{@cookbook_name}" unless @manifest.files_for(segment)
+ found_manifest_record = @manifest.files_for(segment).find { |manifest_record| manifest_record[:path] == filename }
raise "No such file #{filename} in #{@cookbook_name}" unless found_manifest_record
cache_filename = File.join("cookbooks", @cookbook_name, found_manifest_record["path"])
diff --git a/lib/chef/cookbook/synchronizer.rb b/lib/chef/cookbook/synchronizer.rb
index bb44bc3d5c..625f3b4f20 100644
--- a/lib/chef/cookbook/synchronizer.rb
+++ b/lib/chef/cookbook/synchronizer.rb
@@ -62,18 +62,11 @@ class Chef
# Synchronizes the locally cached copies of cookbooks with the files on the
# server.
class CookbookSynchronizer
- CookbookFile = Struct.new(:cookbook, :segment, :manifest_record)
+ CookbookFile = Struct.new(:cookbook, :manifest_record)
attr_accessor :remove_obsoleted_files
def initialize(cookbooks_by_name, events)
- @eager_segments = Chef::CookbookVersion::COOKBOOK_SEGMENTS.dup
- unless Chef::Config[:no_lazy_load]
- @eager_segments.delete(:files)
- @eager_segments.delete(:templates)
- end
- @eager_segments.freeze
-
@cookbooks_by_name, @events = cookbooks_by_name, events
@cookbook_full_file_paths = {}
@@ -101,15 +94,19 @@ class Chef
end
def cookbook_segment(cookbook_name, segment)
- @cookbooks_by_name[cookbook_name].manifest[segment]
+ @cookbooks_by_name[cookbook_name].files_for(segment)
end
def files
+ exclude = unless Chef::Config[:no_lazy_load]
+ [ :files, :templates ]
+ else
+ []
+ end
+
@files ||= cookbooks.inject([]) do |memo, cookbook|
- @eager_segments.each do |segment|
- cookbook.manifest[segment].each do |manifest_record|
- memo << CookbookFile.new(cookbook, segment, manifest_record)
- end
+ cookbook.each_file(excluded_parts: exclude) do |manifest_record|
+ memo << CookbookFile.new(cookbook, manifest_record)
end
memo
end
@@ -162,8 +159,10 @@ class Chef
@events.cookbook_sync_start(cookbook_count)
queue.process(Chef::Config[:cookbook_sync_threads])
+ # Ensure that cookbooks know where they're rooted at, for manifest purposes.
+ ensure_cookbook_paths
# Update the full file paths in the manifest
- update_cookbook_filenames()
+ update_cookbook_filenames
rescue Exception => e
@events.cookbook_sync_failed(cookbooks, e)
@@ -176,9 +175,8 @@ class Chef
# Saves the full_path to the file of the cookbook to be updated
# in the manifest later
def save_full_file_path(file, full_path)
- @cookbook_full_file_paths[file.cookbook] ||= {}
- @cookbook_full_file_paths[file.cookbook][file.segment] ||= [ ]
- @cookbook_full_file_paths[file.cookbook][file.segment] << full_path
+ @cookbook_full_file_paths[file.cookbook] ||= []
+ @cookbook_full_file_paths[file.cookbook] << full_path
end
# remove cookbooks that are not referenced in the expanded run_list at all
@@ -229,10 +227,15 @@ class Chef
end
def update_cookbook_filenames
- @cookbook_full_file_paths.each do |cookbook, file_segments|
- file_segments.each do |segment, full_paths|
- cookbook.replace_segment_filenames(segment, full_paths)
- end
+ @cookbook_full_file_paths.each do |cookbook, full_paths|
+ cookbook.all_files = full_paths
+ end
+ end
+
+ def ensure_cookbook_paths
+ cookbooks.each do |cookbook|
+ cb_dir = File.join(Chef::Config[:file_cache_path], "cookbooks", cookbook.name)
+ cookbook.root_paths = Array(cb_dir)
end
end
diff --git a/lib/chef/cookbook_manifest.rb b/lib/chef/cookbook_manifest.rb
index d6de9dd029..125f353d21 100644
--- a/lib/chef/cookbook_manifest.rb
+++ b/lib/chef/cookbook_manifest.rb
@@ -15,7 +15,10 @@
# limitations under the License.
require "forwardable"
+require "chef/mixin/versioned_api"
require "chef/util/path_helper"
+require "chef/cookbook/manifest_v0"
+require "chef/cookbook/manifest_v2"
require "chef/log"
class Chef
@@ -24,17 +27,11 @@ class Chef
# to a Chef Server.
class CookbookManifest
- # Duplicates the same constant in CookbookVersion. We cannot remove it
- # there because it is treated by other code as part of CookbookVersion's
- # public API (also used in some deprecated methods).
- COOKBOOK_SEGMENTS = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ].freeze
-
extend Forwardable
attr_reader :cookbook_version
def_delegator :@cookbook_version, :root_paths
- def_delegator :@cookbook_version, :segment_filenames
def_delegator :@cookbook_version, :name
def_delegator :@cookbook_version, :identifier
def_delegator :@cookbook_version, :metadata
@@ -56,10 +53,7 @@ class Chef
# the format used by the `cookbook_artifacts` endpoint (for policyfiles).
# Setting this option also changes the behavior of #save_url and
# #force_save_url such that CookbookVersions will be uploaded to the new
- # `cookbook_artifacts` API. This endpoint is currently under active
- # development and the format is expected to change frequently, therefore
- # the result of #manifest, #to_hash, and #to_json will not be stable when
- # `policy_mode` is enabled.
+ # `cookbook_artifacts` API.
def initialize(cookbook_version, policy_mode: false)
@cookbook_version = cookbook_version
@policy_mode = !!policy_mode
@@ -126,10 +120,7 @@ class Chef
end
def to_hash
- result = manifest.dup
- result["frozen?"] = frozen_version?
- result["chef_type"] = "cookbook_version"
- result.to_hash
+ CookbookManifestVersions.to_hash(self)
end
def to_json(*a)
@@ -164,15 +155,48 @@ class Chef
# make the corresponding changes to the cookbook_version object. Required
# to provide backward compatibility with CookbookVersion#manifest= method.
def update_from(new_manifest)
- @manifest = Mash.new new_manifest
+ @manifest = Chef::CookbookManifestVersions.from_hash(new_manifest)
@checksums = extract_checksums_from_manifest(@manifest)
@manifest_records_by_path = extract_manifest_records_by_path(@manifest)
+ end
+
+ def files_for(part)
+ return root_files if part.to_s == "root_files"
+ manifest[:all_files].select do |file|
+ seg = file[:name].split("/")[0]
+ part.to_s == seg
+ end
+ end
+
+ def each_file(excluded_parts: [], &block)
+ excluded_parts = Array(excluded_parts).map { |p| p.to_s }
- COOKBOOK_SEGMENTS.each do |segment|
- next unless @manifest.has_key?(segment)
- filenames = @manifest[segment].map { |manifest_record| manifest_record["name"] }
+ manifest[:all_files].each do |file|
+ seg = file[:name].split("/")[0]
+ next if excluded_parts.include?(seg)
+ yield file if block_given?
+ end
+ end
+
+ def by_parent_directory
+ @by_parent_directory ||=
+ manifest[:all_files].inject({}) do |memo, file|
+ parts = file[:name].split("/")
+ parent = if parts.length == 1
+ "root_files"
+ else
+ parts[0]
+ end
+
+ memo[parent] ||= []
+ memo[parent] << file
+ memo
+ end
+ end
- cookbook_version.replace_segment_filenames(segment, filenames)
+ def root_files
+ manifest[:all_files].select do |file|
+ file[:name].split("/").length == 1
end
end
@@ -186,15 +210,7 @@ class Chef
# See #preferred_manifest_record for a description an individual manifest record.
def generate_manifest
manifest = Mash.new({
- :recipes => Array.new,
- :definitions => Array.new,
- :libraries => Array.new,
- :attributes => Array.new,
- :files => Array.new,
- :templates => Array.new,
- :resources => Array.new,
- :providers => Array.new,
- :root_files => Array.new,
+ all_files: Array.new,
})
@checksums = {}
@@ -203,24 +219,24 @@ class Chef
raise "Cookbook #{name} does not have root_paths! Cannot generate manifest."
end
- COOKBOOK_SEGMENTS.each do |segment|
- segment_filenames(segment).each do |segment_file|
- next if File.directory?(segment_file)
+ @cookbook_version.all_files.each do |file|
+ next if File.directory?(file)
- path, specificity = parse_segment_file_from_root_paths(segment, segment_file)
- file_name = File.basename(path)
+ name, path, specificity = parse_file_from_root_paths(file)
- csum = checksum_cookbook_file(segment_file)
- @checksums[csum] = segment_file
- rs = Mash.new({
- :name => file_name,
- :path => path,
- :checksum => csum,
- :specificity => specificity,
- })
+ csum = checksum_cookbook_file(file)
+ @checksums[csum] = file
+ rs = Mash.new({
+ :name => name,
+ :path => path,
+ :checksum => csum,
+ :specificity => specificity,
+ # full_path is not a part of the normal manifest, but is very useful to keep around.
+ # uploaders should strip this out.
+ :full_path => file,
+ })
- manifest[segment] << rs
- end
+ manifest[:all_files] << rs
end
manifest[:metadata] = metadata
@@ -238,38 +254,42 @@ class Chef
@manifest = manifest
end
- def parse_segment_file_from_root_paths(segment, segment_file)
+ def parse_file_from_root_paths(file)
root_paths.each do |root_path|
- pathname = Chef::Util::PathHelper.relative_path_from(root_path, segment_file)
+ pathname = Chef::Util::PathHelper.relative_path_from(root_path, file)
parts = pathname.each_filename.take(2)
# Check if path is actually under root_path
next if parts[0] == ".."
- if segment == :templates || segment == :files
+
+ # if we have a root_file, such as metadata.rb, the first part will be "."
+ return [ pathname.to_s, pathname.to_s, "default" ] if parts.length == 1
+
+ segment = parts[0]
+
+ name = File.join(segment, pathname.basename.to_s)
+
+ if segment == "templates" || segment == "files"
# Check if pathname looks like files/foo or templates/foo (unscoped)
if pathname.each_filename.to_a.length == 2
# Use root_default in case the same path exists at root_default and default
- return [ pathname.to_s, "root_default" ]
+ return [ name, pathname.to_s, "root_default" ]
else
- return [ pathname.to_s, parts[1] ]
+ return [ name, pathname.to_s, parts[1] ]
end
else
- return [ pathname.to_s, "default" ]
+ return [ name, pathname.to_s, "default" ]
end
end
- Chef::Log.error("Cookbook file #{segment_file} not under cookbook root paths #{root_paths.inspect}.")
- raise "Cookbook file #{segment_file} not under cookbook root paths #{root_paths.inspect}."
+ Chef::Log.error("Cookbook file #{file} not under cookbook root paths #{root_paths.inspect}.")
+ raise "Cookbook file #{file} not under cookbook root paths #{root_paths.inspect}."
end
def extract_checksums_from_manifest(manifest)
- checksums = {}
- COOKBOOK_SEGMENTS.each do |segment|
- next unless manifest.has_key?(segment)
- manifest[segment].each do |manifest_record|
- checksums[manifest_record[:checksum]] = nil
- end
+ manifest[:all_files].inject({}) do |memo, manifest_record|
+ memo[manifest_record[:checksum]] = nil
+ memo
end
- checksums
end
def checksum_cookbook_file(filepath)
@@ -277,14 +297,20 @@ class Chef
end
def extract_manifest_records_by_path(manifest)
- manifest_records_by_path = {}
- COOKBOOK_SEGMENTS.each do |segment|
- next unless manifest.has_key?(segment)
- manifest[segment].each do |manifest_record|
- manifest_records_by_path[manifest_record[:path]] = manifest_record
- end
+ manifest[:all_files].inject({}) do |memo, manifest_record|
+ memo[manifest_record[:path]] = manifest_record
+ memo
end
- manifest_records_by_path
end
+
+ end
+ class CookbookManifestVersions
+
+ extend Chef::Mixin::VersionedAPIFactory
+ add_versioned_api_class Chef::Cookbook::ManifestV0
+ add_versioned_api_class Chef::Cookbook::ManifestV2
+
+ def_versioned_delegator :from_hash
+ def_versioned_delegator :to_hash
end
end
diff --git a/lib/chef/cookbook_site_streaming_uploader.rb b/lib/chef/cookbook_site_streaming_uploader.rb
index c0e85ff984..1641992eac 100644
--- a/lib/chef/cookbook_site_streaming_uploader.rb
+++ b/lib/chef/cookbook_site_streaming_uploader.rb
@@ -43,15 +43,13 @@ class Chef
FileUtils.mkdir_p(tmp_cookbook_dir)
Chef::Log.debug("Staging at #{tmp_cookbook_dir}")
checksums_to_on_disk_paths = cookbook.checksums
- Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segment|
- cookbook.manifest[segment].each do |manifest_record|
- path_in_cookbook = manifest_record[:path]
- on_disk_path = checksums_to_on_disk_paths[manifest_record[:checksum]]
- dest = File.join(tmp_cookbook_dir, cookbook.name.to_s, path_in_cookbook)
- FileUtils.mkdir_p(File.dirname(dest))
- Chef::Log.debug("Staging #{on_disk_path} to #{dest}")
- FileUtils.cp(on_disk_path, dest)
- end
+ cookbook.each_file do |manifest_record|
+ path_in_cookbook = manifest_record[:path]
+ on_disk_path = checksums_to_on_disk_paths[manifest_record[:checksum]]
+ dest = File.join(tmp_cookbook_dir, cookbook.name.to_s, path_in_cookbook)
+ FileUtils.mkdir_p(File.dirname(dest))
+ Chef::Log.debug("Staging #{on_disk_path} to #{dest}")
+ FileUtils.cp(on_disk_path, dest)
end
# First, generate metadata
diff --git a/lib/chef/cookbook_uploader.rb b/lib/chef/cookbook_uploader.rb
index bb75234563..5e11314190 100644
--- a/lib/chef/cookbook_uploader.rb
+++ b/lib/chef/cookbook_uploader.rb
@@ -40,7 +40,7 @@ class Chef
def initialize(cookbooks, opts = {})
@opts = opts
@cookbooks = Array(cookbooks)
- @rest = opts[:rest] || Chef::ServerAPI.new(Chef::Config[:chef_server_url])
+ @rest = opts[:rest] || Chef::ServerAPI.new(Chef::Config[:chef_server_url], version_class: Chef::CookbookManifestVersions)
@concurrency = opts[:concurrency] || 10
@policy_mode = opts[:policy_mode] || false
end
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 7353941bb1..dcb8c97548 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -37,45 +37,23 @@ class Chef
class CookbookVersion
include Comparable
+ extend Forwardable
+
+ def_delegator :@cookbook_manifest, :files_for
+ def_delegator :@cookbook_manifest, :each_file
COOKBOOK_SEGMENTS = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ]
- attr_accessor :all_files
+ attr_reader :all_files
attr_accessor :root_paths
- attr_accessor :definition_filenames
- attr_accessor :template_filenames
- attr_accessor :file_filenames
- attr_accessor :library_filenames
- attr_accessor :resource_filenames
- attr_accessor :provider_filenames
- attr_accessor :root_filenames
attr_accessor :name
- attr_accessor :metadata_filenames
-
- def status=(new_status)
- Chef.deprecated(:internal_api, "Deprecated method `status' called. This method will be removed.")
- @status = new_status
- end
-
- def status
- Chef.deprecated(:internal_api, "Deprecated method `status' called. This method will be removed.")
- @status
- end
# A Chef::Cookbook::Metadata object. It has a setter that fixes up the
# metadata to add descriptions of the recipes contained in this
# CookbookVersion.
attr_reader :metadata
- # attribute_filenames also has a setter that has non-default
- # functionality.
- attr_reader :attribute_filenames
-
- # recipe_filenames also has a setter that has non-default
- # functionality.
- attr_reader :recipe_filenames
-
attr_reader :recipe_filenames_by_name
attr_reader :attribute_filenames_by_short_filename
@@ -96,6 +74,11 @@ class Chef
root_paths[0]
end
+ def all_files=(files)
+ @all_files = Array(files)
+ cookbook_manifest.reset!
+ end
+
# This is the one and only method that knows how cookbook files'
# checksums are generated.
def self.checksum_cookbook_file(filepath)
@@ -118,23 +101,10 @@ class Chef
@root_paths = root_paths
@frozen = false
- @attribute_filenames = Array.new
- @definition_filenames = Array.new
- @template_filenames = Array.new
- @file_filenames = Array.new
- @recipe_filenames = Array.new
- @recipe_filenames_by_name = Hash.new
- @library_filenames = Array.new
- @resource_filenames = Array.new
- @provider_filenames = Array.new
- @metadata_filenames = Array.new
- @root_filenames = Array.new
-
@all_files = Array.new
- # deprecated
- @status = :ready
@file_vendor = nil
+ @cookbook_manifest = Chef::CookbookManifest.new(self)
@metadata = Chef::Cookbook::Metadata.new
@chef_server_rest = chef_server_rest
end
@@ -163,10 +133,25 @@ class Chef
"#{name}-#{version}"
end
- def attribute_filenames=(*filenames)
- @attribute_filenames = filenames.flatten
- @attribute_filenames_by_short_filename = filenames_by_name(attribute_filenames)
- attribute_filenames
+ def attribute_filenames_by_short_filename
+ @attribute_filenames_by_short_filename ||= begin
+ name_map = filenames_by_name(files_for("attributes"))
+ root_alias = cookbook_manifest.root_files.find { |record| record[:name] == "attributes.rb" }
+ name_map["default"] = root_alias[:full_path] if root_alias
+ name_map
+ end
+ end
+
+ def recipe_filenames_by_name
+ @recipe_filenames_by_name ||= begin
+ name_map = filenames_by_name(files_for("recipes"))
+ root_alias = cookbook_manifest.root_files.find { |record| record[:name] == "recipe.rb" }
+ if root_alias
+ Chef::Log.error("Cookbook #{name} contains both recipe.rb and and recipes/default.rb, ignoring recipes/default.rb") if name_map["default"]
+ name_map["default"] = root_alias[:full_path]
+ end
+ name_map
+ end
end
def metadata=(metadata)
@@ -175,14 +160,14 @@ class Chef
@metadata
end
- ## BACKCOMPAT/DEPRECATED - Remove these and fix breakage before release [DAN - 5/20/2010]##
- alias :attribute_files :attribute_filenames
- alias :attribute_files= :attribute_filenames=
-
def manifest
cookbook_manifest.manifest
end
+ def manifest=(new_manifest)
+ cookbook_manifest.update_from(new_manifest)
+ end
+
# Returns a hash of checksums to either nil or the on disk path (which is
# done by generate_manifest).
def checksums
@@ -193,29 +178,16 @@ class Chef
cookbook_manifest.manifest_records_by_path
end
- def manifest=(new_manifest)
- cookbook_manifest.update_from(new_manifest)
- end
-
# Return recipe names in the form of cookbook_name::recipe_name
def fully_qualified_recipe_names
- results = Array.new
- recipe_filenames_by_name.each_key do |rname|
- results << "#{name}::#{rname}"
+ files_for("recipes").inject([]) do |memo, recipe|
+ rname = recipe[:name].split("/")[1]
+ rname = File.basename(rname, ".rb")
+ memo << "#{name}::#{rname}"
+ memo
end
- results
- end
-
- def recipe_filenames=(*filenames)
- @recipe_filenames = filenames.flatten
- @recipe_filenames_by_name = filenames_by_name(recipe_filenames)
- recipe_filenames
end
- ## BACKCOMPAT/DEPRECATED - Remove these and fix breakage before release [DAN - 5/20/2010]##
- alias :recipe_files :recipe_filenames
- alias :recipe_files= :recipe_filenames=
-
# called from DSL
def load_recipe(recipe_name, run_context)
unless recipe_filenames_by_name.has_key?(recipe_name)
@@ -235,41 +207,7 @@ class Chef
end
def segment_filenames(segment)
- unless COOKBOOK_SEGMENTS.include?(segment)
- raise ArgumentError, "invalid segment #{segment}: must be one of #{COOKBOOK_SEGMENTS.join(', ')}"
- end
-
- case segment.to_sym
- when :resources
- @resource_filenames
- when :providers
- @provider_filenames
- when :recipes
- @recipe_filenames
- when :libraries
- @library_filenames
- when :definitions
- @definition_filenames
- when :attributes
- @attribute_filenames
- when :files
- @file_filenames
- when :templates
- @template_filenames
- when :root_files
- @root_filenames
- end
- end
-
- def replace_segment_filenames(segment, filenames)
- case segment.to_sym
- when :recipes
- self.recipe_filenames = filenames
- when :attributes
- self.attribute_filenames = filenames
- else
- segment_filenames(segment).replace(filenames)
- end
+ files_for(segment).map { |f| f["full_path"] || File.join(root_dir, f["path"]) }
end
# Query whether a template file +template_filename+ is available. File
@@ -349,7 +287,7 @@ class Chef
filenames_by_pref = Hash.new
preferences.each { |pref| filenames_by_pref[pref] = Array.new }
- manifest[segment].each do |manifest_record|
+ files_for(segment).each do |manifest_record|
manifest_record_path = manifest_record[:path]
# find the NON SPECIFIC filenames, but prefer them by filespecificity.
@@ -389,7 +327,7 @@ class Chef
records_by_pref = Hash.new
preferences.each { |pref| records_by_pref[pref] = Array.new }
- manifest[segment].each do |manifest_record|
+ files_for(segment).each do |manifest_record|
manifest_record_path = manifest_record[:path]
# extract the preference part from the path.
@@ -469,12 +407,22 @@ class Chef
end
private :preferences_for_path
+ def display
+ output = Mash.new
+ output["cookbook_name"] = name
+ output["name"] = full_name
+ output["frozen?"] = frozen_version?
+ output["metadata"] = metadata.to_hash
+ output["version"] = version
+ output.merge(cookbook_manifest.by_parent_directory)
+ end
+
def self.from_hash(o)
cookbook_version = new(o["cookbook_name"] || o["name"])
# We want the Chef::Cookbook::Metadata object to always be inflated
- cookbook_version.metadata = Chef::Cookbook::Metadata.from_hash(o["metadata"])
cookbook_version.manifest = o
+ cookbook_version.metadata = Chef::Cookbook::Metadata.from_hash(o["metadata"])
cookbook_version.identifier = o["identifier"] if o.key?("identifier")
# We don't need the following step when we decide to stop supporting deprecated operators in the metadata (e.g. <<, >>)
@@ -488,33 +436,6 @@ class Chef
from_hash(o)
end
- # @deprecated This method was used by the Ruby Chef Server and is no longer
- # needed. There is no replacement.
- def generate_manifest_with_urls
- Chef.deprecated(:internal_api, "Deprecated method #generate_manifest_with_urls.")
-
- rendered_manifest = manifest.dup
- COOKBOOK_SEGMENTS.each do |segment|
- if rendered_manifest.has_key?(segment)
- rendered_manifest[segment].each do |manifest_record|
- url_options = { :cookbook_name => name.to_s, :cookbook_version => version, :checksum => manifest_record["checksum"] }
- manifest_record["url"] = yield(url_options)
- end
- end
- end
- rendered_manifest
- end
-
- def to_hash
- # TODO: this should become deprecated when the API for CookbookManifest becomes stable
- cookbook_manifest.to_hash
- end
-
- def to_json(*a)
- # TODO: this should become deprecated when the API for CookbookManifest becomes stable
- cookbook_manifest.to_json
- end
-
def metadata_json_file
File.join(root_paths[0], "metadata.json")
end
@@ -533,22 +454,12 @@ class Chef
# REST API
##
- def save_url
- # TODO: this should become deprecated when the API for CookbookManifest becomes stable
- cookbook_manifest.save_url
- end
-
- def force_save_url
- # TODO: this should become deprecated when the API for CookbookManifest becomes stable
- cookbook_manifest.force_save_url
- end
-
def chef_server_rest
@chef_server_rest ||= chef_server_rest
end
def self.chef_server_rest
- Chef::ServerAPI.new(Chef::Config[:chef_server_url])
+ Chef::ServerAPI.new(Chef::Config[:chef_server_url], { version_class: Chef::CookbookManifestVersions })
end
def destroy
@@ -602,12 +513,12 @@ class Chef
Chef::Version.new(version) <=> Chef::Version.new(other.version)
end
- private
-
def cookbook_manifest
@cookbook_manifest ||= CookbookManifest.new(self)
end
+ private
+
def find_preferred_manifest_record(node, segment, filename)
preferences = preferences_for_path(node, segment, filename)
@@ -615,15 +526,21 @@ class Chef
preferences.find { |preferred_filename| manifest_records_by_path[preferred_filename] }
end
- # For each filename, produce a mapping of base filename (i.e. recipe name
+ # For each manifest record, produce a mapping of base filename (i.e. recipe name
+ # or attribute file) to on disk location
+ def relative_paths_by_name(records)
+ records.select { |record| record[:name] =~ /\.rb$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:path]; memo }
+ end
+
+ # For each manifest record, produce a mapping of base filename (i.e. recipe name
# or attribute file) to on disk location
- def filenames_by_name(filenames)
- filenames.select { |filename| filename =~ /\.rb$/ }.inject({}) { |memo, filename| memo[File.basename(filename, ".rb")] = filename; memo }
+ def filenames_by_name(records)
+ records.select { |record| record[:name] =~ /\.rb$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:full_path]; memo }
end
def file_vendor
unless @file_vendor
- @file_vendor = Chef::Cookbook::FileVendor.create_from_manifest(manifest)
+ @file_vendor = Chef::Cookbook::FileVendor.create_from_manifest(cookbook_manifest)
end
@file_vendor
end
diff --git a/lib/chef/data_bag_item.rb b/lib/chef/data_bag_item.rb
index ddb520dc0b..d0fca26125 100644
--- a/lib/chef/data_bag_item.rb
+++ b/lib/chef/data_bag_item.rb
@@ -75,6 +75,7 @@ class Chef
end
def raw_data=(new_data)
+ new_data = Mash.new(new_data)
unless new_data.respond_to?(:[]) && new_data.respond_to?(:keys)
raise Exceptions::ValidationFailed, "Data Bag Items must contain a Hash or Mash!"
end
@@ -132,7 +133,7 @@ class Chef
item = new
item.data_bag(h.delete("data_bag")) if h.key?("data_bag")
if h.key?("raw_data")
- item.raw_data = Mash.new(h["raw_data"])
+ item.raw_data = h["raw_data"]
else
item.raw_data = h
end
diff --git a/lib/chef/data_collector/messages.rb b/lib/chef/data_collector/messages.rb
index c0683534a9..ca854957d1 100644
--- a/lib/chef/data_collector/messages.rb
+++ b/lib/chef/data_collector/messages.rb
@@ -73,6 +73,8 @@ class Chef
"resources" => reporter_data[:resources].map(&:report_data),
"run_id" => run_status.run_id,
"run_list" => run_status.node.run_list.for_json,
+ "policy_name" => run_status.node.policy_name,
+ "policy_group" => run_status.node.policy_group,
"start_time" => run_status.start_time.utc.iso8601,
"end_time" => run_status.end_time.utc.iso8601,
"source" => collector_source,
diff --git a/lib/chef/decorator/unchain.rb b/lib/chef/decorator/unchain.rb
index b1e1f9fce1..30179d4e63 100644
--- a/lib/chef/decorator/unchain.rb
+++ b/lib/chef/decorator/unchain.rb
@@ -38,22 +38,6 @@ class Chef
__path__.push(key)
@delegate_sd_obj.public_send(__method__, *__path__, value)
end
-
- # unfortunately we have to support method_missing for node.set_unless.foo.bar = 'baz' notation
- def method_missing(symbol, *args)
- if symbol == :to_ary
- merged_attributes.send(symbol, *args)
- elsif args.empty?
- Chef.deprecated :attributes, %q{method access to node attributes (node.foo.bar) is deprecated and will be removed in Chef 13, please use bracket syntax (node["foo"]["bar"])}
- self[symbol]
- elsif symbol.to_s =~ /=$/
- Chef.deprecated :attributes, %q{method setting of node attributes (node.foo="bar") is deprecated and will be removed in Chef 13, please use bracket syntax (node["foo"]="bar")}
- key_to_set = symbol.to_s[/^(.+)=$/, 1]
- self[key_to_set] = (args.length == 1 ? args[0] : args)
- else
- raise NoMethodError, "Undefined node attribute or method `#{symbol}' on `node'"
- end
- end
end
end
end
diff --git a/lib/chef/deprecated.rb b/lib/chef/deprecated.rb
index 461f65225b..04ecfe5a6e 100644
--- a/lib/chef/deprecated.rb
+++ b/lib/chef/deprecated.rb
@@ -218,6 +218,26 @@ class Chef
end
end
+ class MultiresourceMatch < Base
+ def id
+ 16
+ end
+
+ def target
+ "multiresource_match.html"
+ end
+ end
+
+ class UseInlineResources < Base
+ def id
+ 17
+ end
+
+ def target
+ "use_inline_resources.html"
+ end
+ end
+
# id 3694 was deleted
class Generic < Base
diff --git a/lib/chef/dsl/declare_resource.rb b/lib/chef/dsl/declare_resource.rb
index ac3776c92f..6869e77eca 100644
--- a/lib/chef/dsl/declare_resource.rb
+++ b/lib/chef/dsl/declare_resource.rb
@@ -241,7 +241,7 @@ class Chef
resource = build_resource(type, name, created_at: created_at, &resource_attrs_block)
- run_context.resource_collection.insert(resource, resource_type: type, instance_name: name)
+ run_context.resource_collection.insert(resource, resource_type: resource.declared_type, instance_name: resource.name)
resource
end
diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb
index 926bbe24b5..0f8013f114 100644
--- a/lib/chef/event_dispatch/base.rb
+++ b/lib/chef/event_dispatch/base.rb
@@ -195,6 +195,22 @@ class Chef
def lwrp_load_complete
end
+ # Called when an ohai plugin file loading starts
+ def ohai_plugin_load_start(file_count)
+ end
+
+ # Called when an ohai plugin file has been loaded
+ def ohai_plugin_file_loaded(path)
+ end
+
+ # Called when an ohai plugin file has an error on load.
+ def ohai_plugin_file_load_failed(path, exception)
+ end
+
+ # Called when an ohai plugin file loading has finished
+ def ohai_plugin_load_complete
+ end
+
# Called before attribute files are loaded
def attribute_load_start(attribute_file_count)
end
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index 78bdf0cf4a..a09a3a062c 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -59,14 +59,6 @@ class Chef
class UnsupportedAction < RuntimeError; end
class MissingLibrary < RuntimeError; end
- class DeprecatedExitCode < RuntimeError
- def initalize
- super "Exiting with a non RFC 062 Exit Code."
- require "chef/application/exit_code"
- Chef::Application::ExitCode.notify_deprecated_exit_code
- end
- end
-
class CannotDetermineNodeName < RuntimeError
def initialize
super "Unable to determine node name: configure node_name or configure the system's hostname and fqdn"
diff --git a/lib/chef/formatters/error_description.rb b/lib/chef/formatters/error_description.rb
index ece33bdd49..ceb2f68539 100644
--- a/lib/chef/formatters/error_description.rb
+++ b/lib/chef/formatters/error_description.rb
@@ -17,6 +17,8 @@
# limitations under the License.
#
+require "chef/version"
+
class Chef
module Formatters
# == Formatters::ErrorDescription
@@ -45,7 +47,7 @@ class Chef
display_section(heading, text, out)
end
end
- display_section("Platform:", RUBY_PLATFORM, out)
+ display_section("System Info:", error_context_info, out)
end
def for_json
@@ -64,6 +66,21 @@ class Chef
out.puts "\n"
end
+ def error_context_info
+ context_info = { chef_version: Chef::VERSION }
+ if Chef.node
+ context_info[:platform] = Chef.node["platform"]
+ context_info[:platform_version] = Chef.node["platform_version"]
+ end
+ # A string like "ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]"
+ context_info[:ruby] = RUBY_DESCRIPTION
+ # The argv[0] value.
+ context_info[:program_name] = $PROGRAM_NAME
+ # This is kind of wonky but it's the only way to get the entry path script.
+ context_info[:executable] = File.realpath(caller.last[/^(.*):\d+:in /, 1])
+ context_info.map { |k, v| "#{k}=#{v}" }.join("\n")
+ end
+
end
end
end
diff --git a/lib/chef/guard_interpreter/default_guard_interpreter.rb b/lib/chef/guard_interpreter/default_guard_interpreter.rb
index 449ca9a316..f93c0e04f0 100644
--- a/lib/chef/guard_interpreter/default_guard_interpreter.rb
+++ b/lib/chef/guard_interpreter/default_guard_interpreter.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Edwards (<adamed@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,7 +33,9 @@ class Chef
public
def evaluate
- shell_out(@command, @command_opts).status.success?
+ shell_out_with_systems_locale(@command, @command_opts).status.success?
+ # Timeout fails command rather than chef-client run, see:
+ # https://tickets.opscode.com/browse/CHEF-2690
rescue Chef::Exceptions::CommandTimeout
Chef::Log.warn "Command '#{@command}' timed out"
false
diff --git a/lib/chef/http/socketless_chef_zero_client.rb b/lib/chef/http/socketless_chef_zero_client.rb
index d2f1f45b1d..296330815a 100644
--- a/lib/chef/http/socketless_chef_zero_client.rb
+++ b/lib/chef/http/socketless_chef_zero_client.rb
@@ -170,6 +170,7 @@ class Chef
"QUERY_STRING" => url.query,
"SERVER_PORT" => url.port,
"HTTP_HOST" => "localhost:#{url.port}",
+ "HTTP_X_OPS_SERVER_API_VERSION" => headers["X-Ops-Server-API-Version"],
"rack.url_scheme" => "chefzero",
"rack.input" => StringIO.new(body_str),
}
diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb
index 47ce85b9e3..9c8b984054 100644
--- a/lib/chef/knife.rb
+++ b/lib/chef/knife.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Brown (<cb@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -265,8 +265,7 @@ class Chef
ui.fatal("Cannot find subcommand for: '#{args.join(' ')}'")
# Mention rehash when the subcommands cache(plugin_manifest.json) is used
- if subcommand_loader.is_a?(Chef::Knife::SubcommandLoader::HashedCommandLoader) ||
- subcommand_loader.is_a?(Chef::Knife::SubcommandLoader::CustomManifestLoader)
+ if subcommand_loader.is_a?(Chef::Knife::SubcommandLoader::HashedCommandLoader)
ui.info("If this is a recently installed plugin, please run 'knife rehash' to update the subcommands cache.")
end
diff --git a/lib/chef/knife/configure.rb b/lib/chef/knife/configure.rb
index 48007bbee7..967a18de87 100644
--- a/lib/chef/knife/configure.rb
+++ b/lib/chef/knife/configure.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -75,8 +75,6 @@ class Chef
::File.open(config[:config_file], "w") do |f|
f.puts <<-EOH
-log_level :info
-log_location STDOUT
node_name '#{new_client_name}'
client_key '#{new_client_key}'
validation_client_name '#{validation_client_name}'
diff --git a/lib/chef/knife/configure_client.rb b/lib/chef/knife/configure_client.rb
index 7d0b3d260d..c015687ac7 100644
--- a/lib/chef/knife/configure_client.rb
+++ b/lib/chef/knife/configure_client.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -34,8 +34,6 @@ class Chef
FileUtils.mkdir_p(@config_dir)
ui.info("Writing client.rb")
File.open(File.join(@config_dir, "client.rb"), "w") do |file|
- file.puts("log_level :info")
- file.puts("log_location STDOUT")
file.puts("chef_server_url '#{Chef::Config[:chef_server_url]}'")
file.puts("validation_client_name '#{Chef::Config[:validation_client_name]}'")
end
diff --git a/lib/chef/knife/cookbook_create.rb b/lib/chef/knife/cookbook_create.rb
index ccb78bb7a6..6122fd52d3 100644
--- a/lib/chef/knife/cookbook_create.rb
+++ b/lib/chef/knife/cookbook_create.rb
@@ -21,442 +21,9 @@ require "chef/knife"
class Chef
class Knife
class CookbookCreate < Knife
-
- deps do
- require "chef/json_compat"
- require "uri"
- require "fileutils"
- end
-
- banner "knife cookbook create COOKBOOK (options)"
-
- option :cookbook_path,
- :short => "-o PATH",
- :long => "--cookbook-path PATH",
- :description => "The directory where the cookbook will be created"
-
- option :readme_format,
- :short => "-r FORMAT",
- :long => "--readme-format FORMAT",
- :description => "Format of the README file, supported formats are 'md' (markdown) and 'rdoc' (rdoc)"
-
- option :cookbook_license,
- :short => "-I LICENSE",
- :long => "--license LICENSE",
- :description => "License for cookbook, apachev2, gplv2, gplv3, mit or none"
-
- option :cookbook_copyright,
- :short => "-C COPYRIGHT",
- :long => "--copyright COPYRIGHT",
- :description => "Name of copyright holder"
-
- option :cookbook_email,
- :short => "-m EMAIL",
- :long => "--email EMAIL",
- :description => "Email address of cookbook maintainer"
-
def run
- Chef::Log.deprecation <<EOF
-This command is being deprecated in favor of `chef generate cookbook` and will soon return an error.
-Please use `chef generate cookbook` instead of this command.
-EOF
- self.config = Chef::Config.merge!(config)
- if @name_args.length < 1
- show_usage
- ui.fatal("You must specify a cookbook name")
- exit 1
- end
-
- if default_cookbook_path_empty? && parameter_empty?(config[:cookbook_path])
- raise ArgumentError, "Default cookbook_path is not specified in the knife.rb config file, and a value to -o is not provided. Nowhere to write the new cookbook to."
- end
-
- cookbook_path = File.expand_path(Array(config[:cookbook_path]).first)
- cookbook_name = @name_args.first
- copyright = config[:cookbook_copyright] || "YOUR_COMPANY_NAME"
- email = config[:cookbook_email] || "YOUR_EMAIL"
- license = ((config[:cookbook_license] != "false") && config[:cookbook_license]) || "none"
- readme_format = ((config[:readme_format] != "false") && config[:readme_format]) || "md"
- create_cookbook(cookbook_path, cookbook_name, copyright, license)
- create_readme(cookbook_path, cookbook_name, readme_format)
- create_changelog(cookbook_path, cookbook_name)
- create_metadata(cookbook_path, cookbook_name, copyright, email, license, readme_format)
- end
-
- def create_cookbook(dir, cookbook_name, copyright, license)
- msg("** Creating cookbook #{cookbook_name} in #{dir}")
- FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "attributes")}"
- FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "recipes")}"
- FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "definitions")}"
- FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "libraries")}"
- FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "resources")}"
- FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "providers")}"
- FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "files", "default")}"
- FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "templates", "default")}"
- unless File.exists?(File.join(dir, cookbook_name, "recipes", "default.rb"))
- open(File.join(dir, cookbook_name, "recipes", "default.rb"), "w") do |file|
- file.puts <<-EOH
-#
-# Cookbook Name:: #{cookbook_name}
-# Recipe:: default
-#
-# Copyright #{Time.now.year}, #{copyright}
-#
-EOH
- case license
- when "apachev2"
- file.puts <<-EOH
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-EOH
- when "gplv2"
- file.puts <<-EOH
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-EOH
- when "gplv3"
- file.puts <<-EOH
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-EOH
- when "mit"
- file.puts <<-EOH
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-EOH
- when "none"
- file.puts <<-EOH
-# All rights reserved - Do Not Redistribute
-#
-EOH
- end
- end
- end
- end
-
- def create_changelog(dir, cookbook_name)
- msg("** Creating CHANGELOG for cookbook: #{cookbook_name}")
- unless File.exists?(File.join(dir, cookbook_name, "CHANGELOG.md"))
- open(File.join(dir, cookbook_name, "CHANGELOG.md"), "w") do |file|
- file.puts <<-EOH
-# #{cookbook_name} CHANGELOG
-
-This file is used to list changes made in each version of the #{cookbook_name} cookbook.
-
-## 0.1.0
-- [your_name] - Initial release of #{cookbook_name}
-
-- - -
-Check the [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) for help with Markdown.
-
-The [Github Flavored Markdown page](http://github.github.com/github-flavored-markdown/) describes the differences between markdown on github and standard markdown.
-EOH
- end
- end
+ Chef::Log.fatal("knife cookbook create has been removed. Please use `chef generate cookbook` from the ChefDK")
end
-
- def create_readme(dir, cookbook_name, readme_format)
- msg("** Creating README for cookbook: #{cookbook_name}")
- unless File.exist?(File.join(dir, cookbook_name, "README.#{readme_format}"))
- open(File.join(dir, cookbook_name, "README.#{readme_format}"), "w") do |file|
- case readme_format
- when "rdoc"
- file.puts <<-EOH
-= #{cookbook_name} Cookbook
-TODO: Enter the cookbook description here.
-
-e.g.
-This cookbook makes your favorite breakfast sandwich.
-
-== Requirements
-TODO: List your cookbook requirements. Be sure to include any requirements this cookbook has on platforms, libraries, other cookbooks, packages, operating systems, etc.
-
-e.g.
-==== packages
-- +toaster+ - #{cookbook_name} needs toaster to brown your bagel.
-
-== Attributes
-TODO: List your cookbook attributes here.
-
-e.g.
-==== #{cookbook_name}::default
-<table>
- <tr>
- <th>Key</th>
- <th>Type</th>
- <th>Description</th>
- <th>Default</th>
- </tr>
- <tr>
- <td><tt>['#{cookbook_name}']['bacon']</tt></td>
- <td>Boolean</td>
- <td>whether to include bacon</td>
- <td><tt>true</tt></td>
- </tr>
-</table>
-
-== Usage
-==== #{cookbook_name}::default
-TODO: Write usage instructions for each cookbook.
-
-e.g.
-Just include +#{cookbook_name}+ in your node's +run_list+:
-
- {
- "name":"my_node",
- "run_list": [
- "recipe[#{cookbook_name}]"
- ]
- }
-
-== Contributing
-TODO: (optional) If this is a public cookbook, detail the process for contributing. If this is a private cookbook, remove this section.
-
-e.g.
-1. Fork the repository on Github
-2. Create a named feature branch (like `add_component_x`)
-3. Write your change
-4. Write tests for your change (if applicable)
-5. Run the tests, ensuring they all pass
-6. Submit a Pull Request using Github
-
-== License and Authors
-Authors: TODO: List authors
-EOH
- when "md", "mkd", "txt"
- file.puts <<-EOH
-# #{cookbook_name} Cookbook
-
-TODO: Enter the cookbook description here.
-
-e.g.
-This cookbook makes your favorite breakfast sandwich.
-
-## Requirements
-
-TODO: List your cookbook requirements. Be sure to include any requirements this cookbook has on platforms, libraries, other cookbooks, packages, operating systems, etc.
-
-e.g.
-### Platforms
-
-- SandwichOS
-
-### Chef
-
-- Chef 12.0 or later
-
-### Cookbooks
-
-- `toaster` - #{cookbook_name} needs toaster to brown your bagel.
-
-## Attributes
-
-TODO: List your cookbook attributes here.
-
-e.g.
-### #{cookbook_name}::default
-
-<table>
- <tr>
- <th>Key</th>
- <th>Type</th>
- <th>Description</th>
- <th>Default</th>
- </tr>
- <tr>
- <td><tt>['#{cookbook_name}']['bacon']</tt></td>
- <td>Boolean</td>
- <td>whether to include bacon</td>
- <td><tt>true</tt></td>
- </tr>
-</table>
-
-## Usage
-
-### #{cookbook_name}::default
-
-TODO: Write usage instructions for each cookbook.
-
-e.g.
-Just include `#{cookbook_name}` in your node's `run_list`:
-
-```json
-{
- "name":"my_node",
- "run_list": [
- "recipe[#{cookbook_name}]"
- ]
-}
-```
-
-## Contributing
-
-TODO: (optional) If this is a public cookbook, detail the process for contributing. If this is a private cookbook, remove this section.
-
-e.g.
-1. Fork the repository on Github
-2. Create a named feature branch (like `add_component_x`)
-3. Write your change
-4. Write tests for your change (if applicable)
-5. Run the tests, ensuring they all pass
-6. Submit a Pull Request using Github
-
-## License and Authors
-
-Authors: TODO: List authors
-
-EOH
- else
- file.puts <<-EOH
-#{cookbook_name} Cookbook
-#{'=' * "#{cookbook_name} Cookbook".length}
- TODO: Enter the cookbook description here.
-
- e.g.
- This cookbook makes your favorite breakfast sandwich.
-
-Requirements
- TODO: List your cookbook requirements. Be sure to include any requirements this cookbook has on platforms, libraries, other cookbooks, packages, operating systems, etc.
-
- e.g.
- toaster #{cookbook_name} needs toaster to brown your bagel.
-
-Attributes
- TODO: List your cookbook attributes here.
-
- #{cookbook_name}
- Key Type Description Default
- ['#{cookbook_name}']['bacon'] Boolean whether to include bacon true
-
-Usage
- #{cookbook_name}
- TODO: Write usage instructions for each cookbook.
-
- e.g.
- Just include `#{cookbook_name}` in your node's `run_list`:
-
- [code]
- {
- "name":"my_node",
- "run_list": [
- "recipe[#{cookbook_name}]"
- ]
- }
- [/code]
-
-Contributing
- TODO: (optional) If this is a public cookbook, detail the process for contributing. If this is a private cookbook, remove this section.
-
- e.g.
- 1. Fork the repository on Github
- 2. Create a named feature branch (like `add_component_x`)
- 3. Write your change
- 4. Write tests for your change (if applicable)
- 5. Run the tests, ensuring they all pass
- 6. Submit a Pull Request using Github
-
-License and Authors
- Authors: TODO: List authors
-EOH
- end
- end
- end
- end
-
- def create_metadata(dir, cookbook_name, copyright, email, license, readme_format)
- msg("** Creating metadata for cookbook: #{cookbook_name}")
-
- license_name = case license
- when "apachev2"
- "Apache 2.0"
- when "gplv2"
- "GNU Public License 2.0"
- when "gplv3"
- "GNU Public License 3.0"
- when "mit"
- "MIT"
- when "none"
- "All rights reserved"
- end
-
- unless File.exist?(File.join(dir, cookbook_name, "metadata.rb"))
- open(File.join(dir, cookbook_name, "metadata.rb"), "w") do |file|
- if File.exist?(File.join(dir, cookbook_name, "README.#{readme_format}"))
- long_description = "long_description IO.read(File.join(File.dirname(__FILE__), 'README.#{readme_format}'))"
- end
- file.puts <<-EOH
-name '#{cookbook_name}'
-maintainer '#{copyright}'
-maintainer_email '#{email}'
-license '#{license_name}'
-description 'Installs/Configures #{cookbook_name}'
-#{long_description}
-version '0.1.0'
-EOH
- end
- end
- end
-
- private
-
- def default_cookbook_path_empty?
- Chef::Config[:cookbook_path].nil? || Chef::Config[:cookbook_path].empty?
- end
-
- def parameter_empty?(parameter)
- parameter.nil? || parameter.empty?
- end
-
end
end
end
diff --git a/lib/chef/knife/cookbook_download.rb b/lib/chef/knife/cookbook_download.rb
index 741f444093..b745e77f27 100644
--- a/lib/chef/knife/cookbook_download.rb
+++ b/lib/chef/knife/cookbook_download.rb
@@ -70,7 +70,7 @@ class Chef
ui.info("Downloading #{@cookbook_name} cookbook version #{@version}")
cookbook = Chef::CookbookVersion.load(@cookbook_name, @version)
- manifest = cookbook.manifest
+ manifest = cookbook.cookbook_manifest
basedir = File.join(config[:download_directory], "#{@cookbook_name}-#{cookbook.version}")
if File.exists?(basedir)
@@ -83,10 +83,9 @@ class Chef
end
end
- Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segment|
- next unless manifest.has_key?(segment)
+ manifest.by_parent_directory.each do |segment, files|
ui.info("Downloading #{segment}")
- manifest[segment].each do |segment_file|
+ files.each do |segment_file|
dest = File.join(basedir, segment_file["path"].gsub("/", File::SEPARATOR))
Chef::Log.debug("Downloading #{segment_file['path']} to #{dest}")
FileUtils.mkdir_p(File.dirname(dest))
diff --git a/lib/chef/knife/cookbook_show.rb b/lib/chef/knife/cookbook_show.rb
index d0c930de0a..1d9983632d 100644
--- a/lib/chef/knife/cookbook_show.rb
+++ b/lib/chef/knife/cookbook_show.rb
@@ -76,9 +76,13 @@ class Chef
pretty_print(temp_file.read)
when 3 # We are showing a specific part of the cookbook
- output(cookbook.manifest[segment])
- when 2 # We are showing the whole cookbook data
- output(cookbook)
+ if segment == "metadata"
+ output(cookbook.metadata)
+ else
+ output(cookbook.files_for(segment))
+ end
+ when 2 # We are showing the whole cookbook
+ output(cookbook.display)
when 1 # We are showing the cookbook versions (all of them)
env = config[:environment]
api_endpoint = env ? "environments/#{env}/cookbooks/#{cookbook_name}" : "cookbooks/#{cookbook_name}"
diff --git a/lib/chef/knife/cookbook_site_vendor.rb b/lib/chef/knife/cookbook_site_vendor.rb
deleted file mode 100644
index 291715cc0b..0000000000
--- a/lib/chef/knife/cookbook_site_vendor.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2011-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"
-require "chef/knife/cookbook_site_install"
-
-class Chef::Knife::CookbookSiteVendor < Chef::Knife::CookbookSiteInstall
-
- def self.load_deps
- superclass.load_deps
- end
-
- def self.options=(new_opts)
- superclass.options = new_opts
- end
-
- def self.options
- superclass.options
- end
-
- banner(<<-B)
-*************************************************
-DEPRECATED: please use knife cookbook site install
-*************************************************
-
-#{superclass.banner}
-B
-
- category "deprecated"
-
-end
diff --git a/lib/chef/knife/core/custom_manifest_loader.rb b/lib/chef/knife/core/custom_manifest_loader.rb
deleted file mode 100644
index 9fe51599af..0000000000
--- a/lib/chef/knife/core/custom_manifest_loader.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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.
-#
-
-require "chef/version"
-class Chef
- class Knife
- class SubcommandLoader
-
- #
- # Load a subcommand from a user-supplied
- # manifest file
- #
- class CustomManifestLoader < Chef::Knife::SubcommandLoader
- attr_accessor :manifest
- def initialize(chef_config_dir, plugin_manifest)
- super(chef_config_dir)
- @manifest = plugin_manifest
- end
-
- # If the user has created a ~/.chef/plugin_manifest.json file, we'll use
- # that instead of inspecting the on-system gems to find the plugins. The
- # file format is expected to look like:
- #
- # { "plugins": {
- # "knife-ec2": {
- # "paths": [
- # "/home/alice/.rubymanagerthing/gems/knife-ec2-x.y.z/lib/chef/knife/ec2_server_create.rb",
- # "/home/alice/.rubymanagerthing/gems/knife-ec2-x.y.z/lib/chef/knife/ec2_server_delete.rb"
- # ]
- # }
- # }
- # }
- #
- # Extraneous content in this file is ignored. This is intentional so that we
- # can adapt the file format for potential behavior changes to knife in
- # the future.
- def find_subcommands_via_manifest
- # Format of subcommand_files is "relative_path" (something you can
- # Kernel.require()) => full_path. The relative path isn't used
- # currently, so we just map full_path => full_path.
- subcommand_files = {}
- manifest["plugins"].each do |plugin_name, plugin_manifest|
- plugin_manifest["paths"].each do |cmd_path|
- subcommand_files[cmd_path] = cmd_path
- end
- end
- subcommand_files.merge(find_subcommands_via_dirglob)
- end
-
- def subcommand_files
- @subcommand_files ||= (find_subcommands_via_manifest.values + site_subcommands).flatten.uniq
- end
- end
- end
- end
-end
diff --git a/lib/chef/knife/core/subcommand_loader.rb b/lib/chef/knife/core/subcommand_loader.rb
index 30a438b780..14b6479b53 100644
--- a/lib/chef/knife/core/subcommand_loader.rb
+++ b/lib/chef/knife/core/subcommand_loader.rb
@@ -1,6 +1,6 @@
# Author:: Christopher Brown (<cb@chef.io>)
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,7 +20,6 @@ require "chef/version"
require "chef/util/path_helper"
require "chef/knife/core/gem_glob_loader"
require "chef/knife/core/hashed_command_loader"
-require "chef/knife/core/custom_manifest_loader"
class Chef
class Knife
@@ -38,7 +37,6 @@ class Chef
#
class SubcommandLoader
attr_reader :chef_config_dir
- attr_reader :env
# A small factory method. Eventually, this is the only place
# where SubcommandLoader should know about its subclasses, but
@@ -50,9 +48,6 @@ class Chef
if autogenerated_manifest?
Chef::Log.debug("Using autogenerated hashed command manifest #{plugin_manifest_path}")
Knife::SubcommandLoader::HashedCommandLoader.new(chef_config_dir, plugin_manifest)
- elsif custom_manifest?
- Chef.deprecated(:internal_api, "Using custom manifest #{plugin_manifest_path} is deprecated. Please use a `knife rehash` autogenerated manifest instead.")
- Knife::SubcommandLoader::CustomManifestLoader.new(chef_config_dir, plugin_manifest)
else
Knife::SubcommandLoader::GemGlobLoader.new(chef_config_dir)
end
@@ -72,10 +67,6 @@ class Chef
plugin_manifest? && plugin_manifest.key?(HashedCommandLoader::KEY)
end
- def self.custom_manifest?
- plugin_manifest? && plugin_manifest.key?("plugins")
- end
-
def self.plugin_manifest
Chef::JSONCompat.from_json(File.read(plugin_manifest_path))
end
@@ -84,14 +75,8 @@ class Chef
Chef::Util::PathHelper.home(".chef", "plugin_manifest.json")
end
- def initialize(chef_config_dir, env = nil)
+ def initialize(chef_config_dir)
@chef_config_dir = chef_config_dir
-
- # Deprecated and un-used instance variable.
- @env = env
- unless env.nil?
- Chef.deprecated(:internal_api, "The env argument to Chef::Knife::SubcommandLoader is deprecated. If you are using env to inject/mock HOME, consider mocking Chef::Util::PathHelper.home instead.")
- end
end
# Load all the sub-commands
@@ -149,21 +134,6 @@ class Chef
end
#
- # Subclassses should define this themselves. Eventually, this will raise a
- # NotImplemented error, but for now, we mimic the behavior the user was likely
- # to get in the past.
- #
- def subcommand_files
- Chef.deprecated :internal_api, "Using Chef::Knife::SubcommandLoader directly is deprecated.
-Please use Chef::Knife::SubcommandLoader.for_config(chef_config_dir, env)"
- @subcommand_files ||= if Chef::Knife::SubcommandLoader.plugin_manifest?
- Chef::Knife::SubcommandLoader::CustomManifestLoader.new(chef_config_dir, env).subcommand_files
- else
- Chef::Knife::SubcommandLoader::GemGlobLoader.new(chef_config_dir, env).subcommand_files
- end
- end
-
- #
# Utility function for finding an element in a hash given an array
# of words and a separator. We find the the longest key in the
# hash composed of the given words joined by the separator.
diff --git a/lib/chef/knife/search.rb b/lib/chef/knife/search.rb
index 7fc76b28c0..c4c3380734 100644
--- a/lib/chef/knife/search.rb
+++ b/lib/chef/knife/search.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -73,19 +73,18 @@ class Chef
def run
read_cli_args
- fuzzify_query
if @type == "node"
ui.use_presenter Knife::Core::NodePresenter
end
q = Chef::Search::Query.new
- escaped_query = Addressable::URI.encode_component(@query, Addressable::URI::CharacterClasses::QUERY)
result_items = []
result_count = 0
search_args = Hash.new
+ search_args[:fuzz] = true
search_args[:start] = config[:start] if config[:start]
search_args[:rows] = config[:rows] if config[:rows]
if config[:filter_result]
@@ -95,7 +94,7 @@ class Chef
end
begin
- q.search(@type, escaped_query, search_args) do |item|
+ q.search(@type, @query, search_args) do |item|
formatted_item = Hash.new
if item.is_a?(Hash)
# doing a little magic here to set the correct name
@@ -109,7 +108,7 @@ class Chef
rescue Net::HTTPServerException => e
msg = Chef::JSONCompat.from_json(e.response.body)["error"].first
ui.error("knife search failed: #{msg}")
- exit 1
+ exit 99
end
if ui.interchange?
@@ -124,6 +123,9 @@ class Chef
end
end
end
+
+ # return a "failure" code to the shell so that knife search can be used in pipes similar to grep
+ exit 1 if result_count == 0
end
def read_cli_args
@@ -151,12 +153,6 @@ class Chef
end
end
- def fuzzify_query
- if @query !~ /:/
- @query = "tags:*#{@query}* OR roles:*#{@query}* OR fqdn:*#{@query}* OR addresses:*#{@query}* OR policy_name:*#{@query}* OR policy_group:*#{@query}*"
- end
- end
-
# This method turns a set of key value pairs in a string into the appropriate data structure that the
# chef-server search api is expecting.
# expected input is in the form of:
diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb
index d79565991f..380a60fdd6 100644
--- a/lib/chef/knife/ssh.rb
+++ b/lib/chef/knife/ssh.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -223,7 +223,7 @@ class Chef
end
@search_count = 0
- query.search(:node, @name_args[0], filter_result: required_attributes) do |item|
+ query.search(:node, @name_args[0], filter_result: required_attributes, fuzz: true) do |item|
@search_count += 1
# we should skip the loop to next iteration if the item
# returned by the search is nil
@@ -331,18 +331,22 @@ class Chef
command = fixup_sudo(command)
command.force_encoding("binary") if command.respond_to?(:force_encoding)
subsession.open_channel do |chan|
- chan.request_pty
- chan.exec command do |ch, success|
- raise ArgumentError, "Cannot execute #{command}" unless success
- ch.on_data do |ichannel, data|
- print_data(ichannel[:host], data)
- if data =~ /^knife sudo password: /
- print_data(ichannel[:host], "\n")
- ichannel.send_data("#{get_password}\n")
+ if config[:on_error] && exit_status != 0
+ chan.close()
+ else
+ chan.request_pty
+ chan.exec command do |ch, success|
+ raise ArgumentError, "Cannot execute #{command}" unless success
+ ch.on_data do |ichannel, data|
+ print_data(ichannel[:host], data)
+ if data =~ /^knife sudo password: /
+ print_data(ichannel[:host], "\n")
+ ichannel.send_data("#{get_password}\n")
+ end
+ end
+ ch.on_request "exit-status" do |ichannel, data|
+ exit_status = [exit_status, data.read_long].max
end
- end
- ch.on_request "exit-status" do |ichannel, data|
- exit_status = [exit_status, data.read_long].max
end
end
end
diff --git a/lib/chef/mixin/command.rb b/lib/chef/mixin/command.rb
deleted file mode 100644
index b1fa7ebd89..0000000000
--- a/lib/chef/mixin/command.rb
+++ /dev/null
@@ -1,194 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-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/log"
-require "chef/exceptions"
-require "tmpdir"
-require "fcntl"
-require "etc"
-
-class Chef
- module Mixin
-
- #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- # NOTE:
- # The popen4 method upon which all the code here is based has a race
- # condition where it may fail to read all of the data written to stdout and
- # stderr after the child process exits. The tests for the code here
- # occasionally fail because of this race condition, so they have been
- # tagged "volatile".
- #
- # This code is considered deprecated, so it should not need to be modified
- # frequently, if at all. HOWEVER, if you do modify the code here, you must
- # explicitly enable volatile tests:
- #
- # bundle exec rspec spec/unit/mixin/command_spec.rb -t volatile
- #
- # In addition, you should make a note that tests need to be run with
- # volatile tests enabled on any pull request or bug report you submit with
- # your patch.
- #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
- module Command
- extend self
-
- # NOTE: run_command is deprecated in favor of using Chef::Shellout which now comes from the mixlib-shellout gem. NOTE #
-
- if RUBY_PLATFORM =~ /mswin|mingw32|windows/
- require "chef/mixin/command/windows"
- include ::Chef::Mixin::Command::Windows
- extend ::Chef::Mixin::Command::Windows
- else
- require "chef/mixin/command/unix"
- include ::Chef::Mixin::Command::Unix
- extend ::Chef::Mixin::Command::Unix
- end
-
- # === Parameters
- # args<Hash>: A number of required and optional arguments
- # command<String>, <Array>: A complete command with options to execute or a command and options as an Array
- # creates<String>: The absolute path to a file that prevents the command from running if it exists
- # cwd<String>: Working directory to execute command in, defaults to Dir.tmpdir
- # timeout<String>: How many seconds to wait for the command to execute before timing out
- # returns<String>: The single exit value command is expected to return, otherwise causes an exception
- # ignore_failure<Boolean>: Whether to raise an exception on failure, or just return the status
- # output_on_failure<Boolean>: Return output in raised exception regardless of Log.level
- #
- # user<String>: The UID or user name of the user to execute the command as
- # group<String>: The GID or group name of the group to execute the command as
- # environment<Hash>: Pairs of environment variable names and their values to set before execution
- #
- # === Returns
- # Returns the exit status of args[:command]
- def run_command(args = {})
- status, stdout, stderr = run_command_and_return_stdout_stderr(args)
-
- status
- end
-
- # works same as above, except that it returns stdout and stderr
- # requirement => platforms like solaris 9,10 has weird issues where
- # even in command failure the exit code is zero, so we need to lookup stderr.
- def run_command_and_return_stdout_stderr(args = {})
- command_output = ""
-
- args[:ignore_failure] ||= false
- args[:output_on_failure] ||= false
-
- # TODO: This is the wrong place for this responsibility.
- if args.has_key?(:creates)
- if File.exists?(args[:creates])
- Chef::Log.debug("Skipping #{args[:command]} - creates #{args[:creates]} exists.")
- return false
- end
- end
-
- status, stdout, stderr = output_of_command(args[:command], args)
- command_output << "STDOUT: #{stdout}"
- command_output << "STDERR: #{stderr}"
- handle_command_failures(status, command_output, args)
-
- [status, stdout, stderr]
- end
-
- def output_of_command(command, args)
- Chef.deprecated(:run_command, "Chef::Mixin::Command.run_command is deprecated, please use shell_out")
- Chef::Log.debug("Executing #{command}")
- stderr_string, stdout_string, status = "", "", nil
-
- exec_processing_block = lambda do |pid, stdin, stdout, stderr|
- stdout_string, stderr_string = stdout.string.chomp, stderr.string.chomp
- end
-
- args[:cwd] ||= Dir.tmpdir
- unless ::File.directory?(args[:cwd])
- raise Chef::Exceptions::Exec, "#{args[:cwd]} does not exist or is not a directory"
- end
-
- Dir.chdir(args[:cwd]) do
- if args[:timeout]
- begin
- Timeout.timeout(args[:timeout]) do
- status = popen4(command, args, &exec_processing_block)
- end
- rescue Timeout::Error => e
- Chef::Log.error("#{command} exceeded timeout #{args[:timeout]}")
- raise(e)
- end
- else
- status = popen4(command, args, &exec_processing_block)
- end
-
- Chef::Log.debug("---- Begin output of #{command} ----")
- Chef::Log.debug("STDOUT: #{stdout_string}")
- Chef::Log.debug("STDERR: #{stderr_string}")
- Chef::Log.debug("---- End output of #{command} ----")
- Chef::Log.debug("Ran #{command} returned #{status.exitstatus}")
- end
-
- [status, stdout_string, stderr_string]
- end
-
- def handle_command_failures(status, command_output, opts = {})
- return if opts[:ignore_failure]
- opts[:returns] ||= 0
- return if Array(opts[:returns]).include?(status.exitstatus)
-
- # if the log level is not debug, through output of command when we fail
- output = ""
- if Chef::Log.level == :debug || opts[:output_on_failure]
- output << "\n---- Begin output of #{opts[:command]} ----\n"
- output << command_output.to_s
- output << "\n---- End output of #{opts[:command]} ----\n"
- end
- raise Chef::Exceptions::Exec, "#{opts[:command]} returned #{status.exitstatus}, expected #{opts[:returns]}#{output}"
- end
-
- # Call #run_command but set LC_ALL to the system's current environment so it doesn't get changed to C.
- #
- # === Parameters
- # args<Hash>: A number of required and optional arguments that will be handed out to #run_command
- #
- # === Returns
- # Returns the result of #run_command
- def run_command_with_systems_locale(args = {})
- args[:environment] ||= {}
- args[:environment]["LC_ALL"] = ENV["LC_ALL"]
- run_command args
- end
-
- # def popen4(cmd, args={}, &b)
- # @@os_handler.popen4(cmd, args, &b)
- # end
-
- # module_function :popen4
-
- # FIXME: yard with @yield
- def chdir_or_tmpdir(dir)
- dir ||= Dir.tmpdir
- unless File.directory?(dir)
- raise Chef::Exceptions::Exec, "#{dir} does not exist or is not a directory"
- end
- Dir.chdir(dir) do
- yield
- end
- end
-
- end
- end
-end
diff --git a/lib/chef/mixin/command/unix.rb b/lib/chef/mixin/command/unix.rb
deleted file mode 100644
index aa541c3637..0000000000
--- a/lib/chef/mixin/command/unix.rb
+++ /dev/null
@@ -1,220 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-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 Mixin
- module Command
- module Unix
- # This is taken directly from Ara T Howard's Open4 library, and then
- # modified to suit the needs of Chef. Any bugs here are most likely
- # my own, and not Ara's.
- #
- # The original appears in external/open4.rb in its unmodified form.
- #
- # Thanks Ara!
- def popen4(cmd, args = {}, &b)
- # Ruby 1.8 suffers from intermittent segfaults believed to be due to GC while IO.select
- # See CHEF-2916 / CHEF-1305
- GC.disable
-
- # Waitlast - this is magic.
- #
- # Do we wait for the child process to die before we yield
- # to the block, or after? That is the magic of waitlast.
- #
- # By default, we are waiting before we yield the block.
- args[:waitlast] ||= false
-
- args[:user] ||= nil
- unless args[:user].kind_of?(Integer)
- args[:user] = Etc.getpwnam(args[:user]).uid if args[:user]
- end
- args[:group] ||= nil
- unless args[:group].kind_of?(Integer)
- args[:group] = Etc.getgrnam(args[:group]).gid if args[:group]
- end
- args[:environment] ||= {}
-
- # Default on C locale so parsing commands output can be done
- # independently of the node's default locale.
- # "LC_ALL" could be set to nil, in which case we also must ignore it.
- unless args[:environment].has_key?("LC_ALL")
- args[:environment]["LC_ALL"] = "C"
- end
-
- pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
-
- verbose = $VERBOSE
- begin
- $VERBOSE = nil
- ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
-
- cid = fork do
- pw.last.close
- STDIN.reopen pw.first
- pw.first.close
-
- pr.first.close
- STDOUT.reopen pr.last
- pr.last.close
-
- pe.first.close
- STDERR.reopen pe.last
- pe.last.close
-
- STDOUT.sync = STDERR.sync = true
-
- if args[:group]
- Process.egid = args[:group]
- Process.gid = args[:group]
- end
-
- if args[:user]
- Process.euid = args[:user]
- Process.uid = args[:user]
- end
-
- args[:environment].each do |key, value|
- ENV[key] = value
- end
-
- if args[:umask]
- umask = ((args[:umask].respond_to?(:oct) ? args[:umask].oct : args[:umask].to_i) & 007777)
- File.umask(umask)
- end
-
- begin
- if cmd.kind_of?(Array)
- Kernel.exec(*cmd)
- else
- Kernel.exec(cmd)
- end
- raise "forty-two"
- rescue Exception => e
- Marshal.dump(e, ps.last)
- ps.last.flush
- end
- ps.last.close unless ps.last.closed?
- exit!
- end
- ensure
- $VERBOSE = verbose
- end
-
- [pw.first, pr.last, pe.last, ps.last].each { |fd| fd.close }
-
- begin
- e = Marshal.load ps.first
- raise(Exception === e ? e : "unknown failure!")
- rescue EOFError # If we get an EOF error, then the exec was successful
- 42
- ensure
- ps.first.close
- end
-
- pw.last.sync = true
-
- pi = [pw.last, pr.first, pe.first]
-
- if b
- begin
- if args[:waitlast]
- b[cid, *pi]
- # send EOF so that if the child process is reading from STDIN
- # it will actually finish up and exit
- pi[0].close_write
- Process.waitpid2(cid).last
- else
- # This took some doing.
- # The trick here is to close STDIN
- # Then set our end of the childs pipes to be O_NONBLOCK
- # Then wait for the child to die, which means any IO it
- # wants to do must be done - it's dead. If it isn't,
- # it's because something totally skanky is happening,
- # and we don't care.
- o = StringIO.new
- e = StringIO.new
-
- pi[0].close
-
- stdout = pi[1]
- stderr = pi[2]
-
- stdout.sync = true
- stderr.sync = true
-
- stdout.fcntl(Fcntl::F_SETFL, pi[1].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
- stderr.fcntl(Fcntl::F_SETFL, pi[2].fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK)
-
- stdout_finished = false
- stderr_finished = false
-
- results = nil
-
- while !stdout_finished || !stderr_finished
- begin
- channels_to_watch = []
- channels_to_watch << stdout if !stdout_finished
- channels_to_watch << stderr if !stderr_finished
- ready = IO.select(channels_to_watch, nil, nil, 1.0)
- rescue Errno::EAGAIN
- ensure
- results = Process.waitpid2(cid, Process::WNOHANG)
- if results
- stdout_finished = true
- stderr_finished = true
- end
- end
-
- if ready && ready.first.include?(stdout)
- line = results ? stdout.gets(nil) : stdout.gets
- if line
- o.write(line)
- else
- stdout_finished = true
- end
- end
- if ready && ready.first.include?(stderr)
- line = results ? stderr.gets(nil) : stderr.gets
- if line
- e.write(line)
- else
- stderr_finished = true
- end
- end
- end
- results = Process.waitpid2(cid) unless results
- o.rewind
- e.rewind
- b[cid, pi[0], o, e]
- results.last
- end
- ensure
- pi.each { |fd| fd.close unless fd.closed? }
- end
- else
- [cid, pw.last, pr.first, pe.first]
- end
- ensure
- GC.enable
- end
-
- end
- end
- end
-end
diff --git a/lib/chef/mixin/command/windows.rb b/lib/chef/mixin/command/windows.rb
deleted file mode 100644
index fd45ab0467..0000000000
--- a/lib/chef/mixin/command/windows.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
-# Author:: Doug MacEachern (<dougm@vmware.com>)
-# Copyright:: Copyright 2010-2016, VMware, 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 "open3"
-
-class Chef
- module Mixin
- module Command
- module Windows
- def popen4(cmd, args = {}, &b)
- # By default, we are waiting before we yield the block.
- args[:waitlast] ||= false
-
- #XXX :user, :group, :environment support?
-
- Open3.popen3(cmd) do |stdin, stdout, stderr, cid|
- if b
- if args[:waitlast]
- b[cid, stdin, stdout, stderr]
- # send EOF so that if the child process is reading from STDIN
- # it will actually finish up and exit
- stdin.close_write
- else
- o = StringIO.new
- e = StringIO.new
-
- stdin.close
-
- stdout.sync = true
- stderr.sync = true
-
- line = stdout.gets(nil)
- if line
- o.write(line)
- end
- line = stderr.gets(nil)
- if line
- e.write(line)
- end
- o.rewind
- e.rewind
- b[cid, stdin, o, e]
- end
- else
- [cid, stdin, stdout, stderr]
- end
- end
- $?
- end
-
- end
- end
- end
-end
diff --git a/lib/chef/mixin/path_sanity.rb b/lib/chef/mixin/path_sanity.rb
index 6a8e017bcd..c441d0770a 100644
--- a/lib/chef/mixin/path_sanity.rb
+++ b/lib/chef/mixin/path_sanity.rb
@@ -1,6 +1,6 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
-# Copyright:: Copyright 2011-2016, Chef Software Inc.
+# Copyright:: Copyright 2011-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,25 +22,23 @@ class Chef
def enforce_path_sanity(env = ENV)
if Chef::Config[:enforce_path_sanity]
- env["PATH"] = "" if env["PATH"].nil?
- path_separator = Chef::Platform.windows? ? ";" : ":"
- existing_paths = env["PATH"].split(path_separator)
- # ensure the Ruby and Gem bindirs are included
- # mainly for 'full-stack' Chef installs
- paths_to_add = []
- paths_to_add << ruby_bindir unless sane_paths.include?(ruby_bindir)
- paths_to_add << gem_bindir unless sane_paths.include?(gem_bindir)
- paths_to_add << sane_paths if sane_paths
- paths_to_add.flatten!.compact!
- paths_to_add.each do |sane_path|
- unless existing_paths.include?(sane_path)
- env_path = env["PATH"].dup
- env_path << path_separator unless env["PATH"].empty?
- env_path << sane_path
- env["PATH"] = env_path.encode("utf-8", invalid: :replace, undef: :replace)
- end
- end
+ env["PATH"] = sanitized_path(env)
+ end
+ end
+
+ def sanitized_path(env = ENV)
+ env_path = env["PATH"].nil? ? "" : env["PATH"].dup
+ path_separator = Chef::Platform.windows? ? ";" : ":"
+ # ensure the Ruby and Gem bindirs are included
+ # mainly for 'full-stack' Chef installs
+ new_paths = env_path.split(path_separator)
+ [ ruby_bindir, gem_bindir ].compact.each do |path|
+ new_paths = [ path ] + new_paths unless new_paths.include?(path)
+ end
+ sane_paths.each do |path|
+ new_paths << path unless new_paths.include?(path)
end
+ new_paths.join(path_separator).encode("utf-8", invalid: :replace, undef: :replace)
end
private
diff --git a/lib/chef/mixin/shell_out.rb b/lib/chef/mixin/shell_out.rb
index 18bd067989..b6e4cffe92 100644
--- a/lib/chef/mixin/shell_out.rb
+++ b/lib/chef/mixin/shell_out.rb
@@ -16,11 +16,12 @@
# limitations under the License.
require "mixlib/shellout"
-require "chef/deprecated"
+require "chef/mixin/path_sanity"
class Chef
module Mixin
module ShellOut
+ include Chef::Mixin::PathSanity
# PREFERRED APIS:
#
@@ -108,6 +109,7 @@ class Chef
"LC_ALL" => Chef::Config[:internal_locale],
"LANGUAGE" => Chef::Config[:internal_locale],
"LANG" => Chef::Config[:internal_locale],
+ env_path => sanitized_path,
}.update(options[env_key] || {})
shell_out_command(*args, **options)
end
@@ -129,28 +131,6 @@ class Chef
cmd
end
- DEPRECATED_OPTIONS =
- [ [:command_log_level, :log_level],
- [:command_log_prepend, :log_tag] ]
-
- # CHEF-3090: Deprecate command_log_level and command_log_prepend
- # Patterned after https://github.com/chef/chef/commit/e1509990b559984b43e428d4d801c394e970f432
- def run_command_compatible_options(command_args)
- return command_args unless command_args.last.is_a?(Hash)
-
- my_command_args = command_args.dup
- my_options = my_command_args.last
-
- DEPRECATED_OPTIONS.each do |old_option, new_option|
- # Edge case: someone specifies :command_log_level and 'command_log_level' in the option hash
- next unless value = my_options.delete(old_option) || my_options.delete(old_option.to_s)
- deprecate_option old_option, new_option
- my_options[new_option] = value
- end
-
- my_command_args
- end
-
# Helper for sublcasses to convert an array of string args into a string. It
# will compact nil or empty strings in the array and will join the array elements
# with spaces, without introducing any double spaces for nil/empty elements.
@@ -186,16 +166,12 @@ class Chef
private
def shell_out_command(*command_args)
- cmd = Mixlib::ShellOut.new(*run_command_compatible_options(command_args))
+ cmd = Mixlib::ShellOut.new(*command_args)
cmd.live_stream ||= io_for_live_stream
cmd.run_command
cmd
end
- def deprecate_option(old_option, new_option)
- Chef.deprecated :internal_api, "Chef::Mixin::ShellOut option :#{old_option} is deprecated. Use :#{new_option}"
- end
-
def io_for_live_stream
if STDOUT.tty? && !Chef::Config[:daemon] && Chef::Log.debug?
STDOUT
@@ -203,6 +179,14 @@ class Chef
nil
end
end
+
+ def env_path
+ if Chef::Platform.windows?
+ "Path"
+ else
+ "PATH"
+ end
+ end
end
end
end
diff --git a/lib/chef/mixins.rb b/lib/chef/mixins.rb
index b980e81287..2306fb9e89 100644
--- a/lib/chef/mixins.rb
+++ b/lib/chef/mixins.rb
@@ -1,6 +1,5 @@
require "chef/mixin/shell_out"
require "chef/mixin/checksum"
-require "chef/mixin/command"
require "chef/mixin/convert_to_class_name"
require "chef/mixin/create_path"
require "chef/mixin/deep_merge"
diff --git a/lib/chef/node.rb b/lib/chef/node.rb
index 92bdb5887b..549bde0dbb 100644
--- a/lib/chef/node.rb
+++ b/lib/chef/node.rb
@@ -338,6 +338,10 @@ class Chef
automatic[:platform_version] = version
end
+ def consume_ohai_data(ohai_data)
+ self.automatic_attrs = Chef::Mixin::DeepMerge.merge(automatic_attrs, ohai_data)
+ end
+
# Consumes the combined run_list and other attributes in +attrs+
def consume_attributes(attrs)
normal_attrs_to_merge = consume_run_list(attrs)
diff --git a/lib/chef/platform/rebooter.rb b/lib/chef/platform/rebooter.rb
index 6829b66539..33a6e24be2 100644
--- a/lib/chef/platform/rebooter.rb
+++ b/lib/chef/platform/rebooter.rb
@@ -51,8 +51,7 @@ class Chef
raise Chef::Exceptions::RebootFailed.new(e.message)
end
- raise Chef::Exceptions::Reboot.new(msg) if Chef::Application::ExitCode.enforce_rfc_062_exit_codes?
- Chef::Application::ExitCode.notify_reboot_exit_code_deprecation
+ raise Chef::Exceptions::Reboot.new(msg)
end
# this is a wrapper function so Chef::Client only needs a single line of code.
diff --git a/lib/chef/policy_builder/expand_node_object.rb b/lib/chef/policy_builder/expand_node_object.rb
index dbed44a002..26f39e8b73 100644
--- a/lib/chef/policy_builder/expand_node_object.rb
+++ b/lib/chef/policy_builder/expand_node_object.rb
@@ -239,7 +239,8 @@ class Chef
end
def api_service
- @api_service ||= Chef::ServerAPI.new(config[:chef_server_url])
+ @api_service ||= Chef::ServerAPI.new(config[:chef_server_url],
+ { version_class: Chef::CookbookManifestVersions })
end
def config
diff --git a/lib/chef/policy_builder/policyfile.rb b/lib/chef/policy_builder/policyfile.rb
index f0009eac6c..f84e1dc68e 100644
--- a/lib/chef/policy_builder/policyfile.rb
+++ b/lib/chef/policy_builder/policyfile.rb
@@ -149,7 +149,7 @@ class Chef
#
# @return [Chef::RunContext]
def setup_run_context(specific_recipes = nil)
- Chef::Cookbook::FileVendor.fetch_from_remote(http_api)
+ Chef::Cookbook::FileVendor.fetch_from_remote(api_service)
sync_cookbooks
cookbook_collection = Chef::CookbookCollection.new(cookbooks_to_sync)
cookbook_collection.validate!
@@ -267,7 +267,7 @@ class Chef
# @api private
def policy
- @policy ||= http_api.get(policyfile_location)
+ @policy ||= api_service.get(policyfile_location)
rescue Net::HTTPServerException => e
raise ConfigurationError, "Error loading policyfile from `#{policyfile_location}': #{e.class} - #{e.message}"
end
@@ -452,8 +452,9 @@ class Chef
end
# @api private
- def http_api
- @api_service ||= Chef::ServerAPI.new(config[:chef_server_url])
+ def api_service
+ @api_service ||= Chef::ServerAPI.new(config[:chef_server_url],
+ { version_class: Chef::CookbookManifestVersions })
end
# @api private
@@ -496,7 +497,7 @@ class Chef
def compat_mode_manifest_for(cookbook_name, lock_data)
xyz_version = lock_data["dotted_decimal_identifier"]
rel_url = "cookbooks/#{cookbook_name}/#{xyz_version}"
- inflate_cbv_object(http_api.get(rel_url))
+ inflate_cbv_object(api_service.get(rel_url))
rescue Exception => e
message = "Error loading cookbook #{cookbook_name} at version #{xyz_version} from #{rel_url}: #{e.class} - #{e.message}"
err = Chef::Exceptions::CookbookNotFound.new(message)
@@ -507,7 +508,7 @@ class Chef
def artifact_manifest_for(cookbook_name, lock_data)
identifier = lock_data["identifier"]
rel_url = "cookbook_artifacts/#{cookbook_name}/#{identifier}"
- inflate_cbv_object(http_api.get(rel_url))
+ inflate_cbv_object(api_service.get(rel_url))
rescue Exception => e
message = "Error loading cookbook #{cookbook_name} with identifier #{identifier} from #{rel_url}: #{e.class} - #{e.message}"
err = Chef::Exceptions::CookbookNotFound.new(message)
diff --git a/lib/chef/property.rb b/lib/chef/property.rb
index c6f72e15a7..a72e41a61e 100644
--- a/lib/chef/property.rb
+++ b/lib/chef/property.rb
@@ -110,6 +110,20 @@ class Chef
raise ArgumentError, "Cannot specify both default and name_property/name_attribute together on property #{self}"
end
+ # Recursively freeze the default if it isn't a lazy value.
+ unless default.is_a?(DelayedEvaluator)
+ visitor = lambda do |obj|
+ case obj
+ when Hash
+ obj.each_value { |value| visitor.call(value) }
+ when Array
+ obj.each { |value| visitor.call(value) }
+ end
+ obj.freeze
+ end
+ visitor.call(default)
+ end
+
# Validate the default early, so the user gets a good error message, and
# cache it so we don't do it again if so
begin
diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb
index 8334eab0a6..c7048d50e5 100644
--- a/lib/chef/provider.rb
+++ b/lib/chef/provider.rb
@@ -51,6 +51,32 @@ class Chef
true
end
+ # Defines an action method on the provider, running the block to compile the
+ # resources, converging them, and then checking if any were updated (and
+ # updating new-resource if so)
+ #
+ # @since 13.0
+ # @param name [String, Symbol] Name of the action to define.
+ # @param block [Proc] Body of the action.
+ # @return [void]
+ def self.action(name, &block)
+ # We need the block directly in a method so that `super` works.
+ define_method("compile_action_#{name}", &block)
+ class_eval <<-EOM
+ def action_#{name}
+ compile_and_converge_action { compile_action_#{name} }
+ end
+ EOM
+ end
+
+ # Deprecation stub for the old use_inline_resources mode.
+ #
+ # @return [void]
+ def self.use_inline_resources
+ # Uncomment this in Chef 13.6.
+ # Chef.deprecated(:use_inline_resources, "The use_inline_resources mode is no longer optional and the line enabling it can be removed")
+ end
+
#--
# TODO: this should be a reader, and the action should be passed in the
# constructor; however, many/most subclasses override the constructor so
@@ -176,6 +202,22 @@ class Chef
converge_actions.add_action(descriptions, &block)
end
+ # Create a child run_context, compile the block, and converge it.
+ #
+ # @api private
+ def compile_and_converge_action(&block)
+ old_run_context = run_context
+ @run_context = run_context.create_child
+ return_value = instance_eval(&block)
+ Chef::Runner.new(run_context).converge
+ return_value
+ ensure
+ if run_context.resource_collection.any? { |r| r.updated? }
+ new_resource.updated_by_last_action(true)
+ end
+ @run_context = old_run_context
+ end
+
#
# Handle patchy convergence safely.
#
@@ -326,84 +368,6 @@ class Chef
end
end
- # Enables inline evaluation of resources in provider actions.
- #
- # Without this option, any resources declared inside the Provider are added
- # to the resource collection after the current position at the time the
- # action is executed. Because they are added to the primary resource
- # collection for the chef run, they can notify other resources outside
- # the Provider, and potentially be notified by resources outside the Provider
- # (but this is complicated by the fact that they don't exist until the
- # provider executes). In this mode, it is impossible to correctly set the
- # updated_by_last_action flag on the parent Provider resource, since it
- # executes and returns before its component resources are run.
- #
- # With this option enabled, each action creates a temporary run_context
- # with its own resource collection, evaluates the action's code in that
- # context, and then converges the resources created. If any resources
- # were updated, then this provider's new_resource will be marked updated.
- #
- # In this mode, resources created within the Provider cannot interact with
- # external resources via notifies, though notifications to other
- # resources within the Provider will work. Delayed notifications are executed
- # at the conclusion of the provider's action, *not* at the end of the
- # main chef run.
- #
- # This mode of evaluation is experimental, but is believed to be a better
- # set of tradeoffs than the append-after mode, so it will likely become
- # the default in a future major release of Chef.
- #
- def self.use_inline_resources
- extend InlineResources::ClassMethods
- include InlineResources
- end
-
- # Chef::Provider::InlineResources
- # Implementation of inline resource convergence for providers. See
- # Provider.use_inline_resources for a longer explanation.
- #
- # This code is restricted to a module so that it can be selectively
- # applied to providers on an opt-in basis.
- #
- # @api private
- module InlineResources
-
- # Create a child run_context, compile the block, and converge it.
- #
- # @api private
- def compile_and_converge_action(&block)
- old_run_context = run_context
- @run_context = run_context.create_child
- return_value = instance_eval(&block)
- Chef::Runner.new(run_context).converge
- return_value
- ensure
- if run_context.resource_collection.any? { |r| r.updated? }
- new_resource.updated_by_last_action(true)
- end
- @run_context = old_run_context
- end
-
- # Class methods for InlineResources. Overrides the `action` DSL method
- # with one that enables inline resource convergence.
- #
- # @api private
- module ClassMethods
- # Defines an action method on the provider, running the block to
- # compile the resources, converging them, and then checking if any
- # were updated (and updating new-resource if so)
- def action(name, &block)
- # We need the block directly in a method so that `super` works
- define_method("compile_action_#{name}", &block)
- class_eval <<-EOM
- def action_#{name}
- compile_and_converge_action { compile_action_#{name} }
- end
- EOM
- end
- end
- end
-
protected
def converge_actions
@@ -432,33 +396,6 @@ class Chef
end
end
- module DeprecatedLWRPClass
- def const_missing(class_name)
- if Chef::Provider.deprecated_constants[class_name.to_sym]
- Chef.deprecated(:custom_resource, "Using an LWRP provider by its name (#{class_name}) directly is no longer supported in Chef 12 and will be removed. Use Chef::ProviderResolver.new(node, resource, action) instead.")
- Chef::Provider.deprecated_constants[class_name.to_sym]
- else
- raise NameError, "uninitialized constant Chef::Provider::#{class_name}"
- end
- end
-
- # @api private
- def register_deprecated_lwrp_class(provider_class, class_name)
- # Register Chef::Provider::MyProvider with deprecation warnings if you
- # try to access it
- if Chef::Provider.const_defined?(class_name, false)
- Chef::Log.warn "Chef::Provider::#{class_name} already exists! Cannot create deprecation class for #{provider_class}"
- else
- Chef::Provider.deprecated_constants[class_name.to_sym] = provider_class
- end
- end
-
- def deprecated_constants
- raise "Deprecated constants should be called only on Chef::Provider" unless self == Chef::Provider
- @deprecated_constants ||= {}
- end
- end
- extend DeprecatedLWRPClass
end
end
diff --git a/lib/chef/provider/apt_repository.rb b/lib/chef/provider/apt_repository.rb
index 2c72849d1c..541f733e7b 100644
--- a/lib/chef/provider/apt_repository.rb
+++ b/lib/chef/provider/apt_repository.rb
@@ -26,8 +26,6 @@ require "chef/provider/noop"
class Chef
class Provider
class AptRepository < Chef::Provider
- use_inline_resources
-
include Chef::Mixin::ShellOut
extend Chef::Mixin::Which
diff --git a/lib/chef/provider/apt_update.rb b/lib/chef/provider/apt_update.rb
index 135bd64035..670f3ad7f6 100644
--- a/lib/chef/provider/apt_update.rb
+++ b/lib/chef/provider/apt_update.rb
@@ -23,8 +23,6 @@ require "chef/mixin/which"
class Chef
class Provider
class AptUpdate < Chef::Provider
- use_inline_resources
-
extend Chef::Mixin::Which
provides :apt_update do
diff --git a/lib/chef/provider/cron.rb b/lib/chef/provider/cron.rb
index a45e889bcc..c232585c18 100644
--- a/lib/chef/provider/cron.rb
+++ b/lib/chef/provider/cron.rb
@@ -17,13 +17,11 @@
#
require "chef/log"
-require "chef/mixin/command"
require "chef/provider"
class Chef
class Provider
class Cron < Chef::Provider
- include Chef::Mixin::Command
provides :cron, os: ["!aix", "!solaris2"]
@@ -202,30 +200,18 @@ class Chef
end
def read_crontab
- crontab = nil
- status = popen4("crontab -l -u #{new_resource.user}") do |pid, stdin, stdout, stderr|
- crontab = stdout.read
- end
- if status.exitstatus > 1
- raise Chef::Exceptions::Cron, "Error determining state of #{new_resource.name}, exit: #{status.exitstatus}"
- end
- crontab
+ so = shell_out!("crontab -l -u #{new_resource.user}", returns: [0, 1])
+ return nil if so.exitstatus == 1
+ so.stdout
+ rescue => e
+ raise Chef::Exceptions::Cron, "Error determining state of #{new_resource.name}, error: #{e}"
end
def write_crontab(crontab)
write_exception = false
- status = popen4("crontab -u #{new_resource.user} -", :waitlast => true) do |pid, stdin, stdout, stderr|
- begin
- stdin.write crontab
- rescue Errno::EPIPE => e
- # popen4 could yield while child has already died.
- write_exception = true
- Chef::Log.debug("#{e.message}")
- end
- end
- if status.exitstatus > 0 || write_exception
- raise Chef::Exceptions::Cron, "Error updating state of #{new_resource.name}, exit: #{status.exitstatus}"
- end
+ so = shell_out!("crontab -u #{new_resource.user} -", input: crontab)
+ rescue => e
+ raise Chef::Exceptions::Cron, "Error updating state of #{new_resource.name}, error: #{e}"
end
def get_crontab_entry
diff --git a/lib/chef/provider/deploy.rb b/lib/chef/provider/deploy.rb
index 172705ac71..c4229d2441 100644
--- a/lib/chef/provider/deploy.rb
+++ b/lib/chef/provider/deploy.rb
@@ -16,7 +16,6 @@
# limitations under the License.
#
-require "chef/mixin/command"
require "chef/mixin/from_file"
require "chef/provider/git"
require "chef/provider/subversion"
@@ -29,7 +28,6 @@ class Chef
include Chef::DSL::Recipe
include Chef::Mixin::FromFile
- include Chef::Mixin::Command
attr_reader :scm_provider, :release_path, :shared_path, :previous_release_path
diff --git a/lib/chef/provider/env.rb b/lib/chef/provider/env.rb
index 7777da183d..490fa31146 100644
--- a/lib/chef/provider/env.rb
+++ b/lib/chef/provider/env.rb
@@ -17,13 +17,11 @@
#
require "chef/provider"
-require "chef/mixin/command"
require "chef/resource/env"
class Chef
class Provider
class Env < Chef::Provider
- include Chef::Mixin::Command
attr_accessor :key_exists
provides :env, os: "!windows"
diff --git a/lib/chef/provider/erl_call.rb b/lib/chef/provider/erl_call.rb
index 26ac19d03b..b73341bb16 100644
--- a/lib/chef/provider/erl_call.rb
+++ b/lib/chef/provider/erl_call.rb
@@ -17,13 +17,11 @@
#
require "chef/log"
-require "chef/mixin/command"
require "chef/provider"
class Chef
class Provider
class ErlCall < Chef::Provider
- include Chef::Mixin::Command
provides :erl_call
@@ -58,44 +56,18 @@ class Chef
command = "erl_call -e #{distributed} #{node} #{cookie}"
converge_by("run erlang block") do
- begin
- pid, stdin, stdout, stderr = popen4(command, :waitlast => true)
+ so = shell_out!(command, input: new_resource.code)
- Chef::Log.debug("#{new_resource} running")
- Chef::Log.debug("#{new_resource} command: #{command}")
- Chef::Log.debug("#{new_resource} code: #{new_resource.code}")
-
- new_resource.code.each_line { |line| stdin.puts(line.chomp) }
-
- stdin.close
-
- Chef::Log.debug("#{new_resource} output: ")
-
- stdout_output = ""
- stdout.each_line { |line| stdout_output << line }
- stdout.close
-
- stderr_output = ""
- stderr.each_line { |line| stderr_output << line }
- stderr.close
-
- # fail if stderr contains anything
- if stderr_output.length > 0
- raise Chef::Exceptions::ErlCall, stderr_output
- end
-
- # fail if the first 4 characters aren't "{ok,"
- unless stdout_output[0..3].include?("{ok,")
- raise Chef::Exceptions::ErlCall, stdout_output
- end
-
- new_resource.updated_by_last_action(true)
+ # fail if stderr contains anything
+ if so.stderr.length > 0
+ raise Chef::Exceptions::ErlCall, so.stderr
+ end
- Chef::Log.debug("#{new_resource} #{stdout_output}")
- Chef::Log.info("#{@new_resouce} ran successfully")
- ensure
- Process.wait(pid) if pid
+ # fail if the first 4 characters aren't "{ok,"
+ unless so.stdout[0..3].include?("{ok,")
+ raise Chef::Exceptions::ErlCall, so.stdout
end
+
end
end
diff --git a/lib/chef/provider/group.rb b/lib/chef/provider/group.rb
index 82196c72f3..ce20a2b5e5 100644
--- a/lib/chef/provider/group.rb
+++ b/lib/chef/provider/group.rb
@@ -18,14 +18,12 @@
require "chef/provider"
require "chef/mixin/shell_out"
-require "chef/mixin/command"
require "etc"
class Chef
class Provider
class Group < Chef::Provider
include Chef::Mixin::ShellOut
- include Chef::Mixin::Command
attr_accessor :group_exists
attr_accessor :change_desc
diff --git a/lib/chef/provider/ifconfig.rb b/lib/chef/provider/ifconfig.rb
index 003cc3b0e0..16bbe8124b 100644
--- a/lib/chef/provider/ifconfig.rb
+++ b/lib/chef/provider/ifconfig.rb
@@ -17,7 +17,6 @@
#
require "chef/log"
-require "chef/mixin/command"
require "chef/mixin/shell_out"
require "chef/provider"
require "chef/resource/file"
@@ -42,7 +41,6 @@ class Chef
provides :ifconfig
include Chef::Mixin::ShellOut
- include Chef::Mixin::Command
attr_accessor :config_template
attr_accessor :config_path
diff --git a/lib/chef/provider/ifconfig/redhat.rb b/lib/chef/provider/ifconfig/redhat.rb
index 841e725b94..8af9f10f67 100644
--- a/lib/chef/provider/ifconfig/redhat.rb
+++ b/lib/chef/provider/ifconfig/redhat.rb
@@ -22,7 +22,7 @@ class Chef
class Provider
class Ifconfig
class Redhat < Chef::Provider::Ifconfig
- provides :ifconfig, platform_family: %w{fedora rhel}
+ provides :ifconfig, platform_family: %w{fedora rhel amazon}
def initialize(new_resource, run_context)
super(new_resource, run_context)
diff --git a/lib/chef/provider/launchd.rb b/lib/chef/provider/launchd.rb
index a58954c707..9c368c2b48 100644
--- a/lib/chef/provider/launchd.rb
+++ b/lib/chef/provider/launchd.rb
@@ -85,6 +85,10 @@ class Chef
manage_service(:disable)
end
+ def action_restart
+ manage_service(:restart)
+ end
+
def manage_plist(action)
if source
res = cookbook_file_resource
diff --git a/lib/chef/provider/lwrp_base.rb b/lib/chef/provider/lwrp_base.rb
index cbf25f1e4f..09f90b7403 100644
--- a/lib/chef/provider/lwrp_base.rb
+++ b/lib/chef/provider/lwrp_base.rb
@@ -75,18 +75,9 @@ class Chef
LWRPBase.loaded_lwrps[filename] = true
- Chef::Provider.register_deprecated_lwrp_class(provider_class, convert_to_class_name(resource_name))
-
provider_class
end
- # DSL for defining a provider's actions.
- def action(name, &block)
- define_method("action_#{name}") do
- instance_eval(&block)
- end
- end
-
protected
def loaded_lwrps
diff --git a/lib/chef/provider/mdadm.rb b/lib/chef/provider/mdadm.rb
index 5c972462bc..7d7b26acfa 100644
--- a/lib/chef/provider/mdadm.rb
+++ b/lib/chef/provider/mdadm.rb
@@ -25,10 +25,6 @@ class Chef
provides :mdadm
- def popen4
- raise Exception, "deprecated"
- end
-
def load_current_resource
@current_resource = Chef::Resource::Mdadm.new(new_resource.name)
current_resource.raid_device(new_resource.raid_device)
diff --git a/lib/chef/provider/ohai.rb b/lib/chef/provider/ohai.rb
index 0c2397cee5..42fc450271 100644
--- a/lib/chef/provider/ohai.rb
+++ b/lib/chef/provider/ohai.rb
@@ -21,8 +21,6 @@ require "ohai"
class Chef
class Provider
class Ohai < Chef::Provider
- use_inline_resources
-
provides :ohai
def load_current_resource
diff --git a/lib/chef/provider/osx_profile.rb b/lib/chef/provider/osx_profile.rb
index 8ecde54ce0..1d87f29eb2 100644
--- a/lib/chef/provider/osx_profile.rb
+++ b/lib/chef/provider/osx_profile.rb
@@ -25,7 +25,6 @@ require "uuidtools"
class Chef
class Provider
class OsxProfile < Chef::Provider
- include Chef::Mixin::Command
provides :osx_profile, os: "darwin"
provides :osx_config_profile, os: "darwin"
diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb
index 36df048741..4b73f47ed3 100644
--- a/lib/chef/provider/package.rb
+++ b/lib/chef/provider/package.rb
@@ -17,7 +17,6 @@
#
require "chef/mixin/shell_out"
-require "chef/mixin/command"
require "chef/mixin/subclass_directive"
require "chef/log"
require "chef/file_cache"
@@ -28,12 +27,9 @@ require "shellwords"
class Chef
class Provider
class Package < Chef::Provider
- include Chef::Mixin::Command
include Chef::Mixin::ShellOut
extend Chef::Mixin::SubclassDirective
- use_inline_resources
-
# subclasses declare this if they want all their arguments as arrays of packages and names
subclass_directive :use_multipackage_api
# subclasses declare this if they want sources (filenames) pulled from their package names
@@ -54,11 +50,7 @@ class Chef
end
def options
- if new_resource.options.is_a?(String)
- new_resource.options.shellsplit
- else
- new_resource.options
- end
+ new_resource.options
end
def check_resource_semantics!
@@ -305,7 +297,11 @@ class Chef
def expand_options(options)
# its deprecated but still work to do to deprecate it fully
#Chef.deprecated(:package_misc, "expand_options is deprecated, use shell_out_compact or shell_out_compact_timeout instead")
- options ? " #{options}" : ""
+ if options
+ " #{options.is_a?(Array) ? Shellwords.join(options) : options}"
+ else
+ ""
+ end
end
# Check the current_version against either the candidate_version or the new_version
diff --git a/lib/chef/provider/package/aix.rb b/lib/chef/provider/package/aix.rb
index 5af5f5afad..b013b3d8ce 100644
--- a/lib/chef/provider/package/aix.rb
+++ b/lib/chef/provider/package/aix.rb
@@ -17,7 +17,6 @@
#
#
require "chef/provider/package"
-require "chef/mixin/command"
require "chef/resource/package"
require "chef/mixin/get_source_from_package"
diff --git a/lib/chef/provider/package/cab.rb b/lib/chef/provider/package/cab.rb
index d6e989eb72..3a8cc507f9 100644
--- a/lib/chef/provider/package/cab.rb
+++ b/lib/chef/provider/package/cab.rb
@@ -26,7 +26,6 @@ class Chef
class Provider
class Package
class Cab < Chef::Provider::Package
- use_inline_resources
include Chef::Mixin::ShellOut
include Chef::Mixin::Uris
include Chef::Mixin::Checksum
diff --git a/lib/chef/provider/package/dnf.rb b/lib/chef/provider/package/dnf.rb
index c551ae7cb0..42d679c940 100644
--- a/lib/chef/provider/package/dnf.rb
+++ b/lib/chef/provider/package/dnf.rb
@@ -35,7 +35,7 @@ class Chef
use_multipackage_api
use_package_name_for_source
- provides :package, platform_family: %w{rhel fedora} do
+ provides :package, platform_family: %w{rhel fedora amazon} do
which("dnf") && shell_out("rpm -q dnf").stdout =~ /^dnf-[1-9]/
end
diff --git a/lib/chef/provider/package/ips.rb b/lib/chef/provider/package/ips.rb
index 9666013cc3..d0c8bed175 100644
--- a/lib/chef/provider/package/ips.rb
+++ b/lib/chef/provider/package/ips.rb
@@ -19,7 +19,6 @@
require "open3"
require "chef/provider/package"
-require "chef/mixin/command"
require "chef/resource/package"
class Chef
diff --git a/lib/chef/provider/package/msu.rb b/lib/chef/provider/package/msu.rb
index fe4a11461f..15e18feba4 100644
--- a/lib/chef/provider/package/msu.rb
+++ b/lib/chef/provider/package/msu.rb
@@ -32,7 +32,6 @@ class Chef
class Provider
class Package
class Msu < Chef::Provider::Package
- use_inline_resources
include Chef::Mixin::ShellOut
include Chef::Mixin::Uris
include Chef::Mixin::Checksum
diff --git a/lib/chef/provider/package/pacman.rb b/lib/chef/provider/package/pacman.rb
index 25683687b2..d1830bdefa 100644
--- a/lib/chef/provider/package/pacman.rb
+++ b/lib/chef/provider/package/pacman.rb
@@ -17,7 +17,6 @@
#
require "chef/provider/package"
-require "chef/mixin/command"
require "chef/resource/package"
class Chef
diff --git a/lib/chef/provider/package/portage.rb b/lib/chef/provider/package/portage.rb
index fd96dfa47f..05a5df370e 100644
--- a/lib/chef/provider/package/portage.rb
+++ b/lib/chef/provider/package/portage.rb
@@ -17,7 +17,6 @@
#
require "chef/provider/package"
-require "chef/mixin/command"
require "chef/resource/package"
require "chef/util/path_helper"
diff --git a/lib/chef/provider/package/rpm.rb b/lib/chef/provider/package/rpm.rb
index 1701886191..7ec24f8c24 100644
--- a/lib/chef/provider/package/rpm.rb
+++ b/lib/chef/provider/package/rpm.rb
@@ -16,7 +16,6 @@
# limitations under the License.
#
require "chef/provider/package"
-require "chef/mixin/command"
require "chef/resource/package"
require "chef/mixin/get_source_from_package"
diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb
index 1019b8d3fa..69936b3d58 100644
--- a/lib/chef/provider/package/rubygems.rb
+++ b/lib/chef/provider/package/rubygems.rb
@@ -19,7 +19,6 @@
require "uri"
require "chef/provider/package"
-require "chef/mixin/command"
require "chef/resource/package"
require "chef/mixin/get_source_from_package"
@@ -424,6 +423,7 @@ class Chef
def source_is_remote?
return true if new_resource.source.nil?
+ return true if new_resource.source.is_a?(Array)
scheme = URI.parse(new_resource.source).scheme
# URI.parse gets confused by MS Windows paths with forward slashes.
scheme = nil if scheme =~ /^[a-z]$/
@@ -470,7 +470,9 @@ class Chef
end
def gem_sources
- new_resource.source ? Array(new_resource.source) : nil
+ srcs = [ new_resource.source ]
+ srcs << Chef::Config[:rubygems_url] if new_resource.include_default_source
+ srcs.flatten.compact
end
def load_current_resource
@@ -534,18 +536,18 @@ class Chef
end
def install_via_gem_command(name, version)
- if new_resource.source =~ /\.gem$/i
+ src = []
+ if new_resource.source.is_a?(String) && new_resource.source =~ /\.gem$/i
name = new_resource.source
- elsif new_resource.clear_sources
- src = " --clear-sources"
- src << (new_resource.source && " --source=#{new_resource.source}" || "")
else
- src = new_resource.source && " --source=#{new_resource.source} --source=#{Chef::Config[:rubygems_url]}"
+ src << "--clear-sources" if new_resource.clear_sources
+ src += gem_sources.map { |s| "--source=#{s}" }
end
+ src_str = src.empty? ? "" : " #{src.join(" ")}"
if !version.nil? && !version.empty?
- shell_out_with_timeout!("#{gem_binary_path} install #{name} -q --no-rdoc --no-ri -v \"#{version}\"#{src}#{opts}", env: nil)
+ shell_out_with_timeout!("#{gem_binary_path} install #{name} -q --no-rdoc --no-ri -v \"#{version}\"#{src_str}#{opts}", env: nil)
else
- shell_out_with_timeout!("#{gem_binary_path} install \"#{name}\" -q --no-rdoc --no-ri #{src}#{opts}", env: nil)
+ shell_out_with_timeout!("#{gem_binary_path} install \"#{name}\" -q --no-rdoc --no-ri #{src_str}#{opts}", env: nil)
end
end
diff --git a/lib/chef/provider/package/solaris.rb b/lib/chef/provider/package/solaris.rb
index 5537127310..f6e66c050a 100644
--- a/lib/chef/provider/package/solaris.rb
+++ b/lib/chef/provider/package/solaris.rb
@@ -16,7 +16,6 @@
# limitations under the License.
#
require "chef/provider/package"
-require "chef/mixin/command"
require "chef/resource/package"
require "chef/mixin/get_source_from_package"
diff --git a/lib/chef/provider/package/windows/msi.rb b/lib/chef/provider/package/windows/msi.rb
index 7e6048ce49..ef8b674b60 100644
--- a/lib/chef/provider/package/windows/msi.rb
+++ b/lib/chef/provider/package/windows/msi.rb
@@ -1,6 +1,6 @@
#
# Author:: Bryan McLellan <btm@loftninjas.org>
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb
index d37aa1fb73..d87e421409 100644
--- a/lib/chef/provider/package/yum.rb
+++ b/lib/chef/provider/package/yum.rb
@@ -1,6 +1,6 @@
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software, Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,7 +29,7 @@ class Chef
class Yum < Chef::Provider::Package
include Chef::Mixin::GetSourceFromPackage
- provides :package, platform_family: %w{rhel fedora}
+ provides :package, platform_family: %w{rhel fedora amazon}
provides :yum_package, os: "linux"
# Multipackage API
@@ -194,7 +194,7 @@ class Chef
def manage_extra_repo_control
if new_resource.options
repo_control = []
- new_resource.options.split.each do |opt|
+ new_resource.options.each do |opt|
repo_control << opt if opt =~ /--(enable|disable)repo=.+/
end
diff --git a/lib/chef/provider/package/zypper.rb b/lib/chef/provider/package/zypper.rb
index 45c6c91f60..7b8fd6c426 100644
--- a/lib/chef/provider/package/zypper.rb
+++ b/lib/chef/provider/package/zypper.rb
@@ -2,7 +2,7 @@
#
# Authors:: Adam Jacob (<adam@chef.io>)
# Ionuț Arțăriși (<iartarisi@suse.cz>)
-# Copyright:: Copyright 2008-2016, Chef Software, Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# Copyright 2013-2016, SUSE Linux GmbH
# License:: Apache License, Version 2.0
#
@@ -145,17 +145,7 @@ class Chef
end
def gpg_checks
- case Chef::Config[:zypper_check_gpg]
- when true
- nil
- when false
- "--no-gpg-checks"
- when nil
- Chef::Log.warn("Chef::Config[:zypper_check_gpg] was not set. " \
- "All packages will be installed without gpg signature checks. " \
- "This is a security hazard.")
- "--no-gpg-checks"
- end
+ "--no-gpg-checks" unless new_resource.gpg_check
end
end
end
diff --git a/lib/chef/provider/route.rb b/lib/chef/provider/route.rb
index 2e2a1266b4..59d516be6a 100644
--- a/lib/chef/provider/route.rb
+++ b/lib/chef/provider/route.rb
@@ -17,14 +17,12 @@
#
require "chef/log"
-require "chef/mixin/command"
require "chef/provider"
require "ipaddr"
class Chef
class Provider
class Route < Chef::Provider
- include Chef::Mixin::Command
provides :route
diff --git a/lib/chef/provider/service.rb b/lib/chef/provider/service.rb
index 11d04eaca2..34ecf2f0bc 100644
--- a/lib/chef/provider/service.rb
+++ b/lib/chef/provider/service.rb
@@ -17,15 +17,12 @@
# limitations under the License.
#
-require "chef/mixin/command"
require "chef/provider"
class Chef
class Provider
class Service < Chef::Provider
- include Chef::Mixin::Command
-
def supports
@supports ||= new_resource.supports.dup
end
@@ -248,7 +245,7 @@ class Chef
Chef.set_provider_priority_array :service, [ Systemd, Arch ], platform_family: "arch"
Chef.set_provider_priority_array :service, [ Systemd, Gentoo ], platform_family: "gentoo"
Chef.set_provider_priority_array :service, [ Systemd, Upstart, Insserv, Debian, Invokercd ], platform_family: "debian"
- Chef.set_provider_priority_array :service, [ Systemd, Insserv, Redhat ], platform_family: %w{rhel fedora suse}
+ Chef.set_provider_priority_array :service, [ Systemd, Insserv, Redhat ], platform_family: %w{rhel fedora suse amazon}
end
end
end
diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb
index 9d11032055..58a43d27f8 100644
--- a/lib/chef/provider/service/debian.rb
+++ b/lib/chef/provider/service/debian.rb
@@ -1,6 +1,6 @@
#
# Author:: AJ Christensen (<aj@hjksolutions.com>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,8 +35,6 @@ class Chef
def load_current_resource
super
- @priority_success = true
- @rcd_status = nil
current_resource.priority(get_priority)
current_resource.enabled(service_currently_enabled?(current_resource.priority))
current_resource
@@ -54,8 +52,8 @@ class Chef
end
requirements.assert(:all_actions) do |a|
- a.assertion { @priority_success }
- a.failure_message Chef::Exceptions::Service, "/usr/sbin/update-rc.d -n -f #{current_resource.service_name} failed - #{@rcd_status.inspect}"
+ a.assertion { @so_priority.exitstatus == 0 }
+ a.failure_message Chef::Exceptions::Service, "/usr/sbin/update-rc.d -n -f #{current_resource.service_name} failed - #{@so_priority.inspect}"
# This can happen if the service is not yet installed,so we'll fake it.
a.whyrun ["Unable to determine priority of service, assuming service would have been correctly installed earlier in the run.",
"Assigning temporary priorities to continue.",
@@ -75,19 +73,18 @@ class Chef
def get_priority
priority = {}
- @rcd_status = popen4("/usr/sbin/update-rc.d -n -f #{current_resource.service_name} remove") do |pid, stdin, stdout, stderr|
-
- [stdout, stderr].each do |iop|
- iop.each_line do |line|
- if UPDATE_RC_D_PRIORITIES =~ line
- # priority[runlevel] = [ S|K, priority ]
- # S = Start, K = Kill
- # debian runlevels: 0 Halt, 1 Singleuser, 2 Multiuser, 3-5 == 2, 6 Reboot
- priority[$1] = [($2 == "S" ? :start : :stop), $3]
- end
- if line =~ UPDATE_RC_D_ENABLED_MATCHES
- enabled = true
- end
+ @so_priority = shell_out!("/usr/sbin/update-rc.d -n -f #{current_resource.service_name} remove")
+
+ [@so_priority.stdout, @so_priority.stderr].each do |iop|
+ iop.each_line do |line|
+ if UPDATE_RC_D_PRIORITIES =~ line
+ # priority[runlevel] = [ S|K, priority ]
+ # S = Start, K = Kill
+ # debian runlevels: 0 Halt, 1 Singleuser, 2 Multiuser, 3-5 == 2, 6 Reboot
+ priority[$1] = [($2 == "S" ? :start : :stop), $3]
+ end
+ if line =~ UPDATE_RC_D_ENABLED_MATCHES
+ enabled = true
end
end
end
@@ -98,9 +95,6 @@ class Chef
priority = priority[2].last
end
- unless @rcd_status.exitstatus == 0
- @priority_success = false
- end
priority
end
diff --git a/lib/chef/provider/service/freebsd.rb b/lib/chef/provider/service/freebsd.rb
index 9746dfdef0..c1e315afee 100644
--- a/lib/chef/provider/service/freebsd.rb
+++ b/lib/chef/provider/service/freebsd.rb
@@ -18,7 +18,6 @@
require "chef/resource/service"
require "chef/provider/service/init"
-require "chef/mixin/command"
class Chef
class Provider
diff --git a/lib/chef/provider/service/gentoo.rb b/lib/chef/provider/service/gentoo.rb
index 7bb57113ac..0ac74649b6 100644
--- a/lib/chef/provider/service/gentoo.rb
+++ b/lib/chef/provider/service/gentoo.rb
@@ -18,7 +18,6 @@
#
require "chef/provider/service/init"
-require "chef/mixin/command"
require "chef/util/path_helper"
class Chef::Provider::Service::Gentoo < Chef::Provider::Service::Init
diff --git a/lib/chef/provider/service/init.rb b/lib/chef/provider/service/init.rb
index dff627d016..c6c582f8b8 100644
--- a/lib/chef/provider/service/init.rb
+++ b/lib/chef/provider/service/init.rb
@@ -17,7 +17,6 @@
#
require "chef/provider/service/simple"
-require "chef/mixin/command"
require "chef/platform/service_helpers"
class Chef
diff --git a/lib/chef/provider/service/insserv.rb b/lib/chef/provider/service/insserv.rb
index c3dca10495..a8e841f8b3 100644
--- a/lib/chef/provider/service/insserv.rb
+++ b/lib/chef/provider/service/insserv.rb
@@ -1,6 +1,6 @@
#
# Author:: Bryan McLellan <btm@loftninjas.org>
-# Copyright:: Copyright 2011-2016, Chef Software Inc.
+# Copyright:: Copyright 2011-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,7 +24,7 @@ class Chef
class Service
class Insserv < Chef::Provider::Service::Init
- provides :service, platform_family: %w{debian rhel fedora suse} do |node|
+ provides :service, platform_family: %w{debian rhel fedora suse amazon} do |node|
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:insserv)
end
diff --git a/lib/chef/provider/service/openbsd.rb b/lib/chef/provider/service/openbsd.rb
index 780337e1b6..f839d54780 100644
--- a/lib/chef/provider/service/openbsd.rb
+++ b/lib/chef/provider/service/openbsd.rb
@@ -16,7 +16,6 @@
# limitations under the License.
#
-require "chef/mixin/command"
require "chef/mixin/shell_out"
require "chef/provider/service/init"
require "chef/resource/service"
diff --git a/lib/chef/provider/service/redhat.rb b/lib/chef/provider/service/redhat.rb
index 21ab678706..1da3d7c01a 100644
--- a/lib/chef/provider/service/redhat.rb
+++ b/lib/chef/provider/service/redhat.rb
@@ -1,6 +1,6 @@
#
# Author:: AJ Christensen (<aj@hjksolutions.com>)
-# Copyright:: Copyright 2008-2016, Chef Software, Inc.
+# Copyright:: Copyright 2008-2017, 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
# @api private
attr_accessor :current_run_levels
- provides :service, platform_family: %w{rhel fedora suse} do |node|
+ provides :service, platform_family: %w{rhel fedora suse amazon} do |node|
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat)
end
diff --git a/lib/chef/provider/service/simple.rb b/lib/chef/provider/service/simple.rb
index 84ced52071..81ac970b87 100644
--- a/lib/chef/provider/service/simple.rb
+++ b/lib/chef/provider/service/simple.rb
@@ -18,7 +18,6 @@
require "chef/provider/service"
require "chef/resource/service"
-require "chef/mixin/command"
class Chef
class Provider
diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb
index c560bed011..9c85fda05f 100644
--- a/lib/chef/provider/service/solaris.rb
+++ b/lib/chef/provider/service/solaris.rb
@@ -18,7 +18,6 @@
require "chef/provider/service"
require "chef/resource/service"
-require "chef/mixin/command"
class Chef
class Provider
diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb
index 9c0d97d376..9783b3b3a5 100644
--- a/lib/chef/provider/service/upstart.rb
+++ b/lib/chef/provider/service/upstart.rb
@@ -18,7 +18,6 @@
require "chef/resource/service"
require "chef/provider/service/simple"
-require "chef/mixin/command"
require "chef/util/file_edit"
class Chef
@@ -241,17 +240,16 @@ class Chef
def upstart_goal_state
command = "/sbin/status #{@job}"
- status = popen4(command) do |pid, stdin, stdout, stderr|
- stdout.each_line do |line|
- # service goal/state
- # OR
- # service (instance) goal/state
- # OR
- # service (goal) state
- line =~ UPSTART_STATE_FORMAT
- data = Regexp.last_match
- return data[1]
- end
+ so = shell_out(command)
+ so.stdout.each_line do |line|
+ # service goal/state
+ # OR
+ # service (instance) goal/state
+ # OR
+ # service (goal) state
+ line =~ UPSTART_STATE_FORMAT
+ data = Regexp.last_match
+ return data[1]
end
end
diff --git a/lib/chef/provider/subversion.rb b/lib/chef/provider/subversion.rb
index d7e26f3968..4fece0ae40 100644
--- a/lib/chef/provider/subversion.rb
+++ b/lib/chef/provider/subversion.rb
@@ -20,7 +20,6 @@
require "chef/log"
require "chef/provider"
-require "chef/mixin/command"
require "chef-config/mixin/fuzzy_hostname_matcher"
require "fileutils"
@@ -32,7 +31,6 @@ class Chef
SVN_INFO_PATTERN = /^([\w\s]+): (.+)$/
- include Chef::Mixin::Command
include ChefConfig::Mixin::FuzzyHostnameMatcher
def load_current_resource
diff --git a/lib/chef/provider/systemd_unit.rb b/lib/chef/provider/systemd_unit.rb
index 5175dc6be9..143efe7b91 100644
--- a/lib/chef/provider/systemd_unit.rb
+++ b/lib/chef/provider/systemd_unit.rb
@@ -194,7 +194,7 @@ class Chef
f.group "root"
f.mode "0644"
f.content new_resource.to_ini
- f.verify :systemd_unit
+ f.verify :systemd_unit if new_resource.verify
end.run_action(action)
end
diff --git a/lib/chef/provider/template/content.rb b/lib/chef/provider/template/content.rb
index acf200621d..b40794564a 100644
--- a/lib/chef/provider/template/content.rb
+++ b/lib/chef/provider/template/content.rb
@@ -36,7 +36,30 @@ class Chef
private
def file_for_provider
- context = TemplateContext.new(new_resource.variables)
+ # Deal with any DelayedEvaluator values in the template variables.
+ visitor = lambda do |obj|
+ case obj
+ when Hash
+ # If this is an Attribute object, we need to change class otherwise
+ # we get the immutable behavior. This could probably be fixed by
+ # using Hash#transform_values once we only support Ruby 2.4.
+ obj_class = obj.is_a?(Chef::Node::ImmutableMash) ? Mash : obj.class
+ # Avoid mutating hashes in the resource in case we're changing anything.
+ obj.each_with_object(obj_class.new) do |(key, value), memo|
+ memo[key] = visitor.call(value)
+ end
+ when Array
+ # Avoid mutating arrays in the resource in case we're changing anything.
+ obj.map { |value| visitor.call(value) }
+ when DelayedEvaluator
+ new_resource.instance_eval(&obj)
+ else
+ obj
+ end
+ end
+ variables = visitor.call(new_resource.variables)
+
+ context = TemplateContext.new(variables)
context[:node] = run_context.node
context[:template_finder] = template_finder
diff --git a/lib/chef/provider/user.rb b/lib/chef/provider/user.rb
index dcfee22c31..abdff441a5 100644
--- a/lib/chef/provider/user.rb
+++ b/lib/chef/provider/user.rb
@@ -17,13 +17,11 @@
#
require "chef/provider"
-require "chef/mixin/command"
require "etc"
class Chef
class Provider
class User < Chef::Provider
- include Chef::Mixin::Command
attr_accessor :user_exists, :locked
diff --git a/lib/chef/provider/user/linux.rb b/lib/chef/provider/user/linux.rb
index cf75bdc38b..2db6c218bd 100644
--- a/lib/chef/provider/user/linux.rb
+++ b/lib/chef/provider/user/linux.rb
@@ -58,6 +58,7 @@ class Chef
def usermod_options
opts = []
+ opts += [ "-u", new_resource.uid ] if new_resource.non_unique
if updating_home?
if new_resource.manage_home
opts << "-m"
diff --git a/lib/chef/provider/user/pw.rb b/lib/chef/provider/user/pw.rb
index cf47bb7fde..06bd221d26 100644
--- a/lib/chef/provider/user/pw.rb
+++ b/lib/chef/provider/user/pw.rb
@@ -94,13 +94,7 @@ class Chef
if !new_resource.password.nil? && (current_resource.password != new_resource.password)
Chef::Log.debug("#{new_resource} updating password")
command = "pw usermod #{new_resource.username} -H 0"
- status = popen4(command, waitlast: true) do |pid, stdin, stdout, stderr|
- stdin.puts new_resource.password.to_s
- end
-
- unless status.exitstatus == 0
- raise Chef::Exceptions::User, "pw failed - #{status.inspect}!"
- end
+ shell_out!(command, input: new_resource.password.to_s)
else
Chef::Log.debug("#{new_resource} no change needed to password")
end
diff --git a/lib/chef/provider/windows_task.rb b/lib/chef/provider/windows_task.rb
new file mode 100644
index 0000000000..a96d4b2b7e
--- /dev/null
+++ b/lib/chef/provider/windows_task.rb
@@ -0,0 +1,418 @@
+#
+# Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
+# Copyright:: Copyright 2008-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/mixin/shell_out"
+require "rexml/document"
+require "iso8601"
+require "chef/mixin/powershell_out"
+
+class Chef
+ class Provider
+ class WindowsTask < Chef::Provider
+ include Chef::Mixin::ShellOut
+ include Chef::Mixin::PowershellOut
+
+ provides :windows_task, os: "windows"
+
+ def load_current_resource
+ @current_resource = Chef::Resource::WindowsTask.new(new_resource.name)
+ pathed_task_name = new_resource.task_name.start_with?('\\') ? new_resource.task_name : "\\#{new_resource.task_name}"
+
+ @current_resource.task_name(pathed_task_name)
+ task_hash = load_task_hash(pathed_task_name)
+
+ set_current_resource(task_hash) if task_hash.respond_to?(:[]) && task_hash[:TaskName] == pathed_task_name
+ @current_resource
+ end
+
+ def set_current_resource(task_hash)
+ @current_resource.exists = true
+ @current_resource.command(task_hash[:TaskToRun])
+ @current_resource.cwd(task_hash[:StartIn]) unless task_hash[:StartIn] == "N/A"
+ @current_resource.user(task_hash[:RunAsUser])
+ set_current_run_level task_hash[:run_level]
+ set_current_frequency task_hash
+ @current_resource.day(task_hash[:day]) if task_hash[:day]
+ @current_resource.months(task_hash[:months]) if task_hash[:months]
+ set_current_idle_time(task_hash[:idle_time]) if task_hash[:idle_time]
+ @current_resource.random_delay(task_hash[:random_delay]) if task_hash[:random_delay]
+ @current_resource.execution_time_limit(task_hash[:execution_time_limit]) if task_hash[:execution_time_limit]
+
+ @current_resource.status = :running if task_hash[:Status] == "Running"
+ @current_resource.enabled = true if task_hash[:ScheduledTaskState] == "Enabled"
+ end
+
+ def action_create
+ if @current_resource.exists && !(task_need_update? || @new_resource.force)
+ Chef::Log.info "#{@new_resource} task already exists - nothing to do"
+ else
+ options = {}
+ options["F"] = "" if @new_resource.force || task_need_update?
+ options["SC"] = schedule
+ options["MO"] = @new_resource.frequency_modifier if frequency_modifier_allowed
+ options["I"] = @new_resource.idle_time unless @new_resource.idle_time.nil?
+ options["SD"] = @new_resource.start_day unless @new_resource.start_day.nil?
+ options["ST"] = @new_resource.start_time unless @new_resource.start_time.nil?
+ options["TR"] = @new_resource.command
+ options["RU"] = @new_resource.user
+ options["RP"] = @new_resource.password if use_password?
+ options["RL"] = "HIGHEST" if @new_resource.run_level == :highest
+ options["IT"] = "" if @new_resource.interactive_enabled
+ options["D"] = @new_resource.day if @new_resource.day
+ options["M"] = @new_resource.months unless @new_resource.months.nil?
+
+ run_schtasks "CREATE", options
+ xml_options = []
+ xml_options << "cwd" if new_resource.cwd
+ xml_options << "random_delay" if new_resource.random_delay
+ xml_options << "execution_time_limit" if new_resource.execution_time_limit
+ update_task_xml(xml_options) unless xml_options.empty?
+
+ new_resource.updated_by_last_action true
+ Chef::Log.info "#{@new_resource} task created"
+ end
+ end
+
+ def action_run
+ if @current_resource.exists
+ if @current_resource.status == :running
+ Chef::Log.info "#{@new_resource} task is currently running, skipping run"
+ else
+ run_schtasks "RUN"
+ new_resource.updated_by_last_action true
+ Chef::Log.info "#{@new_resource} task ran"
+ end
+ else
+ Chef::Log.warn "#{@new_resource} task doesn't exists - nothing to do"
+ end
+ end
+
+ def action_delete
+ if @current_resource.exists
+ # always need to force deletion
+ run_schtasks "DELETE", "F" => ""
+ new_resource.updated_by_last_action true
+ Chef::Log.info "#{@new_resource} task deleted"
+ else
+ Chef::Log.warn "#{@new_resource} task doesn't exists - nothing to do"
+ end
+ end
+
+ def action_end
+ if @current_resource.exists
+ if @current_resource.status != :running
+ Chef::Log.debug "#{@new_resource} is not running - nothing to do"
+ else
+ run_schtasks "END"
+ @new_resource.updated_by_last_action true
+ Chef::Log.info "#{@new_resource} task ended"
+ end
+ else
+ Chef::Log.warn "#{@new_resource} task doesn't exist - nothing to do"
+ end
+ end
+
+ def action_enable
+ if @current_resource.exists
+ if @current_resource.enabled
+ Chef::Log.debug "#{@new_resource} already enabled - nothing to do"
+ else
+ run_schtasks "CHANGE", "ENABLE" => ""
+ @new_resource.updated_by_last_action true
+ Chef::Log.info "#{@new_resource} task enabled"
+ end
+ else
+ Chef::Log.fatal "#{@new_resource} task doesn't exist - nothing to do"
+ raise Errno::ENOENT, "#{@new_resource}: task does not exist, cannot enable"
+ end
+ end
+
+ def action_disable
+ if @current_resource.exists
+ if @current_resource.enabled
+ run_schtasks "CHANGE", "DISABLE" => ""
+ @new_resource.updated_by_last_action true
+ Chef::Log.info "#{@new_resource} task disabled"
+ else
+ Chef::Log.warn "#{@new_resource} already disabled - nothing to do"
+ end
+ else
+ Chef::Log.warn "#{@new_resource} task doesn't exist - nothing to do"
+ end
+ end
+
+ private
+
+ # rubocop:disable Style/StringLiteralsInInterpolation
+ def run_schtasks(task_action, options = {})
+ cmd = "schtasks /#{task_action} /TN \"#{@new_resource.task_name}\" "
+ options.keys.each do |option|
+ cmd += "/#{option} "
+ cmd += "\"#{options[option].to_s.gsub('"', "\\\"")}\" " unless options[option] == ""
+ end
+ Chef::Log.debug("running: ")
+ Chef::Log.debug(" #{cmd}")
+ shell_out!(cmd, returns: [0])
+ end
+ # rubocop:enable Style/StringLiteralsInInterpolation
+
+ def task_need_update?
+ return true if @current_resource.command != @new_resource.command.tr("'", '"') ||
+ @current_resource.user != @new_resource.user ||
+ @current_resource.run_level != @new_resource.run_level ||
+ @current_resource.cwd != @new_resource.cwd ||
+ @current_resource.frequency_modifier != @new_resource.frequency_modifier ||
+ @current_resource.frequency != @new_resource.frequency ||
+ @current_resource.idle_time != @new_resource.idle_time ||
+ @current_resource.random_delay != @new_resource.random_delay ||
+ @current_resource.execution_time_limit != @new_resource.execution_time_limit ||
+ !@new_resource.start_day.nil? || !@new_resource.start_time.nil?
+
+ begin
+ return true if @new_resource.day.to_s.casecmp(@current_resource.day.to_s) != 0 ||
+ @new_resource.months.to_s.casecmp(@current_resource.months.to_s) != 0
+ rescue
+ Chef::Log.debug "caught a raise in task_needs_update?"
+ end
+
+ false
+ end
+
+ def update_task_xml(options = [])
+ # random_delay xml element is different for different frequencies
+ random_delay_xml_element = {
+ :minute => "Triggers/TimeTrigger/RandomDelay",
+ :hourly => "Triggers/TimeTrigger/RandomDelay",
+ :once => "Triggers/TimeTrigger/RandomDelay",
+ :daily => "Triggers/CalendarTrigger/RandomDelay",
+ :weekly => "Triggers/CalendarTrigger/RandomDelay",
+ :monthly => "Triggers/CalendarTrigger/RandomDelay",
+ }
+
+ xml_element_mapping = {
+ "cwd" => "Actions/Exec/WorkingDirectory",
+ "random_delay" => random_delay_xml_element[@new_resource.frequency],
+ "execution_time_limit" => "Settings/ExecutionTimeLimit",
+ }
+
+ Chef::Log.debug "looking for existing tasks"
+
+ task_script = <<-EOH
+ [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
+ schtasks /Query /TN \"#{@new_resource.task_name}\" /XML
+ EOH
+ xml_cmd = powershell_out(task_script)
+
+ return if xml_cmd.exitstatus != 0
+
+ doc = REXML::Document.new(xml_cmd.stdout)
+
+ options.each do |option|
+ Chef::Log.debug 'Removing former #{option} if any'
+ doc.root.elements.delete(xml_element_mapping[option])
+ option_value = @new_resource.send("#{option}")
+
+ if option_value
+ Chef::Log.debug "Setting #option as #option_value"
+ split_xml_path = xml_element_mapping[option].split("/") # eg. if xml_element_mapping[option] = "Actions/Exec/WorkingDirectory"
+ element_name = split_xml_path.last # element_name = "WorkingDirectory"
+ cwd_element = REXML::Element.new(element_name)
+ cwd_element.add_text(option_value)
+ element_root = (split_xml_path - [element_name]).join("/") # element_root = 'Actions/Exec'
+ exec_element = doc.root.elements[element_root]
+ exec_element.add_element(cwd_element)
+ end
+ end
+
+ temp_task_file = ::File.join(ENV["TEMP"], "windows_task.xml")
+ begin
+ ::File.open(temp_task_file, "w:UTF-16LE") do |f|
+ doc.write(f)
+ end
+
+ options = {}
+ options["RU"] = @new_resource.user if @new_resource.user
+ options["RP"] = @new_resource.password if @new_resource.password
+ options["IT"] = "" if @new_resource.interactive_enabled
+ options["XML"] = temp_task_file
+
+ run_schtasks("DELETE", "F" => "")
+ run_schtasks("CREATE", options)
+ ensure
+ ::File.delete(temp_task_file)
+ end
+ end
+
+ def load_task_hash(task_name)
+ Chef::Log.debug "Looking for existing tasks"
+
+ task_script = <<-EOH
+ [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
+ schtasks /Query /FO LIST /V /TN \"#{task_name}\"
+ EOH
+
+ output = powershell_out(task_script).stdout.force_encoding("UTF-8")
+ if output.empty?
+ task = false
+ else
+ task = {}
+
+ output.split("\n").map! do |line|
+ line.split(": ").map!(&:strip)
+ end.each do |field|
+ if field.is_a?(Array) && field[0].respond_to?(:to_sym)
+ key = (field - [field.last]).join(": ")
+ task[key.gsub(/\s+/, "").to_sym] = field.last
+ end
+ end
+ end
+
+ task_xml = load_task_xml task_name
+ task.merge!(task_xml) if task && task_xml
+
+ task
+ end
+
+ def load_task_xml(task_name)
+ task_script = <<-EOH
+ [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
+ schtasks /Query /TN \"#{task_name}\" /XML
+ EOH
+ xml_cmd = powershell_out(task_script)
+
+ return if xml_cmd.exitstatus != 0
+
+ doc = REXML::Document.new(xml_cmd.stdout)
+ root = doc.root
+
+ task = {}
+ task[:run_level] = root.elements["Principals/Principal/RunLevel"].text if root.elements["Principals/Principal/RunLevel"]
+
+ # for frequency = :minutes, :hourly
+ task[:repetition_interval] = root.elements["Triggers/TimeTrigger/Repetition/Interval"].text if root.elements["Triggers/TimeTrigger/Repetition/Interval"]
+
+ # for frequency = :daily
+ task[:schedule_by_day] = root.elements["Triggers/CalendarTrigger/ScheduleByDay/DaysInterval"].text if root.elements["Triggers/CalendarTrigger/ScheduleByDay/DaysInterval"]
+
+ # for frequency = :weekly
+ task[:schedule_by_week] = root.elements["Triggers/CalendarTrigger/ScheduleByWeek/WeeksInterval"].text if root.elements["Triggers/CalendarTrigger/ScheduleByWeek/WeeksInterval"]
+ if root.elements["Triggers/CalendarTrigger/ScheduleByWeek/DaysOfWeek"]
+ task[:day] = []
+ root.elements["Triggers/CalendarTrigger/ScheduleByWeek/DaysOfWeek"].elements.each do |e|
+ task[:day] << e.to_s[0..3].delete("<").delete("/>")
+ end
+ task[:day] = task[:day].join(", ")
+ end
+
+ # for frequency = :monthly
+ task[:schedule_by_month] = root.elements["Triggers/CalendarTrigger/ScheduleByMonth/DaysOfMonth/Day"].text if root.elements["Triggers/CalendarTrigger/ScheduleByMonth/DaysOfMonth/Day"]
+ if root.elements["Triggers/CalendarTrigger/ScheduleByMonth/Months"]
+ task[:months] = []
+ root.elements["Triggers/CalendarTrigger/ScheduleByMonth/Months"].elements.each do |e|
+ task[:months] << e.to_s[0..3].delete("<").delete("/>")
+ end
+ task[:months] = task[:months].join(", ")
+ end
+
+ task[:on_logon] = true if root.elements["Triggers/LogonTrigger"]
+ task[:onstart] = true if root.elements["Triggers/BootTrigger"]
+ task[:on_idle] = true if root.elements["Triggers/IdleTrigger"]
+
+ task[:idle_time] = root.elements["Settings/IdleSettings/Duration"].text if root.elements["Settings/IdleSettings/Duration"] && task[:on_idle]
+
+ task[:once] = true if !(task[:repetition_interval] || task[:schedule_by_day] || task[:schedule_by_week] || task[:schedule_by_month] || task[:on_logon] || task[:onstart] || task[:on_idle])
+ task[:execution_time_limit] = root.elements["Settings/ExecutionTimeLimit"].text if root.elements["Settings/ExecutionTimeLimit"] #by default PT72H
+ task[:random_delay] = root.elements["Triggers/TimeTrigger/RandomDelay"].text if root.elements["Triggers/TimeTrigger/RandomDelay"]
+ task[:random_delay] = root.elements["Triggers/CalendarTrigger/RandomDelay"].text if root.elements["Triggers/CalendarTrigger/RandomDelay"]
+ task
+ end
+
+ SYSTEM_USERS = ['NT AUTHORITY\SYSTEM', "SYSTEM", 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', "USERS"].freeze
+
+ def use_password?
+ @use_password ||= !SYSTEM_USERS.include?(@new_resource.user.upcase)
+ end
+
+ def schedule
+ case @new_resource.frequency
+ when :on_logon
+ "ONLOGON"
+ when :on_idle
+ "ONIDLE"
+ else
+ @new_resource.frequency
+ end
+ end
+
+ def frequency_modifier_allowed
+ case @new_resource.frequency
+ when :minute, :hourly, :daily, :weekly
+ true
+ when :monthly
+ @new_resource.months.nil? || %w{ FIRST SECOND THIRD FOURTH LAST LASTDAY }.include?(@new_resource.frequency_modifier)
+ else
+ false
+ end
+ end
+
+ def set_current_run_level(run_level)
+ case run_level
+ when "HighestAvailable"
+ @current_resource.run_level(:highest)
+ when "LeastPrivilege"
+ @current_resource.run_level(:limited)
+ end
+ end
+
+ def set_current_frequency(task_hash)
+ if task_hash[:repetition_interval]
+ duration = ISO8601::Duration.new(task_hash[:repetition_interval])
+ if task_hash[:repetition_interval].include?("M")
+ @current_resource.frequency(:minute)
+ @current_resource.frequency_modifier(duration.minutes.atom.to_i)
+ elsif task_hash[:repetition_interval].include?("H")
+ @current_resource.frequency(:hourly)
+ @current_resource.frequency_modifier(duration.hours.atom.to_i)
+ end
+ end
+
+ if task_hash[:schedule_by_day]
+ @current_resource.frequency(:daily)
+ @current_resource.frequency_modifier(task_hash[:schedule_by_day].to_i)
+ end
+
+ if task_hash[:schedule_by_week]
+ @current_resource.frequency(:weekly)
+ @current_resource.frequency_modifier(task_hash[:schedule_by_week].to_i)
+ end
+
+ @current_resource.frequency(:monthly) if task_hash[:schedule_by_month]
+ @current_resource.frequency(:on_logon) if task_hash[:on_logon]
+ @current_resource.frequency(:onstart) if task_hash[:onstart]
+ @current_resource.frequency(:on_idle) if task_hash[:on_idle]
+ @current_resource.frequency(:once) if task_hash[:once]
+ end
+
+ def set_current_idle_time(idle_time)
+ duration = ISO8601::Duration.new(idle_time)
+ @current_resource.idle_time(duration.minutes.atom.to_i)
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/provider/yum_repository.rb b/lib/chef/provider/yum_repository.rb
index bcba8e676d..a5d3c2bc39 100644
--- a/lib/chef/provider/yum_repository.rb
+++ b/lib/chef/provider/yum_repository.rb
@@ -26,8 +26,6 @@ require "chef/provider/noop"
class Chef
class Provider
class YumRepository < Chef::Provider
- use_inline_resources
-
extend Chef::Mixin::Which
provides :yum_repository do
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index 0f19f56a8f..41de44a1d6 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -59,6 +59,7 @@ require "chef/provider/template"
require "chef/provider/user"
require "chef/provider/whyrun_safe_ruby_block"
require "chef/provider/yum_repository"
+require "chef/provider/windows_task"
require "chef/provider/env/windows"
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 9dc01a8d3a..ca6603c06a 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -909,17 +909,6 @@ class Chef
end
#
- # Set whether this class was updated during an action.
- #
- # @deprecated Multiple actions are supported by resources. Please call {}#updated_by_last_action} instead.
- #
- def updated=(true_or_false)
- Chef.deprecated(:custom_resource, "Chef::Resource#updated=(true|false) is deprecated. Please call #updated_by_last_action(true|false) instead.")
- updated_by_last_action(true_or_false)
- @updated = true_or_false
- end
-
- #
# The display name of this resource type, for printing purposes.
#
# Will be used to print out the resource in messages, e.g. resource_name[name]
@@ -1499,27 +1488,6 @@ class Chef
self.class.resource_for_node(name, node).new("name", run_context).provider_for_action(action).class
end
- module DeprecatedLWRPClass
-
- # @api private
- def register_deprecated_lwrp_class(resource_class, class_name)
- if Chef::Resource.const_defined?(class_name, false)
- Chef::Log.warn "#{class_name} already exists! Deprecation class overwrites #{resource_class}"
- Chef::Resource.send(:remove_const, class_name)
- end
-
- if !Chef::Config[:treat_deprecation_warnings_as_errors]
- Chef::Resource.const_set(class_name, resource_class)
- Chef::Resource.deprecated_constants[class_name.to_sym] = resource_class
- end
- end
-
- def deprecated_constants
- raise "Deprecated constants should be called only on Chef::Resource" unless self == Chef::Resource
- @deprecated_constants ||= {}
- end
- end
-
def self.remove_canonical_dsl
if @resource_name
remaining = Chef.resource_handler_map.delete_canonical(@resource_name, self)
@@ -1528,7 +1496,6 @@ class Chef
end
end
end
- extend DeprecatedLWRPClass
end
end
diff --git a/lib/chef/resource/action_class.rb b/lib/chef/resource/action_class.rb
index d2d74b47e2..dce3be3244 100644
--- a/lib/chef/resource/action_class.rb
+++ b/lib/chef/resource/action_class.rb
@@ -64,8 +64,6 @@ class Chef
@current_resource = current_resource
end
- use_inline_resources
-
# XXX: remove in Chef-14
def self.include_resource_dsl?
true
diff --git a/lib/chef/resource/chocolatey_package.rb b/lib/chef/resource/chocolatey_package.rb
index 5460661f6d..a443b9a1d7 100644
--- a/lib/chef/resource/chocolatey_package.rb
+++ b/lib/chef/resource/chocolatey_package.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software, Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -31,6 +31,9 @@ class Chef
@resource_name = :chocolatey_package
end
+ # windows can't take Array options yet
+ property :options, String
+
property :package_name, [String, Array], coerce: proc { |x| [x].flatten }
property :version, [String, Array], coerce: proc { |x| [x].flatten }
diff --git a/lib/chef/resource/dnf_package.rb b/lib/chef/resource/dnf_package.rb
index f10c282f19..d92dc12ec7 100644
--- a/lib/chef/resource/dnf_package.rb
+++ b/lib/chef/resource/dnf_package.rb
@@ -29,7 +29,7 @@ class Chef
allowed_actions :install, :upgrade, :remove, :purge, :reconfig, :lock, :unlock, :flush_cache
- provides :package, platform_family: %w{rhel fedora} do
+ provides :package, platform_family: %w{rhel fedora amazon} do
which("dnf") && shell_out("rpm -q dnf").stdout =~ /^dnf-[1-9]/
end
diff --git a/lib/chef/resource/execute.rb b/lib/chef/resource/execute.rb
index 659fa341b5..dee497e74f 100644
--- a/lib/chef/resource/execute.rb
+++ b/lib/chef/resource/execute.rb
@@ -42,7 +42,6 @@ class Chef
@cwd = nil
@environment = nil
@group = nil
- @path = nil
@returns = 0
@timeout = nil
@user = nil
diff --git a/lib/chef/resource/gem_package.rb b/lib/chef/resource/gem_package.rb
index 5511d3c580..fc162a6033 100644
--- a/lib/chef/resource/gem_package.rb
+++ b/lib/chef/resource/gem_package.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,11 +23,25 @@ class Chef
class GemPackage < Chef::Resource::Package
resource_name :gem_package
+ # the source can either be a path to a package source like:
+ # source /var/tmp/mygem-1.2.3.4.gem
+ # or it can be a url rubygems source like:
+ # https://www.rubygems.org
+ # the default has to be nil in order for the magical wiring up of the name property to
+ # the source pathname to work correctly.
+ #
+ # we don't do coercions here because its all a bit too complicated
+ #
+ # FIXME? the array form of installing paths most likely does not work?
+ #
property :source, [ String, Array ]
property :clear_sources, [ true, false ], default: false, desired_state: false
# Sets a custom gem_binary to run for gem commands.
property :gem_binary, String, desired_state: false
+ # set to false to avoid including Chef::Config[:rubygems_url] in the sources
+ property :include_default_source, [ TrueClass, FalseClass ], default: true
+
##
# Options for the gem install, either a Hash or a String. When a hash is
# given, the options are passed to Gem::DependencyInstaller.new, and the
diff --git a/lib/chef/resource/launchd.rb b/lib/chef/resource/launchd.rb
index c78ffa3f0e..3fba76e220 100644
--- a/lib/chef/resource/launchd.rb
+++ b/lib/chef/resource/launchd.rb
@@ -27,7 +27,7 @@ class Chef
identity_attr :label
default_action :create
- allowed_actions :create, :create_if_missing, :delete, :enable, :disable
+ allowed_actions :create, :create_if_missing, :delete, :enable, :disable, :restart
property :label, String, default: lazy { name }, identity: true
property :backup, [Integer, FalseClass]
@@ -114,7 +114,7 @@ class Chef
property :ld_group, String
property :limit_load_from_hosts, Array
property :limit_load_to_hosts, Array
- property :limit_load_to_session_type, Array
+ property :limit_load_to_session_type, [ Array, String ]
property :low_priority_io, [ TrueClass, FalseClass ]
property :mach_services, Hash
property :nice, Integer
@@ -139,18 +139,6 @@ class Chef
property :wait_for_debugger, [ TrueClass, FalseClass ]
property :watch_paths, Array
property :working_directory, String
-
- # hash is an instance method on Object and needs to return a Fixnum.
- def hash(arg = nil)
- Chef.deprecated(:launchd_hash_property, "Property `hash` on the `launchd` resource has changed to `plist_hash`." \
- "Please use `plist_hash` instead. This will raise an exception in Chef 13.")
-
- set_or_return(
- :plist_hash,
- arg,
- :kind_of => Hash
- )
- end
end
end
end
diff --git a/lib/chef/resource/lwrp_base.rb b/lib/chef/resource/lwrp_base.rb
index 7dfe147341..b12ac98673 100644
--- a/lib/chef/resource/lwrp_base.rb
+++ b/lib/chef/resource/lwrp_base.rb
@@ -69,8 +69,6 @@ class Chef
LWRPBase.loaded_lwrps[filename] = true
- # Create the deprecated Chef::Resource::LwrpFoo class
- Chef::Resource.register_deprecated_lwrp_class(resource_class, convert_to_class_name(resource_name))
resource_class
end
diff --git a/lib/chef/resource/mount.rb b/lib/chef/resource/mount.rb
index 2aca8432dd..7e601b861a 100644
--- a/lib/chef/resource/mount.rb
+++ b/lib/chef/resource/mount.rb
@@ -31,7 +31,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, default: { remount: false },
+ property :supports, Hash, default: lazy { { remount: false } },
coerce: proc { |x| x.is_a?(Array) ? x.each_with_object({}) { |i, m| m[i] = true } : x }
def initialize(name, run_context = nil)
diff --git a/lib/chef/resource/package.rb b/lib/chef/resource/package.rb
index a1f174a6f3..5647f203d2 100644
--- a/lib/chef/resource/package.rb
+++ b/lib/chef/resource/package.rb
@@ -36,7 +36,7 @@ class Chef
property :package_name, [ String, Array ], identity: true
property :version, [ String, Array ]
- property :options, [ String, Array ]
+ property :options, [ String, Array ], coerce: proc { |x| x.is_a?(String) ? x.shellsplit : x }
property :response_file, String, desired_state: false
property :response_file_variables, Hash, default: lazy { {} }, desired_state: false
property :source, String, desired_state: false
diff --git a/lib/chef/resource/systemd_unit.rb b/lib/chef/resource/systemd_unit.rb
index 688f2e9dcd..1a19a7d682 100644
--- a/lib/chef/resource/systemd_unit.rb
+++ b/lib/chef/resource/systemd_unit.rb
@@ -33,14 +33,19 @@ class Chef
:try_restart, :reload_or_restart,
:reload_or_try_restart
+ # Internal provider-managed properties
property :enabled, [TrueClass, FalseClass]
property :active, [TrueClass, FalseClass]
property :masked, [TrueClass, FalseClass]
property :static, [TrueClass, FalseClass]
+
+ # User-provided properties
property :user, String, desired_state: false
property :content, [String, Hash]
property :triggers_reload, [TrueClass, FalseClass],
default: true, desired_state: false
+ property :verify, [TrueClass, FalseClass],
+ default: true, desired_state: false
def to_ini
case content
diff --git a/lib/chef/resource/windows_package.rb b/lib/chef/resource/windows_package.rb
index 0e8dd39672..e37bad4b0a 100644
--- a/lib/chef/resource/windows_package.rb
+++ b/lib/chef/resource/windows_package.rb
@@ -1,6 +1,6 @@
#
# Author:: Bryan McLellan <btm@loftninjas.org>
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -37,6 +37,9 @@ class Chef
@source ||= source(@package_name) if @package_name.downcase.end_with?(".msi")
end
+ # windows can't take array options yet
+ property :options, String
+
# Unique to this resource
property :installer_type, Symbol
property :timeout, [ String, Integer ], default: 600
diff --git a/lib/chef/resource/windows_task.rb b/lib/chef/resource/windows_task.rb
new file mode 100644
index 0000000000..25e76f4220
--- /dev/null
+++ b/lib/chef/resource/windows_task.rb
@@ -0,0 +1,237 @@
+#
+# Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
+# Copyright:: Copyright 2008-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/resource"
+
+class Chef
+ class Resource
+ class WindowsTask < Chef::Resource
+
+ provides :windows_task, os: "windows"
+
+ allowed_actions :create, :delete, :run, :end, :change, :enable, :disable
+ default_action :create
+
+ def initialize(name, run_context = nil)
+ super
+ @resource_name = :windows_task
+ @task_name = name
+ @action = :create
+ end
+
+ property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/]
+ property :command, String
+ property :cwd, String
+ property :user, String, default: "SYSTEM"
+ property :password, String
+ property :run_level, equal_to: [:highest, :limited], default: :limited
+ property :force, [TrueClass, FalseClass], default: false
+ property :interactive_enabled, [TrueClass, FalseClass], default: false
+ property :frequency_modifier, [Integer, String], default: 1
+ property :frequency, equal_to: [:minute,
+ :hourly,
+ :daily,
+ :weekly,
+ :monthly,
+ :once,
+ :on_logon,
+ :onstart,
+ :on_idle], default: :hourly
+ property :start_day, String
+ property :start_time, String
+ property :day, [String, Integer]
+ property :months, String
+ property :idle_time, Integer
+ property :random_delay, String
+ property :execution_time_limit, String
+
+ attr_accessor :exists, :status, :enabled
+
+ def after_created
+ if random_delay
+ validate_random_delay(random_delay, frequency)
+ duration = sec_to_dur(random_delay)
+ random_delay(duration)
+ end
+
+ if execution_time_limit
+ raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as a String e.g. '60'." if execution_time_limit.to_i == 0
+ duration = sec_to_dur(execution_time_limit)
+ execution_time_limit(duration)
+ else
+ # schtask sets execution_time_limit as PT72H by default
+ # We are setting the default value here so that we can do idempotency check later
+ # Note: We can't use `default` in the property
+ # because it will raise error for Invalid values passed as "PT72H" is not in seconds
+ execution_time_limit("PT72H")
+ end
+
+ validate_start_time(start_time) if frequency == :once
+ 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)
+ validate_create_day(day, frequency) if day
+ validate_create_months(months, frequency) if months
+ validate_idle_time(idle_time, frequency) if idle_time
+ end
+
+ private
+
+ def validate_random_delay(random_delay, frequency)
+ if [:once, :on_logon, :onstart, :on_idle].include? frequency
+ raise ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly"
+ end
+
+ raise ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as a String e.g. '60'." if random_delay.to_i == 0
+ end
+
+ def validate_start_day(start_day, frequency)
+ if [:once, :on_logon, :onstart, :on_idle].include? frequency
+ raise ArgumentError, "`start_day` property is not supported with frequency: #{frequency}"
+ end
+ end
+
+ def validate_start_time(start_time)
+ raise ArgumentError, "`start_time` needs to be provided with `frequency :once`" unless start_time
+ end
+
+ SYSTEM_USERS = ['NT AUTHORITY\SYSTEM', "SYSTEM", 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', "USERS"].freeze
+
+ def validate_user_and_password(user, password)
+ if user && use_password?(user)
+ if password.nil?
+ raise ArgumentError, "Can't specify a non-system user without a password!"
+ end
+ end
+ end
+
+ def use_password?(user)
+ @use_password ||= !SYSTEM_USERS.include?(user.upcase)
+ end
+
+ def validate_interactive_setting(interactive_enabled, password)
+ if interactive_enabled && password.nil?
+ raise ArgumentError, "Please provide the password when attempting to set interactive/non-interactive."
+ end
+ end
+
+ def validate_create_frequency_modifier(frequency, frequency_modifier)
+ # Currently is handled in create action 'frequency_modifier_allowed' line. Does not allow for frequency_modifier for once,onstart,onlogon,onidle
+ # Note that 'OnEvent' is not a supported frequency.
+ unless frequency.nil? || frequency_modifier.nil?
+ case frequency
+ when :minute
+ unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 1439
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :minute frequency are 1 - 1439."
+ end
+ when :hourly
+ unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 23
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :hourly frequency are 1 - 23."
+ end
+ when :daily
+ unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 365
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :daily frequency are 1 - 365."
+ end
+ when :weekly
+ unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 52
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :weekly frequency are 1 - 52."
+ end
+ when :monthly
+ unless ("1".."12").to_a.push("FIRST", "SECOND", "THIRD", "FOURTH", "LAST", "LASTDAY").include?(frequency_modifier.to_s.upcase)
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'."
+ end
+ end
+ end
+ end
+
+ def validate_create_day(day, frequency)
+ unless [:weekly].include?(frequency)
+ raise "day attribute is only valid for tasks that run weekly"
+ end
+ if day.is_a?(String) && day.to_i.to_s != day
+ days = day.split(",")
+ days.each do |d|
+ unless ["mon", "tue", "wed", "thu", "fri", "sat", "sun", "*"].include?(d.strip.downcase)
+ raise "day attribute invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma."
+ end
+ end
+ end
+ end
+
+ def validate_create_months(months, frequency)
+ unless [:monthly].include?(frequency)
+ raise "months attribute is only valid for tasks that run monthly"
+ end
+ if months.is_a? String
+ months.split(",").each do |month|
+ unless ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC", "*"].include?(month.strip.upcase)
+ raise "months attribute invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma."
+ end
+ end
+ end
+ end
+
+ def validate_idle_time(idle_time, frequency)
+ unless [:on_idle].include?(frequency)
+ raise "idle_time attribute is only valid for tasks that run on_idle"
+ end
+
+ unless idle_time.to_i > 0 && idle_time.to_i <= 999
+ raise "idle_time value #{idle_time} is invalid. Valid values for :on_idle frequency are 1 - 999."
+ end
+ end
+
+ # Convert the number of seconds to an ISO8601 duration format
+ # @see http://tools.ietf.org/html/rfc2445#section-4.3.6
+ # @param [Integer] seconds The amount of seconds for this duration
+ def sec_to_dur(seconds)
+ seconds = seconds.to_i
+ return if seconds == 0
+ iso_str = "P"
+ if seconds > 604_800 # more than a week
+ weeks = seconds / 604_800
+ seconds -= (604_800 * weeks)
+ iso_str << "#{weeks}W"
+ end
+ if seconds > 86_400 # more than a day
+ days = seconds / 86_400
+ seconds -= (86_400 * days)
+ iso_str << "#{days}D"
+ end
+ if seconds > 0
+ iso_str << "T"
+ if seconds > 3600 # more than an hour
+ hours = seconds / 3600
+ seconds -= (3600 * hours)
+ iso_str << "#{hours}H"
+ end
+ if seconds > 60 # more than a minute
+ minutes = seconds / 60
+ seconds -= (60 * minutes)
+ iso_str << "#{minutes}M"
+ end
+ iso_str << "#{seconds}S"
+ end
+
+ iso_str
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/resource/yum_package.rb b/lib/chef/resource/yum_package.rb
index 2fc5db5cc3..078725e306 100644
--- a/lib/chef/resource/yum_package.rb
+++ b/lib/chef/resource/yum_package.rb
@@ -22,7 +22,7 @@ class Chef
class Resource
class YumPackage < Chef::Resource::Package
resource_name :yum_package
- provides :package, os: "linux", platform_family: %w{rhel fedora}
+ provides :package, os: "linux", platform_family: %w{rhel fedora amazon}
# XXX: the coercions here are due to the provider promiscuously updating the properties on the
# new_resource which causes immutable modification exceptions when passed an immutable node array.
diff --git a/lib/chef/resource/zypper_package.rb b/lib/chef/resource/zypper_package.rb
index f9e3eef49e..6c6e308159 100644
--- a/lib/chef/resource/zypper_package.rb
+++ b/lib/chef/resource/zypper_package.rb
@@ -23,6 +23,8 @@ class Chef
class ZypperPackage < Chef::Resource::Package
resource_name :zypper_package
provides :package, platform_family: "suse"
+
+ property :gpg_check, [ TrueClass, FalseClass ], default: lazy { Chef::Config[:zypper_check_gpg] }
end
end
end
diff --git a/lib/chef/resource_collection/resource_set.rb b/lib/chef/resource_collection/resource_set.rb
index 111d23dc09..6ff29247a0 100644
--- a/lib/chef/resource_collection/resource_set.rb
+++ b/lib/chef/resource_collection/resource_set.rb
@@ -161,27 +161,39 @@ class Chef
end
def find_resource_by_string(arg)
- results = Array.new
- case arg
- when MULTIPLE_RESOURCE_MATCH
- resource_type = $1
- arg =~ /^.+\[(.+)\]$/
- resource_list = $1
- resource_list.split(",").each do |instance_name|
- results << lookup(create_key(resource_type, instance_name))
- end
- when SINGLE_RESOURCE_MATCH
+ begin
+ if arg =~ SINGLE_RESOURCE_MATCH
resource_type = $1
name = $2
- results << lookup(create_key(resource_type, name))
- when NAMELESS_RESOURCE_MATCH
- resource_type = $1
- name = ""
- results << lookup(create_key(resource_type, name))
+ return [ lookup(create_key(resource_type, name)) ]
+ end
+ rescue Chef::Exceptions::ResourceNotFound => e
+ if arg =~ MULTIPLE_RESOURCE_MATCH
+ begin
+ results = Array.new
+ resource_type = $1
+ arg =~ /^.+\[(.+)\]$/
+ resource_list = $1
+ resource_list.split(",").each do |instance_name|
+ results << lookup(create_key(resource_type, instance_name))
+ end
+ Chef.deprecated(:multiresource_match, "The resource_collection multi-resource syntax is deprecated")
+ return results
+ rescue Chef::Exceptions::ResourceNotFound
+ raise e
+ end
else
- raise ArgumentError, "Bad string format #{arg}, you must have a string like resource_type[name]!"
+ raise e
+ end
end
- results
+
+ if arg =~ NAMELESS_RESOURCE_MATCH
+ resource_type = $1
+ name = ""
+ return [ lookup(create_key(resource_type, name)) ]
+ end
+
+ raise ArgumentError, "Bad string format #{arg}, you must have a string like resource_type[name]!"
end
end
end
diff --git a/lib/chef/resource_resolver.rb b/lib/chef/resource_resolver.rb
index 10b8c0f22e..a5c44f65b3 100644
--- a/lib/chef/resource_resolver.rb
+++ b/lib/chef/resource_resolver.rb
@@ -54,11 +54,6 @@ class Chef
# @api private
attr_reader :resource_name
# @api private
- def resource
- Chef.deprecated(:custom_resource, "Chef::ResourceResolver.resource deprecated. Use resource_name instead.")
- resource_name
- end
- # @api private
attr_reader :action
# @api private
attr_reader :canonical
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index a254fa601f..9f87cb2454 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -98,3 +98,4 @@ require "chef/resource/zypper_package"
require "chef/resource/cab_package"
require "chef/resource/powershell_package"
require "chef/resource/msu_package"
+require "chef/resource/windows_task"
diff --git a/lib/chef/run_context/cookbook_compiler.rb b/lib/chef/run_context/cookbook_compiler.rb
index b2a8d236a3..f2598a4f27 100644
--- a/lib/chef/run_context/cookbook_compiler.rb
+++ b/lib/chef/run_context/cookbook_compiler.rb
@@ -57,6 +57,7 @@ class Chef
# Run the compile phase of the chef run. Loads files in the following order:
# * Libraries
+ # * Ohai
# * Attributes
# * LWRPs
# * Resource Definitions
@@ -69,6 +70,7 @@ class Chef
# #cookbook_order for more information.
def compile
compile_libraries
+ compile_ohai_plugins
compile_attributes
compile_lwrps
compile_resource_definitions
@@ -101,11 +103,31 @@ class Chef
@events.library_load_complete
end
+ # Loads Ohai Plugins from cookbooks, and ensure any old ones are
+ # properly cleaned out
+ def compile_ohai_plugins
+ ohai_plugin_count = count_files_by_segment(:ohai)
+ @events.ohai_plugin_load_start(ohai_plugin_count)
+ FileUtils.rm_rf(Chef::Config[:ohai_segment_plugin_path])
+
+ cookbook_order.each do |cookbook|
+ load_ohai_plugins_from_cookbook(cookbook)
+ end
+
+ # Doing a full ohai system check is costly, so only do so if we've loaded additional plugins
+ if ohai_plugin_count > 0
+ ohai = Ohai::System.new.run_additional_plugins(Chef::Config[:ohai_segment_plugin_path])
+ node.consume_ohai_data(ohai)
+ end
+
+ @events.ohai_plugin_load_complete
+ end
+
# Loads attributes files from cookbooks. Attributes files are loaded
# according to #cookbook_order; within a cookbook, +default.rb+ is loaded
# first, then the remaining attributes files in lexical sort order.
def compile_attributes
- @events.attribute_load_start(count_files_by_segment(:attributes))
+ @events.attribute_load_start(count_files_by_segment(:attributes, "attributes.rb"))
cookbook_order.each do |cookbook|
load_attributes_from_cookbook(cookbook)
end
@@ -166,7 +188,16 @@ class Chef
def load_attributes_from_cookbook(cookbook_name)
list_of_attr_files = files_in_cookbook_by_segment(cookbook_name, :attributes).dup
- if default_file = list_of_attr_files.find { |path| File.basename(path) == "default.rb" }
+ root_alias = cookbook_collection[cookbook_name].files_for(:root_files).find { |record| record[:name] == "attributes.rb" }
+ default_file = list_of_attr_files.find { |path| File.basename(path) == "default.rb" }
+ if root_alias
+ if default_file
+ Chef::Log.error("Cookbook #{cookbook_name} contains both attributes.rb and and attributes/default.rb, ignoring attributes/default.rb")
+ list_of_attr_files.delete(default_file)
+ end
+ # The actual root_alias path decoding is handled in CookbookVersion#attribute_filenames_by_short_filename
+ load_attribute_file(cookbook_name.to_s, "default")
+ elsif default_file
list_of_attr_files.delete(default_file)
load_attribute_file(cookbook_name.to_s, default_file)
end
@@ -226,6 +257,19 @@ class Chef
raise
end
+ def load_ohai_plugins_from_cookbook(cookbook_name)
+ target = Chef::Config[:ohai_segment_plugin_path]
+ files_in_cookbook_by_segment(cookbook_name, :ohai).each do |filename|
+ next unless File.extname(filename) == ".rb"
+
+ Chef::Log.debug "Loading Ohai plugin: #{filename} from #{cookbook_name}"
+ target_name = File.join(target, cookbook_name.to_s, File.basename(filename))
+
+ FileUtils.mkdir_p(File.dirname(target_name))
+ FileUtils.cp(filename, target_name)
+ end
+ end
+
def load_resource_definitions_from_cookbook(cookbook_name)
files_in_cookbook_by_segment(cookbook_name, :definitions).each do |filename|
begin
@@ -259,16 +303,16 @@ class Chef
ordered_cookbooks << cookbook
end
- def count_files_by_segment(segment)
+ def count_files_by_segment(segment, root_alias = nil)
cookbook_collection.inject(0) do |count, cookbook_by_name|
- count + cookbook_by_name[1].segment_filenames(segment).size
+ count + cookbook_by_name[1].segment_filenames(segment).size + (root_alias ? cookbook_by_name[1].files_for(:root_files).select { |record| record[:name] == root_alias }.size : 0)
end
end
# Lists the local paths to files in +cookbook+ of type +segment+
# (attribute, recipe, etc.), sorted lexically.
def files_in_cookbook_by_segment(cookbook, segment)
- cookbook_collection[cookbook].segment_filenames(segment).sort
+ cookbook_collection[cookbook].files_for(segment).map { |record| record[:full_path] }.sort
end
# Yields the name, as a symbol, of each cookbook depended on by
diff --git a/lib/chef/search/query.rb b/lib/chef/search/query.rb
index 7357dbf6be..6f494819ba 100644
--- a/lib/chef/search/query.rb
+++ b/lib/chef/search/query.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -63,6 +63,14 @@ class Chef
validate_type(type)
args_h = hashify_args(*args)
+ if args_h[:fuzz]
+ if type == :node
+ query = fuzzify_node_query(query)
+ end
+ # FIXME: can i haz proper ruby-2.x named parameters someday plz?
+ args_h = args_h.reject { |k, v| k == :fuzz }
+ end
+
response = call_rest_service(type, query: query, **args_h)
if block
@@ -92,6 +100,14 @@ class Chef
private
+ def fuzzify_node_query(query)
+ if query !~ /:/
+ "tags:*#{query}* OR roles:*#{query}* OR fqdn:*#{query}* OR addresses:*#{query}* OR policy_name:*#{query}* OR policy_group:*#{query}*"
+ else
+ query
+ end
+ end
+
def validate_type(t)
unless t.kind_of?(String) || t.kind_of?(Symbol)
msg = "Invalid search object type #{t.inspect} (#{t.class}), must be a String or Symbol." +
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index f509cda66c..098751072f 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -21,7 +21,7 @@
class Chef
CHEF_ROOT = File.expand_path("../..", __FILE__)
- VERSION = "13.0.79"
+ VERSION = "13.0.118"
end
#
diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock
index 32cdf871f2..3d32a97a15 100644
--- a/omnibus/Gemfile.lock
+++ b/omnibus/Gemfile.lock
@@ -1,14 +1,14 @@
GIT
remote: https://github.com/chef/license_scout
- revision: 2cf81860f92d4f2df4444341048b8aeec2da0cfa
+ revision: ff3cb28159e72414d63008f9a0d42e85d4aec4ba
specs:
- license_scout (0.1.2)
+ license_scout (0.1.3)
ffi-yajl (~> 2.2)
mixlib-shellout (~> 2.2)
GIT
remote: https://github.com/chef/omnibus
- revision: 433220e0b7c434dbc4a36daaa1fecbdb1bf7231d
+ revision: ffbda9ad7d37ddb485342505ff4407c6ff23d95f
specs:
omnibus (5.5.0)
aws-sdk (~> 2)
@@ -25,7 +25,7 @@ GIT
GIT
remote: https://github.com/chef/omnibus-software
- revision: bc08deef668865990bde3a0f0dc1ef3c3f5be735
+ revision: cae44c1a3ebf7207516813ba15b372231c253954
specs:
omnibus-software (4.0.0)
chef-sugar (>= 3.4.0)
@@ -38,13 +38,13 @@ GEM
public_suffix (~> 2.0, >= 2.0.2)
artifactory (2.8.1)
awesome_print (1.7.0)
- aws-sdk (2.8.14)
- aws-sdk-resources (= 2.8.14)
- aws-sdk-core (2.8.14)
+ aws-sdk (2.9.7)
+ aws-sdk-resources (= 2.9.7)
+ aws-sdk-core (2.9.7)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-resources (2.8.14)
- aws-sdk-core (= 2.8.14)
+ aws-sdk-resources (2.9.7)
+ aws-sdk-core (= 2.9.7)
aws-sigv4 (1.0.0)
berkshelf (4.3.5)
addressable (~> 2.3, >= 2.3.4)
@@ -113,12 +113,12 @@ GEM
iostruct (0.0.4)
ipaddress (0.8.3)
jmespath (1.3.1)
- json (2.0.3)
+ json (2.0.4)
kitchen-vagrant (0.19.0)
test-kitchen (~> 1.4)
libyajl2 (1.2.0)
little-plugger (1.1.4)
- logging (2.2.0)
+ logging (2.2.2)
little-plugger (~> 1.1)
multi_json (~> 1.10)
method_source (0.8.2)
@@ -150,7 +150,7 @@ GEM
net-ssh (>= 2.6.5)
nio4r (2.0.0)
nori (2.6.0)
- octokit (4.6.2)
+ octokit (4.7.0)
sawyer (~> 0.8.0, >= 0.5.3)
ohai (8.23.0)
chef-config (>= 12.5.0.alpha.1, < 13)
@@ -231,7 +231,7 @@ GEM
hashie (>= 2.0.2, < 4.0.0)
win32-process (0.8.3)
ffi (>= 1.0.0)
- winrm (2.1.3)
+ winrm (2.2.1)
builder (>= 2.1.2)
erubis (~> 2.7)
gssapi (~> 1.2)
diff --git a/omnibus/config/software/chef-gem-inspec.rb b/omnibus/config/software/chef-gem-inspec.rb
new file mode 100644
index 0000000000..8c5e1cbf26
--- /dev/null
+++ b/omnibus/config/software/chef-gem-inspec.rb
@@ -0,0 +1,10 @@
+# gem installs this gem from the version specified in chef's Gemfile.lock
+# so we can take advantage of omnibus's caching. Just duplicate this file and
+# add the new software def to chef software def if you want to separate
+# another gem's installation.
+require_relative "../../files/chef-gem/build-chef-gem/gem-install-software-def"
+BuildChefGem::GemInstallSoftwareDef.define(self, __FILE__)
+
+license "Apache-2.0"
+license_file "https://raw.githubusercontent.com/chef/inspec/master/LICENSE"
+skip_transitive_dependency_licensing true
diff --git a/omnibus/config/software/chef.rb b/omnibus/config/software/chef.rb
index c0af403b20..4726f8b687 100644
--- a/omnibus/config/software/chef.rb
+++ b/omnibus/config/software/chef.rb
@@ -26,7 +26,6 @@ end
# For nokogiri
dependency "libxml2"
dependency "libxslt"
-dependency "libiconv"
dependency "liblzma"
dependency "zlib"
@@ -45,6 +44,7 @@ dependency "chef-gem-ruby-prof"
dependency "chef-gem-byebug"
dependency "chef-gem-debug_inspector"
dependency "chef-gem-binding_of_caller"
+dependency "chef-gem-inspec"
unless ios_xr? || solaris?
dependency "chef-gem-rbnacl-libsodium"
dependency "chef-gem-bcrypt_pbkdf-ruby"
diff --git a/omnibus/files/chef-gem/build-chef-gem.rb b/omnibus/files/chef-gem/build-chef-gem.rb
index 9e5bf9b996..c9aaaada1d 100644
--- a/omnibus/files/chef-gem/build-chef-gem.rb
+++ b/omnibus/files/chef-gem/build-chef-gem.rb
@@ -99,7 +99,7 @@ module BuildChefGem
--with-xml2-include=#{Shellwords.escape("#{install_dir}/embedded/include/libxml2")}
--with-xslt-lib=#{Shellwords.escape("#{install_dir}/embedded/lib")}
--with-xslt-include=#{Shellwords.escape("#{install_dir}/embedded/include/libxslt")}
- --with-iconv-dir=#{Shellwords.escape("#{install_dir}/embedded")}
+ --without-iconv-dir
--with-zlib-dir=#{Shellwords.escape("#{install_dir}/embedded")}
}.join(" "),
}
diff --git a/omnibus_overrides.rb b/omnibus_overrides.rb
index 32f460499c..0409c2a1bc 100644
--- a/omnibus_overrides.rb
+++ b/omnibus_overrides.rb
@@ -3,7 +3,7 @@ override :rubygems, version: "2.6.11"
override :bundler, version: "1.12.5"
override "libffi", version: "3.2.1"
override "libiconv", version: "1.14"
-override "liblzma", version: "5.2.2"
+override "liblzma", version: "5.2.3"
override "libtool", version: "2.4.2"
override "libxml2", version: "2.9.4"
override "libxslt", version: "1.1.29"
diff --git a/spec/data/cookbooks/openldap/templates/default/openldap_nested_variable_stuff.erb b/spec/data/cookbooks/openldap/templates/default/openldap_nested_variable_stuff.erb
new file mode 100644
index 0000000000..5ebee33806
--- /dev/null
+++ b/spec/data/cookbooks/openldap/templates/default/openldap_nested_variable_stuff.erb
@@ -0,0 +1 @@
+super secret is <%= @secret.first["key"] -%>
diff --git a/spec/data/lwrp/providers/buck_passer.rb b/spec/data/lwrp/providers/buck_passer.rb
index 2bbca07bf7..0bbd413867 100644
--- a/spec/data/lwrp/providers/buck_passer.rb
+++ b/spec/data/lwrp/providers/buck_passer.rb
@@ -10,7 +10,7 @@ def without_deprecation_warnings(&block)
end
end
-action :pass_buck do
+def action_pass_buck
lwrp_foo :prepared_thumbs do
action :prepare_thumbs
# We know there will be a deprecation error here; head it off
diff --git a/spec/data/lwrp/providers/buck_passer_2.rb b/spec/data/lwrp/providers/buck_passer_2.rb
index c3bab7266f..980506c671 100644
--- a/spec/data/lwrp/providers/buck_passer_2.rb
+++ b/spec/data/lwrp/providers/buck_passer_2.rb
@@ -8,7 +8,7 @@ def without_deprecation_warnings(&block)
end
end
-action :pass_buck do
+def action_pass_buck
lwrp_bar :prepared_eyes do
action :prepare_eyes
# We know there will be a deprecation error here; head it off
diff --git a/spec/data/lwrp/providers/embedded_resource_accesses_providers_scope.rb b/spec/data/lwrp/providers/embedded_resource_accesses_providers_scope.rb
index 77c1111ff5..d6996da55e 100644
--- a/spec/data/lwrp/providers/embedded_resource_accesses_providers_scope.rb
+++ b/spec/data/lwrp/providers/embedded_resource_accesses_providers_scope.rb
@@ -13,7 +13,7 @@ def without_deprecation_warnings(&block)
end
end
-action :twiddle_thumbs do
+def action_twiddle_thumbs
@enclosed_resource = lwrp_foo :foo do
monkey generate_new_name(new_resource.monkey){ 'the monkey' }
# We know there will be a deprecation error here; head it off
diff --git a/spec/data/lwrp/providers/inline_compiler.rb b/spec/data/lwrp/providers/inline_compiler.rb
index 2535276b24..91a80b32af 100644
--- a/spec/data/lwrp/providers/inline_compiler.rb
+++ b/spec/data/lwrp/providers/inline_compiler.rb
@@ -1,6 +1,4 @@
-use_inline_resources
-
action :test do
ruby_block "interior-ruby-block-1" do
diff --git a/spec/data/root_alias_cookbooks/dup_attr/attributes.rb b/spec/data/root_alias_cookbooks/dup_attr/attributes.rb
new file mode 100644
index 0000000000..3a3bab96e1
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/dup_attr/attributes.rb
@@ -0,0 +1 @@
+default["aliased"]["attr"] = "value"
diff --git a/spec/data/root_alias_cookbooks/dup_attr/attributes/default.rb b/spec/data/root_alias_cookbooks/dup_attr/attributes/default.rb
new file mode 100644
index 0000000000..a6f6c78bb0
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/dup_attr/attributes/default.rb
@@ -0,0 +1 @@
+default["aliased"]["attr"] = "other"
diff --git a/spec/data/root_alias_cookbooks/dup_attr/metadata.rb b/spec/data/root_alias_cookbooks/dup_attr/metadata.rb
new file mode 100644
index 0000000000..703a73ab19
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/dup_attr/metadata.rb
@@ -0,0 +1,2 @@
+name "dup_attr"
+version "1.0.0"
diff --git a/spec/data/root_alias_cookbooks/dup_attr/recipe.rb b/spec/data/root_alias_cookbooks/dup_attr/recipe.rb
new file mode 100644
index 0000000000..d82e58fbcd
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/dup_attr/recipe.rb
@@ -0,0 +1,3 @@
+ruby_block "root alias" do
+ block { }
+end
diff --git a/spec/data/root_alias_cookbooks/dup_recipe/attributes.rb b/spec/data/root_alias_cookbooks/dup_recipe/attributes.rb
new file mode 100644
index 0000000000..3a3bab96e1
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/dup_recipe/attributes.rb
@@ -0,0 +1 @@
+default["aliased"]["attr"] = "value"
diff --git a/spec/data/root_alias_cookbooks/dup_recipe/metadata.rb b/spec/data/root_alias_cookbooks/dup_recipe/metadata.rb
new file mode 100644
index 0000000000..62273a64d5
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/dup_recipe/metadata.rb
@@ -0,0 +1,2 @@
+name "dup_recipe"
+version "1.0.0"
diff --git a/spec/data/root_alias_cookbooks/dup_recipe/recipe.rb b/spec/data/root_alias_cookbooks/dup_recipe/recipe.rb
new file mode 100644
index 0000000000..d82e58fbcd
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/dup_recipe/recipe.rb
@@ -0,0 +1,3 @@
+ruby_block "root alias" do
+ block { }
+end
diff --git a/spec/data/root_alias_cookbooks/dup_recipe/recipes/default.rb b/spec/data/root_alias_cookbooks/dup_recipe/recipes/default.rb
new file mode 100644
index 0000000000..3eb7c22809
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/dup_recipe/recipes/default.rb
@@ -0,0 +1,3 @@
+ruby_block "other" do
+ block { }
+end
diff --git a/spec/data/root_alias_cookbooks/simple/attributes.rb b/spec/data/root_alias_cookbooks/simple/attributes.rb
new file mode 100644
index 0000000000..3a3bab96e1
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/simple/attributes.rb
@@ -0,0 +1 @@
+default["aliased"]["attr"] = "value"
diff --git a/spec/data/root_alias_cookbooks/simple/metadata.rb b/spec/data/root_alias_cookbooks/simple/metadata.rb
new file mode 100644
index 0000000000..9147558459
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/simple/metadata.rb
@@ -0,0 +1,2 @@
+name "simple"
+version "1.0.0"
diff --git a/spec/data/root_alias_cookbooks/simple/recipe.rb b/spec/data/root_alias_cookbooks/simple/recipe.rb
new file mode 100644
index 0000000000..d82e58fbcd
--- /dev/null
+++ b/spec/data/root_alias_cookbooks/simple/recipe.rb
@@ -0,0 +1,3 @@
+ruby_block "root alias" do
+ block { }
+end
diff --git a/spec/functional/rebooter_spec.rb b/spec/functional/rebooter_spec.rb
index 1b6e95b39c..a28491cc0b 100644
--- a/spec/functional/rebooter_spec.rb
+++ b/spec/functional/rebooter_spec.rb
@@ -72,6 +72,7 @@ describe Chef::Platform::Rebooter do
def test_rebooter_method(method_sym, is_windows, expected_reboot_str)
allow(ChefConfig).to receive(:windows?).and_return(is_windows)
expect(rebooter).to receive(:shell_out!).once.with(expected_reboot_str)
+ expect(rebooter).to receive(:raise).with(Chef::Exceptions::Reboot)
expect(rebooter).to receive(method_sym).once.and_call_original
rebooter.send(method_sym, run_context.node)
end
diff --git a/spec/functional/resource/cron_spec.rb b/spec/functional/resource/cron_spec.rb
index f5948191c5..1bff8bf874 100644
--- a/spec/functional/resource/cron_spec.rb
+++ b/spec/functional/resource/cron_spec.rb
@@ -1,7 +1,7 @@
# encoding: UTF-8
#
# Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
-# Copyright:: Copyright 2013-2016, Chef Software Inc.
+# Copyright:: Copyright 2013-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -161,7 +161,7 @@ describe Chef::Resource::Cron, :requires_root, :unix_only do
end
def cron_create_should_raise_exception
- expect { new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::Cron, /Error updating state of #{new_resource.name}, exit: 1/)
+ expect { new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::Cron)
cron_should_not_exists(new_resource.name)
end
diff --git a/spec/functional/resource/template_spec.rb b/spec/functional/resource/template_spec.rb
index 32529fbb0c..b9a39255f4 100644
--- a/spec/functional/resource/template_spec.rb
+++ b/spec/functional/resource/template_spec.rb
@@ -32,6 +32,7 @@ describe Chef::Resource::Template do
let(:node) do
node = Chef::Node.new
node.normal[:slappiness] = "a warm gun"
+ node.normal[:nested][:secret] = "value"
node
end
@@ -209,4 +210,36 @@ describe Chef::Resource::Template do
end
end
+ describe "when template variables contain lazy{} calls" do
+ it "resolves the DelayedEvaluator" do
+ resource.source("openldap_variable_stuff.conf.erb")
+ resource.variables(:secret => Chef::DelayedEvaluator.new { "nutella" })
+ resource.run_action(:create)
+ expect(IO.read(path)).to eq("super secret is nutella")
+ end
+
+ it "does not mutate the resource variables" do
+ resource.source("openldap_variable_stuff.conf.erb")
+ resource.variables(:secret => Chef::DelayedEvaluator.new { "nutella" })
+ resource.run_action(:create)
+ expect(resource.variables[:secret]).to be_a Chef::DelayedEvaluator
+ end
+
+ it "resolves the DelayedEvaluator when deeply nested" do
+ resource.source("openldap_nested_variable_stuff.erb")
+ resource.variables(:secret => [{ "key" => Chef::DelayedEvaluator.new { "nutella" } }])
+ resource.run_action(:create)
+ expect(IO.read(path)).to eq("super secret is nutella")
+ end
+ end
+
+ describe "when passing a node attribute mash as a template variable" do
+ it "uses the node attributes like a hash" do
+ resource.source("openldap_variable_stuff.conf.erb")
+ resource.variables(node[:nested])
+ resource.run_action(:create)
+ expect(IO.read(path)).to eq("super secret is value")
+ end
+ end
+
end
diff --git a/spec/functional/root_alias_spec.rb b/spec/functional/root_alias_spec.rb
new file mode 100644
index 0000000000..7091615d12
--- /dev/null
+++ b/spec/functional/root_alias_spec.rb
@@ -0,0 +1,78 @@
+#
+# Copyright:: Copyright 2017, Noah Kantrowitz
+# 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 "root aliases" do
+ let(:chef_repo_path) { File.expand_path(File.join(CHEF_SPEC_DATA, "root_alias_cookbooks")) }
+ let(:cookbook_collection) do
+ cl = Chef::CookbookLoader.new(chef_repo_path)
+ cl.load_cookbooks
+ Chef::CookbookCollection.new(cl)
+ end
+ let(:node) do
+ node = Chef::Node.new
+ node.automatic[:recipes] = []
+ node
+ end
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, cookbook_collection, events) }
+ before do
+ node.run_context = run_context
+ end
+
+ describe "attributes root aliases" do
+ it "should load attributes.rb when included directly" do
+ node.include_attribute("simple")
+ expect(node["aliased"]["attr"]).to eq "value"
+ end
+
+ it "should load attributes.rb when loading a cookbook" do
+ node.run_list << "simple"
+ run_context.load(node.run_list.expand("_default"))
+ expect(node["aliased"]["attr"]).to eq "value"
+ end
+
+ context "with both an attributes.rb and attributes/default.rb" do
+ it "should log an error and ignore attributes/default.rb" do
+ expect(Chef::Log).to receive(:error).with("Cookbook dup_attr contains both attributes.rb and and attributes/default.rb, ignoring attributes/default.rb")
+ node.run_list << "dup_attr"
+ run_context.load(node.run_list.expand("_default"))
+ expect(node["aliased"]["attr"]).to eq "value"
+ end
+ end
+ end
+
+ describe "recipe root aliased" do
+ it "should load recipe.rb" do
+ node.run_list << "simple"
+ run_context.load(node.run_list.expand("_default"))
+ run_context.include_recipe("simple")
+ expect(run_context.resource_collection.map(&:to_s)).to eq ["ruby_block[root alias]"]
+ end
+
+ context "with both an recipe.rb and recipes/default.rb" do
+ it "should log an error and ignore recipes/default.rb" do
+ expect(Chef::Log).to receive(:error).with("Cookbook dup_recipe contains both recipe.rb and and recipes/default.rb, ignoring recipes/default.rb")
+ node.run_list << "dup_recipe"
+ run_context.load(node.run_list.expand("_default"))
+ run_context.include_recipe("dup_recipe")
+ expect(run_context.resource_collection.map(&:to_s)).to eq ["ruby_block[root alias]"]
+ end
+ end
+ end
+end
diff --git a/spec/functional/shell_spec.rb b/spec/functional/shell_spec.rb
index 8c8d7ba482..08c791f2d2 100644
--- a/spec/functional/shell_spec.rb
+++ b/spec/functional/shell_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2012-2016, Chef Software, Inc.
+# Copyright:: Copyright 2012-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,7 +20,6 @@ require "spec_helper"
require "functional/resource/base"
require "chef/version"
require "chef/shell"
-require "chef/mixin/command/unix"
describe Shell do
@@ -28,7 +27,6 @@ describe Shell do
# not catch cases where chef-shell fails to boot because of changes in
# chef/client.rb
describe "smoke tests", :unix_only => true do
- include Chef::Mixin::Command::Unix
TIMEOUT = 300
@@ -79,44 +77,26 @@ describe Shell do
end
def run_chef_shell_with(options)
- case ohai[:platform]
- when "aix"
- config = File.expand_path("shef-config.rb", CHEF_SPEC_DATA)
- path_to_chef_shell = File.expand_path("../../../bin/chef-shell", __FILE__)
- output = ""
- status = popen4("#{path_to_chef_shell} -c #{config} #{options}", :waitlast => true) do |pid, stdin, stdout, stderr|
- read_until(stdout, "chef (#{Chef::VERSION})>")
- yield stdout, stdin if block_given?
- stdin.write("'done'\n")
- output = read_until(stdout, '=> "done"')
- stdin.print("exit\n")
- flush_output(stdout)
- end
-
- [output, status.exitstatus]
- else
- # Windows ruby installs don't (always?) have PTY,
- # so hide the require here
- begin
- require "pty"
- config = File.expand_path("shef-config.rb", CHEF_SPEC_DATA)
- path_to_chef_shell = File.expand_path("../../../bin/chef-shell", __FILE__)
- reader, writer, pid = PTY.spawn("#{path_to_chef_shell} -c #{config} #{options}")
- read_until(reader, "chef (#{Chef::VERSION})>")
- yield reader, writer if block_given?
- writer.puts('"done"')
- output = read_until(reader, '=> "done"')
- writer.print("exit\n")
- flush_output(reader)
- writer.close
-
- exitstatus = wait_or_die(pid)
-
- [output, exitstatus]
- rescue PTY::ChildExited => e
- [output, e.status]
- end
- end
+ # Windows ruby installs don't (always?) have PTY,
+ # so hide the require here
+
+ require "pty"
+ config = File.expand_path("shef-config.rb", CHEF_SPEC_DATA)
+ path_to_chef_shell = File.expand_path("../../../bin/chef-shell", __FILE__)
+ reader, writer, pid = PTY.spawn("#{path_to_chef_shell} -c #{config} #{options}")
+ read_until(reader, "chef (#{Chef::VERSION})>")
+ yield reader, writer if block_given?
+ writer.puts('"done"')
+ output = read_until(reader, '=> "done"')
+ writer.print("exit\n")
+ flush_output(reader)
+ writer.close
+
+ exitstatus = wait_or_die(pid)
+
+ [output, exitstatus]
+ rescue PTY::ChildExited => e
+ [output, e.status]
end
it "boots correctly with -lauto" do
diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb
index 2a31638c0f..00086c75ca 100644
--- a/spec/integration/client/client_spec.rb
+++ b/spec/integration/client/client_spec.rb
@@ -294,10 +294,9 @@ chef_server_url 'http://omg.com/blah'
cookbook_path "#{path_to('cookbooks')}"
EOM
- result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -r 'x::default' -z", :cwd => chef_dir)
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -r 'x::default' -z -l info", :cwd => chef_dir)
expect(result.stdout).not_to include("Overridden Run List")
expect(result.stdout).to include("Run List is [recipe[x::default]]")
- #puts result.stdout
result.error!
end
@@ -445,7 +444,7 @@ control_group "control group without top level control" do
end
RECIPE
- result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'audit_test::succeed'", :cwd => chef_dir)
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'audit_test::succeed' -l info", :cwd => chef_dir)
expect(result.error?).to be_falsey
expect(result.stdout).to include("Successfully executed all `control_group` blocks and contained examples")
end
@@ -465,6 +464,39 @@ end
end
end
+ when_the_repository "has a cookbook with an ohai plugin" do
+ before do
+ file "cookbooks/x/recipes/default.rb", <<-RECIPE
+file #{path_to('tempfile.txt').inspect} do
+ content node["english"]["version"]
+end
+ RECIPE
+
+ file "cookbooks/x/ohai/english.rb", <<-OHAI
+ Ohai.plugin(:English) do
+ provides 'english'
+
+ collect_data do
+ english Mash.new
+ english[:version] = "2014"
+ end
+ end
+ OHAI
+
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+EOM
+ end
+
+ it "should run the ohai plugin" do
+ result = shell_out("#{chef_client} -l debug -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir)
+ result.error!
+
+ expect(IO.read(path_to("tempfile.txt"))).to eq("2014")
+ end
+ end
+
# Fails on appveyor, but works locally on windows and on windows hosts in Ci.
context "when using recipe-url", :skip_appveyor do
before(:each) do
@@ -522,4 +554,42 @@ EOM
command.error!
end
end
+
+ when_the_repository "has a cookbook that logs at the info level" do
+ before do
+ file "cookbooks/x/recipes/default.rb", <<EOM
+ log "info level" do
+ level :info
+ end
+EOM
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+EOM
+ end
+
+ it "a chef client run should not log to info by default" do
+ command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir)
+ command.error!
+ expect(command.stdout).not_to include("INFO")
+ end
+
+ it "a chef client run to a pipe should not log to info by default" do
+ command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork | tee #{path_to('chefrun.out')}", :cwd => chef_dir)
+ command.error!
+ expect(command.stdout).not_to include("INFO")
+ end
+
+ it "a chef solo run should not log to info by default" do
+ command = shell_out("#{chef_solo} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir)
+ command.error!
+ expect(command.stdout).not_to include("INFO")
+ end
+
+ it "a chef solo run to a pipe should not log to info by default" do
+ command = shell_out("#{chef_solo} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork | tee #{path_to('chefrun.out')}", :cwd => chef_dir)
+ command.error!
+ expect(command.stdout).not_to include("INFO")
+ end
+ end
end
diff --git a/spec/integration/client/exit_code_spec.rb b/spec/integration/client/exit_code_spec.rb
index 30020f6a3f..4397426723 100644
--- a/spec/integration/client/exit_code_spec.rb
+++ b/spec/integration/client/exit_code_spec.rb
@@ -25,7 +25,7 @@ describe "chef-client" do
let(:critical_env_vars) { %w{PATH RUBYOPT BUNDLE_GEMFILE GEM_PATH}.map { |o| "#{o}=#{ENV[o]}" } .join(" ") }
- when_the_repository "does not have exit_status configured" do
+ when_the_repository "uses RFC 062 defined exit codes" do
def setup_client_rb
file "config/client.rb", <<EOM
@@ -43,110 +43,6 @@ EOM
end
def run_chef_client_and_expect_exit_code(exit_code)
- shell_out!(
- "#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default'",
- :cwd => chef_dir,
- :returns => [exit_code])
- end
-
- context "has a cookbook" do
- context "with a library" do
- context "which cannot be loaded" do
- before do
- file "cookbooks/x/recipes/default.rb", ""
- file "cookbooks/x/libraries/error.rb", "require 'does/not/exist'"
- end
-
- it "exits with GENERIC_FAILURE, 1" do
- setup_client_rb
- run_chef_client_and_expect_exit_code 1
- end
- end
- end
-
- context "with an audit recipe" do
- context "which fails" do
- before do
- file "cookbooks/x/recipes/default.rb", <<-RECIPE
-control_group "control group without top level control" do
- it "should fail" do
- expect(2 - 2).to eq(1)
- end
-end
-RECIPE
- end
-
- it "exits with GENERIC_FAILURE, 1" do
- setup_client_rb_with_audit_mode
- run_chef_client_and_expect_exit_code 1
- end
- end
- end
-
- context "with a recipe" do
- context "which throws an error" do
- before { file "cookbooks/x/recipes/default.rb", "raise 'BOOM'" }
-
- it "exits with GENERIC_FAILURE, 1" do
- setup_client_rb
- run_chef_client_and_expect_exit_code 1
- end
- end
-
- context "with a recipe which calls Chef::Application.fatal with a non-RFC exit code" do
- before { file "cookbooks/x/recipes/default.rb", "Chef::Application.fatal!('BOOM', 123)" }
-
- it "exits with the specified exit code" do
- setup_client_rb
- run_chef_client_and_expect_exit_code 123
- end
- end
-
- context "with a recipe which calls Chef::Application.exit with a non-RFC exit code" do
- before { file "cookbooks/x/recipes/default.rb", "Chef::Application.exit!('BOOM', 231)" }
-
- it "exits with the specified exit code" do
- setup_client_rb
- run_chef_client_and_expect_exit_code 231
- end
- end
- end
-
- context "when an attempt to reboot fails (like from the reboot resource)" do
- before do
- file "cookbooks/x/recipes/default.rb", <<EOM
-raise Chef::Exceptions::RebootFailed.new
-EOM
- end
-
- it "exits with GENERIC_FAILURE, 1" do
- setup_client_rb
- run_chef_client_and_expect_exit_code 1
- end
- end
- end
- end
-
- when_the_repository "does has exit_status enabled" do
-
- def setup_client_rb
- file "config/client.rb", <<EOM
-local_mode true
-cookbook_path "#{path_to('cookbooks')}"
-exit_status :enabled
-EOM
- end
-
- def setup_client_rb_with_audit_mode
- file "config/client.rb", <<EOM
-local_mode true
-cookbook_path "#{path_to('cookbooks')}"
-exit_status :enabled
-audit_mode :audit_only
-EOM
- end
-
- def run_chef_client_and_expect_exit_code(exit_code)
shell_out!("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default'",
:cwd => chef_dir,
:returns => [exit_code])
diff --git a/spec/integration/knife/chef_repository_file_system_spec.rb b/spec/integration/knife/chef_repository_file_system_spec.rb
index cc538c98c0..222d3aee8a 100644
--- a/spec/integration/knife/chef_repository_file_system_spec.rb
+++ b/spec/integration/knife/chef_repository_file_system_spec.rb
@@ -158,103 +158,6 @@ EOM
end
end
- when_the_repository "has extraneous subdirectories and files under a cookbook" do
- before do
- directory "cookbooks/cookbook1" do
- file "a.rb", ""
- file "blarghle/blah.rb", ""
- directory "attributes" do
- file "a.rb", ""
- file "b.json", {}
- file "c/d.rb", ""
- file "c/e.json", {}
- end
- directory "definitions" do
- file "a.rb", ""
- file "b.json", {}
- file "c/d.rb", ""
- file "c/e.json", {}
- end
- directory "recipes" do
- file "a.rb", ""
- file "b.json", {}
- file "c/d.rb", ""
- file "c/e.json", {}
- end
- directory "libraries" do
- file "a.rb", ""
- file "b.json", {}
- file "c/d.rb", ""
- file "c/e.json", {}
- end
- directory "templates" do
- file "a.rb", ""
- file "b.json", {}
- file "c/d.rb", ""
- file "c/e.json", {}
- end
- directory "files" do
- file "a.rb", ""
- file "b.json", {}
- file "c/d.rb", ""
- file "c/e.json", {}
- end
- directory "resources" do
- file "a.rb", ""
- file "b.json", {}
- file "c/d.rb", ""
- file "c/e.json", {}
- end
- directory "providers" do
- file "a.rb", ""
- file "b.json", {}
- file "c/d.rb", ""
- file "c/e.json", {}
- end
- end
- end
-
- it "knife list --local -Rfp / should NOT return them" do
- knife("list --local -Rfp /").should_succeed <<EOM
-/cookbooks/
-/cookbooks/cookbook1/
-/cookbooks/cookbook1/a.rb
-/cookbooks/cookbook1/attributes/
-/cookbooks/cookbook1/attributes/a.rb
-/cookbooks/cookbook1/definitions/
-/cookbooks/cookbook1/definitions/a.rb
-/cookbooks/cookbook1/files/
-/cookbooks/cookbook1/files/a.rb
-/cookbooks/cookbook1/files/b.json
-/cookbooks/cookbook1/files/c/
-/cookbooks/cookbook1/files/c/d.rb
-/cookbooks/cookbook1/files/c/e.json
-/cookbooks/cookbook1/libraries/
-/cookbooks/cookbook1/libraries/a.rb
-/cookbooks/cookbook1/libraries/b.json
-/cookbooks/cookbook1/libraries/c/
-/cookbooks/cookbook1/libraries/c/d.rb
-/cookbooks/cookbook1/libraries/c/e.json
-/cookbooks/cookbook1/providers/
-/cookbooks/cookbook1/providers/a.rb
-/cookbooks/cookbook1/providers/c/
-/cookbooks/cookbook1/providers/c/d.rb
-/cookbooks/cookbook1/recipes/
-/cookbooks/cookbook1/recipes/a.rb
-/cookbooks/cookbook1/resources/
-/cookbooks/cookbook1/resources/a.rb
-/cookbooks/cookbook1/resources/c/
-/cookbooks/cookbook1/resources/c/d.rb
-/cookbooks/cookbook1/templates/
-/cookbooks/cookbook1/templates/a.rb
-/cookbooks/cookbook1/templates/b.json
-/cookbooks/cookbook1/templates/c/
-/cookbooks/cookbook1/templates/c/d.rb
-/cookbooks/cookbook1/templates/c/e.json
-EOM
- end
- end
-
when_the_repository "has a file in cookbooks/" do
before { file "cookbooks/file", "" }
it "does not show up in list -Rfp" do
diff --git a/spec/integration/knife/cookbook_download_spec.rb b/spec/integration/knife/cookbook_download_spec.rb
index 2fbffb9dea..2e64cac133 100644
--- a/spec/integration/knife/cookbook_download_spec.rb
+++ b/spec/integration/knife/cookbook_download_spec.rb
@@ -35,14 +35,6 @@ describe "knife cookbook download", :workstation do
it "knife cookbook download downloads the latest version" do
knife("cookbook download -d #{tmpdir} x").should_succeed stderr: <<EOM
Downloading x cookbook version 1.0.1
-Downloading resources
-Downloading providers
-Downloading recipes
-Downloading definitions
-Downloading libraries
-Downloading attributes
-Downloading files
-Downloading templates
Downloading root_files
Cookbook downloaded to #{tmpdir}/x-1.0.1
EOM
@@ -51,14 +43,6 @@ EOM
it "knife cookbook download with a version downloads the specified version" do
knife("cookbook download -d #{tmpdir} x 1.0.1").should_succeed stderr: <<EOM
Downloading x cookbook version 1.0.1
-Downloading resources
-Downloading providers
-Downloading recipes
-Downloading definitions
-Downloading libraries
-Downloading attributes
-Downloading files
-Downloading templates
Downloading root_files
Cookbook downloaded to #{tmpdir}/x-1.0.1
EOM
@@ -78,14 +62,6 @@ EOM
it "knife cookbook download with no version prompts" do
knife("cookbook download -d #{tmpdir} x", input: "2\n").should_succeed(stderr: <<EOM, stdout: "Which version do you want to download?\n1. x 1.0.0\n2. x 1.0.1\n\n"
Downloading x cookbook version 1.0.1
-Downloading resources
-Downloading providers
-Downloading recipes
-Downloading definitions
-Downloading libraries
-Downloading attributes
-Downloading files
-Downloading templates
Downloading root_files
Cookbook downloaded to #{tmpdir}/x-1.0.1
EOM
diff --git a/spec/integration/knife/cookbook_show_spec.rb b/spec/integration/knife/cookbook_show_spec.rb
index c001d66b97..1ccf7ffcb7 100644
--- a/spec/integration/knife/cookbook_show_spec.rb
+++ b/spec/integration/knife/cookbook_show_spec.rb
@@ -37,22 +37,14 @@ describe "knife cookbook show", :workstation do
# rubocop:disable Style/TrailingWhitespace
it "knife cookbook show x 1.0.0 shows the correct version" do
knife("cookbook show x 1.0.0").should_succeed <<EOM
-attributes:
-chef_type: cookbook_version
cookbook_name: x
-definitions:
-files:
frozen?: false
-json_class: Chef::CookbookVersion
-libraries:
metadata:
attributes:
chef_versions:
- conflicting:
dependencies:
description:
gems:
- groupings:
issues_url:
license: All rights reserved
long_description:
@@ -63,34 +55,32 @@ metadata:
platforms:
privacy: false
providing:
+ x: >= 0.0.0
+ x::x: >= 0.0.0
recipes:
- recommendations:
- replacing:
+ x:
+ x::x:
source_url:
- suggestions:
version: 1.0.0
name: x-1.0.0
-providers:
recipes:
checksum: 4631b34cf58de10c5ef1304889941b2e
- name: default.rb
+ name: recipes/default.rb
path: recipes/default.rb
specificity: default
url: http://127.0.0.1:8900/file_store/checksums/4631b34cf58de10c5ef1304889941b2e
checksum: d41d8cd98f00b204e9800998ecf8427e
- name: x.rb
+ name: recipes/x.rb
path: recipes/x.rb
specificity: default
url: http://127.0.0.1:8900/file_store/checksums/d41d8cd98f00b204e9800998ecf8427e
-resources:
root_files:
checksum: 8226671f751ba102dea6a6b6bd32fa8d
name: metadata.rb
path: metadata.rb
specificity: default
url: http://127.0.0.1:8900/file_store/checksums/8226671f751ba102dea6a6b6bd32fa8d
-templates:
version: 1.0.0
EOM
end
@@ -99,11 +89,9 @@ EOM
knife("cookbook show x 1.0.0 metadata").should_succeed <<EOM
attributes:
chef_versions:
-conflicting:
dependencies:
description:
gems:
-groupings:
issues_url:
license: All rights reserved
long_description:
@@ -114,11 +102,12 @@ ohai_versions:
platforms:
privacy: false
providing:
+ x: >= 0.0.0
+ x::x: >= 0.0.0
recipes:
-recommendations:
-replacing:
+ x:
+ x::x:
source_url:
-suggestions:
version: 1.0.0
EOM
end
@@ -126,13 +115,13 @@ EOM
it "knife cookbook show x 1.0.0 recipes shows all the recipes" do
knife("cookbook show x 1.0.0 recipes").should_succeed <<EOM
checksum: 4631b34cf58de10c5ef1304889941b2e
-name: default.rb
+name: recipes/default.rb
path: recipes/default.rb
specificity: default
url: http://127.0.0.1:8900/file_store/checksums/4631b34cf58de10c5ef1304889941b2e
checksum: d41d8cd98f00b204e9800998ecf8427e
-name: x.rb
+name: recipes/x.rb
path: recipes/x.rb
specificity: default
url: http://127.0.0.1:8900/file_store/checksums/d41d8cd98f00b204e9800998ecf8427e
diff --git a/spec/integration/knife/search_node_spec.rb b/spec/integration/knife/search_node_spec.rb
new file mode 100644
index 0000000000..e3cda1a138
--- /dev/null
+++ b/spec/integration/knife/search_node_spec.rb
@@ -0,0 +1,39 @@
+#
+# Copyright:: Copyright 2013-2017, 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 "support/shared/integration/integration_helper"
+require "support/shared/context/config"
+
+describe "knife node show", :workstation do
+ include IntegrationSupport
+ include KnifeSupport
+
+ include_context "default config options"
+
+ when_the_chef_server "has a node with a run_list" do
+ before do
+ node "cons", { run_list: ["recipe[bar]", "recipe[foo]"] }
+ end
+
+ it "finds the node" do
+ knife("search node name:cons").should_succeed(/Node Name:\s*cons/, stderr: "1 items found\n\n")
+ end
+
+ it "does not find a node" do
+ knife("search node name:snoc").should_fail("", stderr: "0 items found\n\n", exit_code: 1)
+ end
+ end
+end
diff --git a/spec/integration/knife/serve_spec.rb b/spec/integration/knife/serve_spec.rb
index 72f0bb59ed..b0cdd8c070 100644
--- a/spec/integration/knife/serve_spec.rb
+++ b/spec/integration/knife/serve_spec.rb
@@ -24,33 +24,69 @@ describe "knife serve", :workstation do
include KnifeSupport
include AppServerSupport
+ def with_knife_serve
+ exception = nil
+ t = Thread.new do
+ begin
+ knife("serve --chef-zero-port=8890")
+ rescue
+ exception = $!
+ end
+ end
+ begin
+ Chef::Config.log_level = :debug
+ Chef::Config.chef_server_url = "http://localhost:8890"
+ Chef::Config.node_name = nil
+ Chef::Config.client_key = nil
+ api = Chef::ServerAPI.new
+ yield api
+ rescue
+ if exception
+ raise exception
+ else
+ raise
+ end
+ ensure
+ t.kill
+ sleep 0.5
+ end
+ end
+
when_the_repository "also has one of each thing" do
- before { file "nodes/x.json", { "foo" => "bar" } }
+ before do
+ file "nodes/a_node_in_json.json", { "foo" => "bar" }
+ file "nodes/a_node_in_ruby.rb", "name 'a_node_in_ruby'"
+ file "roles/a_role_in_json.json", { "foo" => "bar" }
+ file "roles/a_role_in_ruby.rb", "name 'a_role_in_ruby'"
+ end
- it "knife serve serves up /nodes/x" do
- exception = nil
- t = Thread.new do
- begin
- knife("serve --chef-zero-port=8890")
- rescue
- exception = $!
+ %w{a_node_in_json a_node_in_ruby}.each do |file_type|
+ context file_type do
+ it "knife serve serves up /nodes" do
+ with_knife_serve do |api|
+ expect(api.get("nodes")).to have_key(file_type)
+ end
+ end
+ it "knife serve serves up /nodes/#{file_type}" do
+ with_knife_serve do |api|
+ expect(api.get("nodes/#{file_type}")["name"]).to eq(file_type)
+ end
end
end
- begin
- Chef::Config.log_level = :debug
- Chef::Config.chef_server_url = "http://localhost:8890"
- Chef::Config.node_name = nil
- Chef::Config.client_key = nil
- api = Chef::ServerAPI.new
- expect(api.get("nodes/x")["name"]).to eq("x")
- rescue
- if exception
- raise exception
- else
- raise
+ end
+
+ %w{a_role_in_json a_role_in_ruby}.each do |file_type|
+ context file_type do
+ it "knife serve serves up /roles" do
+ with_knife_serve do |api|
+ expect(api.get("roles")).to have_key(file_type)
+ end
+ end
+ it "knife serve serves up /roles/#{file_type}" do
+ with_knife_serve do |api|
+ expect(api.get("roles/#{file_type}")["name"]).to eq(file_type)
+ end
end
- ensure
- t.kill
end
end
end
diff --git a/spec/integration/recipes/lwrp_inline_resources_spec.rb b/spec/integration/recipes/lwrp_inline_resources_spec.rb
index 65931d4764..54ce94f263 100644
--- a/spec/integration/recipes/lwrp_inline_resources_spec.rb
+++ b/spec/integration/recipes/lwrp_inline_resources_spec.rb
@@ -19,14 +19,13 @@ describe "LWRPs with inline resources" do
let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" }
context "with a use_inline_resources provider with 'def action_a' instead of action :a" do
- class LwrpInlineResourcesTest < Chef::Resource::LWRPBase
+ class LwrpInlineResourcesTest < Chef::Resource
resource_name :lwrp_inline_resources_test
- actions :a, :nothing
+ allowed_actions :a, :nothing
default_action :a
property :ran_a
class Provider < Chef::Provider::LWRPBase
provides :lwrp_inline_resources_test
- use_inline_resources
def action_a
r = new_resource
ruby_block "run a" do
@@ -46,10 +45,10 @@ describe "LWRPs with inline resources" do
end
context "with an inline resource with a property that shadows the enclosing provider's property" do
- class LwrpShadowedPropertyTest < Chef::Resource::LWRPBase
+ class LwrpShadowedPropertyTest < Chef::Resource
PATH = ::File.join(Dir.tmpdir, "shadow-property.txt")
use_automatic_resource_name
- actions :fiddle
+ allowed_actions :fiddle
property :content
action :fiddle do
file PATH do
@@ -73,16 +72,14 @@ describe "LWRPs with inline resources" do
end
context "with an inline_resources provider with two actions, one calling the other" do
- class LwrpInlineResourcesTest2 < Chef::Resource::LWRPBase
+ class LwrpInlineResourcesTest2 < Chef::Resource
resource_name :lwrp_inline_resources_test2
- actions :a, :b, :nothing
+ allowed_actions :a, :b, :nothing
default_action :b
property :ran_a
property :ran_b
class Provider < Chef::Provider::LWRPBase
provides :lwrp_inline_resources_test2
- use_inline_resources
-
action :a do
r = new_resource
ruby_block "run a" do
@@ -133,8 +130,7 @@ describe "LWRPs with inline resources" do
default_action :create
EOM
file "providers/my_machine.rb", <<-EOM
- use_inline_resources
- action :create do
+ action :create do
x_do_nothing 'a'
x_do_nothing 'b'
end
diff --git a/spec/integration/recipes/notifies_spec.rb b/spec/integration/recipes/notifies_spec.rb
index 6f6a0f06b0..b008e4ade7 100644
--- a/spec/integration/recipes/notifies_spec.rb
+++ b/spec/integration/recipes/notifies_spec.rb
@@ -362,4 +362,33 @@ EOM
result.error!
end
end
+
+ when_the_repository "has resources that have arrays as the name" do
+ before do
+ directory "cookbooks/x" do
+ file "recipes/default.rb", <<-EOM
+ log [ "a", "b" ] do
+ action :nothing
+ end
+
+ log "doit" do
+ notifies :write, "log[a, b]"
+ end
+ EOM
+ end
+ end
+
+ it "notifying the resource should work" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ expect(result.stdout).to match /\* log\[a, b\] action write/
+ result.error!
+ end
+
+ end
end
diff --git a/spec/support/shared/context/client.rb b/spec/support/shared/context/client.rb
index c65650e6b1..19ce82fa15 100644
--- a/spec/support/shared/context/client.rb
+++ b/spec/support/shared/context/client.rb
@@ -129,12 +129,18 @@ shared_context "a client run" do
# ---Client#sync_cookbooks -- downloads the list of cookbooks to sync
#
expect_any_instance_of(Chef::CookbookSynchronizer).to receive(:sync_cookbooks)
- expect(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_url]).and_return(http_cookbook_sync)
+ expect(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_url], version_class: Chef::CookbookManifestVersions).and_return(http_cookbook_sync)
expect(http_cookbook_sync).to receive(:post).
with("environments/_default/cookbook_versions", { :run_list => [] }).
and_return({})
end
+ def stub_for_required_recipe
+ response = Net::HTTPNotFound.new("1.1", "404", "Not Found")
+ exception = Net::HTTPServerException.new('404 "Not Found"', response)
+ expect(http_node_load).to receive(:get).with("required_recipe").and_raise(exception)
+ end
+
def stub_for_converge
# define me
end
@@ -165,6 +171,7 @@ shared_context "a client run" do
stub_for_data_collector_init
stub_for_node_load
stub_for_sync_cookbooks
+ stub_for_required_recipe
stub_for_converge
stub_for_audit
stub_for_node_save
diff --git a/spec/support/shared/integration/knife_support.rb b/spec/support/shared/integration/knife_support.rb
index 4efa30a003..d873723784 100644
--- a/spec/support/shared/integration/knife_support.rb
+++ b/spec/support/shared/integration/knife_support.rb
@@ -1,6 +1,6 @@
#
# Author:: John Keiser (<jkeiser@chef.io>)
-# Copyright:: Copyright 2013-2016, Chef Software Inc.
+# Copyright:: Copyright 2013-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/spec/unit/application/exit_code_spec.rb b/spec/unit/application/exit_code_spec.rb
index 5abf19fc02..7783cf3ed7 100644
--- a/spec/unit/application/exit_code_spec.rb
+++ b/spec/unit/application/exit_code_spec.rb
@@ -70,92 +70,11 @@ describe Chef::Application::ExitCode do
end
end
- context "when Chef::Config :exit_status is not configured" do
- before do
- allow(Chef::Config).to receive(:[]).with(:exit_status).and_return(nil)
- allow(Chef::Config).to receive(:[]).with(:treat_deprecation_warnings_as_errors).and_return(false)
- end
-
- it "writes a deprecation warning" do
- expect(Chef).to receive(:deprecated).with(:exit_code, /^Chef RFC 062/)
- expect(exit_codes.normalize_exit_code(151)).to eq(151)
- end
-
- it "does not modify non-RFC exit codes" do
- expect(exit_codes.normalize_exit_code(151)).to eq(151)
- end
-
- it "returns DEPRECATED_FAILURE when no exit code is specified" do
- expect(exit_codes.normalize_exit_code()).to eq(-1)
- end
-
- it "returns SIGINT_RECEIVED when a SIGINT is received" do
- expect(exit_codes.normalize_exit_code(Chef::Exceptions::SigInt.new("BOOM"))).to eq(2)
- end
-
- it "returns SIGTERM_RECEIVED when a SIGTERM is received" do
- expect(exit_codes.normalize_exit_code(Chef::Exceptions::SigTerm.new("BOOM"))).to eq(3)
- end
-
- it "returns SIGINT_RECEIVED when a deprecated exit code error is received" do
- expect(exit_codes.normalize_exit_code(Chef::Exceptions::DeprecatedExitCode.new("BOOM"))).to eq(2)
- end
-
- it "returns GENERIC_FAILURE when an exception is specified" do
- expect(exit_codes.normalize_exit_code(Exception.new("BOOM"))).to eq(1)
- end
-
- end
-
- context "when Chef::Config :exit_status is configured to not validate exit codes" do
- before do
- allow(Chef::Config).to receive(:[]).with(:exit_status).and_return(:disabled)
- allow(Chef::Config).to receive(:[]).with(:treat_deprecation_warnings_as_errors).and_return(false)
- end
-
- it "does not write a deprecation warning" do
- expect(Chef).not_to receive(:deprecated).with(:exit_code, /^Chef RFC 062/)
- expect(exit_codes.normalize_exit_code(151)).to eq(151)
- end
-
- it "does not modify non-RFC exit codes" do
- expect(exit_codes.normalize_exit_code(151)).to eq(151)
- end
-
- it "returns DEPRECATED_FAILURE when no exit code is specified" do
- expect(exit_codes.normalize_exit_code()).to eq(-1)
- end
-
- it "returns GENERIC_FAILURE when an exception is specified" do
- expect(exit_codes.normalize_exit_code(Exception.new("BOOM"))).to eq(1)
- end
-
- it "returns SUCCESS when a reboot is pending" do
- allow(Chef::DSL::RebootPending).to receive(:reboot_pending?).and_return(true)
- expect(exit_codes.normalize_exit_code(0)).to eq(0)
- end
-
- it "returns SIGINT_RECEIVED when a SIGINT is received" do
- expect(exit_codes.normalize_exit_code(Chef::Exceptions::SigInt.new("BOOM"))).to eq(2)
- end
-
- it "returns SIGTERM_RECEIVED when a SIGTERM is received" do
- expect(exit_codes.normalize_exit_code(Chef::Exceptions::SigTerm.new("BOOM"))).to eq(3)
- end
-
- it "returns SIGINT_RECEIVED when a deprecated exit code error is received" do
- expect(exit_codes.normalize_exit_code(Chef::Exceptions::DeprecatedExitCode.new("BOOM"))).to eq(2)
- end
- end
+ context "when Chef validates exit codes" do
- context "when Chef::Config :exit_status is configured to validate exit codes" do
- before do
- allow(Chef::Config).to receive(:[]).with(:exit_status).and_return(:enabled)
- allow(Chef::Config).to receive(:[]).with(:treat_deprecation_warnings_as_errors).and_return(false)
- end
-
- it "does write a deprecation warning" do
- expect(Chef).to receive(:deprecated).with(:exit_code, /^Chef RFC 062/)
+ it "does write a warning on non-standard exit codes" do
+ expect(Chef::Log).to receive(:warn).with(
+ /^Chef attempted to exit with a non-standard exit code of 151/)
expect(exit_codes.normalize_exit_code(151)).to eq(1)
end
@@ -175,10 +94,6 @@ describe Chef::Application::ExitCode do
expect(exit_codes.normalize_exit_code(Chef::Exceptions::SigTerm.new("BOOM"))).to eq(3)
end
- it "returns GENERIC_FAILURE when a deprecated exit code error is received" do
- expect(exit_codes.normalize_exit_code(Chef::Exceptions::DeprecatedExitCode.new("BOOM"))).to eq(1)
- end
-
it "returns GENERIC_FAILURE when an exception is specified" do
expect(exit_codes.normalize_exit_code(Exception.new("BOOM"))).to eq(1)
end
diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb
index 867cd3f9c2..7981748962 100644
--- a/spec/unit/application_spec.rb
+++ b/spec/unit/application_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: AJ Christensen (<aj@junglist.gen.nz>)
# Author:: Mark Mzyk (mmzyk@chef.io)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -187,53 +187,56 @@ describe Chef::Application do
allow(Chef::Log).to receive(:level=)
@monologger = double("Monologger")
expect(MonoLogger).to receive(:new).with(Chef::Config[:log_location]).and_return(@monologger)
+ allow(MonoLogger).to receive(:new).with(STDOUT).and_return(@monologger)
+ allow(@monologger).to receive(:formatter=).with(Chef::Log.logger.formatter)
expect(Chef::Log).to receive(:init).with(@monologger)
@app.configure_logging
end
shared_examples_for "log_level_is_auto" do
- context "when STDOUT is to a tty" do
+ before do
+ allow(STDOUT).to receive(:tty?).and_return(true)
+ end
+
+ it "configures the log level to :warn" do
+ @app.configure_logging
+ expect(Chef::Log.level).to eq(:warn)
+ end
+
+ context "when force_formater is configured" do
before do
- allow(STDOUT).to receive(:tty?).and_return(true)
+ Chef::Config[:force_formatter] = true
end
- it "configures the log level to :warn" do
+ it "configures the log level to warn" do
@app.configure_logging
expect(Chef::Log.level).to eq(:warn)
end
-
- context "when force_logger is configured" do
- before do
- Chef::Config[:force_logger] = true
- end
-
- it "configures the log level to info" do
- @app.configure_logging
- expect(Chef::Log.level).to eq(:info)
- end
- end
end
- context "when STDOUT is not to a tty" do
+ context "when force_logger is configured" do
before do
- allow(STDOUT).to receive(:tty?).and_return(false)
+ Chef::Config[:force_logger] = true
end
- it "configures the log level to :info" do
+ it "configures the log level to info" do
@app.configure_logging
expect(Chef::Log.level).to eq(:info)
end
+ end
- context "when force_formatter is configured" do
- before do
- Chef::Config[:force_formatter] = true
- end
- it "sets the log level to :warn" do
- @app.configure_logging
- expect(Chef::Log.level).to eq(:warn)
- end
+ context "when both are is configured" do
+ before do
+ Chef::Config[:force_logger] = true
+ Chef::Config[:force_formatter] = true
+ end
+
+ it "configures the log level to warn" do
+ @app.configure_logging
+ expect(Chef::Log.level).to eq(:warn)
end
end
+
end
context "when log_level is not set" do
@@ -299,16 +302,23 @@ describe Chef::Application do
Chef::Application.fatal! "blah"
end
- describe "when an exit code is supplied" do
+ describe "when a standard exit code is supplied" do
it "should exit with the given exit code" do
- expect(Process).to receive(:exit).with(-100).and_return(true)
+ expect(Process).to receive(:exit).with(42).and_return(true)
+ Chef::Application.fatal! "blah", 42
+ end
+ end
+
+ describe "when a non-standard exit code is supplied" do
+ it "should exit with the default exit code" do
+ expect(Process).to receive(:exit).with(1).and_return(true)
Chef::Application.fatal! "blah", -100
end
end
describe "when an exit code is not supplied" do
it "should exit with the default exit code" do
- expect(Process).to receive(:exit).with(-1).and_return(true)
+ expect(Process).to receive(:exit).with(1).and_return(true)
Chef::Application.fatal! "blah"
end
end
diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb
index ec3f70b9b0..d348c24385 100644
--- a/spec/unit/client_spec.rb
+++ b/spec/unit/client_spec.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Tim Hinderliter (<tim@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software, Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -71,48 +71,40 @@ describe Chef::Client do
describe "configuring output formatters" do
context "when no formatter has been configured" do
- context "and STDOUT is a TTY" do
+ it "configures the :doc formatter" do
+ expect(client.formatters_for_run).to eq([[:doc]])
+ end
+
+ context "and force_logger is set" do
before do
- allow(STDOUT).to receive(:tty?).and_return(true)
+ Chef::Config[:force_logger] = true
end
- it "configures the :doc formatter" do
- expect(client.formatters_for_run).to eq([[:doc]])
+ it "configures the :null formatter" do
+ expect(client.formatters_for_run).to eq([[:null]])
end
+ end
- context "and force_logger is set" do
- before do
- Chef::Config[:force_logger] = true
- end
-
- it "configures the :null formatter" do
- expect(Chef::Config[:force_logger]).to be_truthy
- expect(client.formatters_for_run).to eq([[:null]])
- end
-
+ context "and force_formatter is set" do
+ before do
+ Chef::Config[:force_formatter] = true
end
+ it "configures the :doc formatter" do
+ expect(client.formatters_for_run).to eq([[:doc]])
+ end
end
- context "and STDOUT is not a TTY" do
+ context "both are set" do
before do
- allow(STDOUT).to receive(:tty?).and_return(false)
+ Chef::Config[:force_formatter] = true
+ Chef::Config[:force_logger] = true
end
- it "configures the :null formatter" do
- expect(client.formatters_for_run).to eq([[:null]])
- end
-
- context "and force_formatter is set" do
- before do
- Chef::Config[:force_formatter] = true
- end
- it "it configures the :doc formatter" do
- expect(client.formatters_for_run).to eq([[:doc]])
- end
+ it "configures the :doc formatter" do
+ expect(client.formatters_for_run).to eq([[:doc]])
end
end
-
end
context "when a formatter is configured" do
@@ -188,7 +180,7 @@ describe Chef::Client do
# ---Client#sync_cookbooks -- downloads the list of cookbooks to sync
#
expect_any_instance_of(Chef::CookbookSynchronizer).to receive(:sync_cookbooks)
- expect(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_url]).and_return(http_cookbook_sync)
+ expect(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_url], version_class: Chef::CookbookManifestVersions).and_return(http_cookbook_sync)
expect(http_cookbook_sync).to receive(:post).
with("environments/_default/cookbook_versions", { :run_list => ["override_recipe"] }).
and_return({})
@@ -222,7 +214,7 @@ describe Chef::Client do
# ---Client#sync_cookbooks -- downloads the list of cookbooks to sync
#
expect_any_instance_of(Chef::CookbookSynchronizer).to receive(:sync_cookbooks)
- expect(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_url]).and_return(http_cookbook_sync)
+ expect(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_url], version_class: Chef::CookbookManifestVersions).and_return(http_cookbook_sync)
expect(http_cookbook_sync).to receive(:post).
with("environments/_default/cookbook_versions", { :run_list => ["new_run_list_recipe"] }).
and_return({})
@@ -402,6 +394,55 @@ describe Chef::Client do
end
end
+ describe "load_required_recipe" do
+ let(:rest) { double("Chef::ServerAPI (required recipe)") }
+ let(:run_context) { double("Chef::RunContext") }
+ let(:recipe) { double("Chef::Recipe (required recipe)") }
+ let(:required_recipe) do
+ <<EOM
+fake_recipe_variable = "for reals"
+EOM
+ end
+
+ context "when required_recipe is configured" do
+
+ before(:each) do
+ expect(rest).to receive(:get).with("required_recipe").and_return(required_recipe)
+ expect(Chef::Recipe).to receive(:new).with(nil, nil, run_context).and_return(recipe)
+ expect(recipe).to receive(:from_file)
+ end
+
+ it "fetches the recipe and adds it to the run context" do
+ client.load_required_recipe(rest, run_context)
+ end
+
+ context "when the required_recipe has bad contents" do
+ let(:required_recipe) do
+ <<EOM
+this is not a recipe
+EOM
+ end
+ it "should not raise an error" do
+ expect { client.load_required_recipe(rest, run_context) }.not_to raise_error()
+ end
+ end
+ end
+
+ context "when required_recipe returns 404" do
+ let(:http_response) { Net::HTTPNotFound.new("1.1", "404", "Not Found") }
+ let(:http_exception) { Net::HTTPServerException.new('404 "Not Found"', http_response) }
+
+ before(:each) do
+ expect(rest).to receive(:get).with("required_recipe").and_raise(http_exception)
+ end
+
+ it "should log and continue on" do
+ expect(Chef::Log).to receive(:debug)
+ client.load_required_recipe(rest, run_context)
+ end
+ end
+ end
+
describe "windows_admin_check" do
context "platform is not windows" do
before do
diff --git a/spec/unit/config_fetcher_spec.rb b/spec/unit/config_fetcher_spec.rb
index 6847ee5fd3..a674d4de33 100644
--- a/spec/unit/config_fetcher_spec.rb
+++ b/spec/unit/config_fetcher_spec.rb
@@ -58,7 +58,7 @@ describe Chef::ConfigFetcher do
and_return(invalid_json)
expect(Chef::Application).to receive(:fatal!).
- with(invalid_json_error_regex, Chef::Exceptions::DeprecatedExitCode.new)
+ with(invalid_json_error_regex)
fetcher.fetch_json
end
end
@@ -104,7 +104,7 @@ describe Chef::ConfigFetcher do
with("").and_return(invalid_json)
expect(Chef::Application).to receive(:fatal!).
- with(invalid_json_error_regex, Chef::Exceptions::DeprecatedExitCode.new)
+ with(invalid_json_error_regex)
fetcher.fetch_json
end
end
diff --git a/spec/unit/cookbook/cookbook_version_loader_spec.rb b/spec/unit/cookbook/cookbook_version_loader_spec.rb
index 786e17f35b..40a054abee 100644
--- a/spec/unit/cookbook/cookbook_version_loader_spec.rb
+++ b/spec/unit/cookbook/cookbook_version_loader_spec.rb
@@ -40,42 +40,45 @@ describe Chef::Cookbook::CookbookVersionLoader do
File.join(cookbook_path, cookbook_relative_path)
end
+ def full_paths_for_part(part)
+ loaded_cookbook.files_for(part).inject([]) { |memo, f| memo << f[:full_path]; memo }
+ end
+
it "loads attribute files of the cookbook" do
- expect(loaded_cookbook.attribute_filenames).to include(full_path("/attributes/default.rb"))
- expect(loaded_cookbook.attribute_filenames).to include(full_path("/attributes/smokey.rb"))
+ expect(full_paths_for_part("attributes")).to include(full_path("/attributes/default.rb"))
+ expect(full_paths_for_part("attributes")).to include(full_path("/attributes/smokey.rb"))
end
it "loads definition files" do
- expect(loaded_cookbook.definition_filenames).to include(full_path("/definitions/client.rb"))
- expect(loaded_cookbook.definition_filenames).to include(full_path("/definitions/server.rb"))
+ expect(full_paths_for_part("definitions")).to include(full_path("/definitions/client.rb"))
+ expect(full_paths_for_part("definitions")).to include(full_path("/definitions/server.rb"))
end
it "loads recipes" do
- expect(loaded_cookbook.recipe_filenames).to include(full_path("/recipes/default.rb"))
- expect(loaded_cookbook.recipe_filenames).to include(full_path("/recipes/gigantor.rb"))
- expect(loaded_cookbook.recipe_filenames).to include(full_path("/recipes/one.rb"))
- expect(loaded_cookbook.recipe_filenames).to include(full_path("/recipes/return.rb"))
+ expect(full_paths_for_part("recipes")).to include(full_path("/recipes/default.rb"))
+ expect(full_paths_for_part("recipes")).to include(full_path("/recipes/gigantor.rb"))
+ expect(full_paths_for_part("recipes")).to include(full_path("/recipes/one.rb"))
+ expect(full_paths_for_part("recipes")).to include(full_path("/recipes/return.rb"))
end
it "loads libraries" do
- expect(loaded_cookbook.library_filenames).to include(full_path("/libraries/openldap.rb"))
- expect(loaded_cookbook.library_filenames).to include(full_path("/libraries/openldap/version.rb"))
+ expect(full_paths_for_part("libraries")).to include(full_path("/libraries/openldap.rb"))
+ expect(full_paths_for_part("libraries")).to include(full_path("/libraries/openldap/version.rb"))
end
it "loads static files in the files/ dir" do
- expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/remotedir/remotesubdir/remote_subdir_file1.txt"))
- expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/remotedir/remotesubdir/remote_subdir_file2.txt"))
+ expect(full_paths_for_part("files")).to include(full_path("/files/default/remotedir/remotesubdir/remote_subdir_file1.txt"))
+ expect(full_paths_for_part("files")).to include(full_path("/files/default/remotedir/remotesubdir/remote_subdir_file2.txt"))
end
it "loads files that start with a ." do
- expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/.dotfile"))
- expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/.ssh/id_rsa"))
- expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/remotedir/.a_dotdir/.a_dotfile_in_a_dotdir"))
+ expect(full_paths_for_part("files")).to include(full_path("/files/default/.dotfile"))
+ expect(full_paths_for_part("files")).to include(full_path("/files/default/.ssh/id_rsa"))
+ expect(full_paths_for_part("files")).to include(full_path("/files/default/remotedir/.a_dotdir/.a_dotfile_in_a_dotdir"))
end
it "loads root files that start with a ." do
expect(loaded_cookbook.all_files).to include(full_path(".root_dotfile"))
- expect(loaded_cookbook.root_filenames).to include(full_path(".root_dotfile"))
end
it "loads all unignored files, even if they don't match a segment type" do
@@ -97,9 +100,9 @@ describe Chef::Cookbook::CookbookVersionLoader do
let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "kitchen/openldap") }
it "skips ignored files" do
- expect(loaded_cookbook.recipe_filenames).to include(full_path("recipes/gigantor.rb"))
- expect(loaded_cookbook.recipe_filenames).to include(full_path("recipes/woot.rb"))
- expect(loaded_cookbook.recipe_filenames).to_not include(full_path("recipes/ignoreme.rb"))
+ expect(full_paths_for_part("recipes")).to include(full_path("recipes/gigantor.rb"))
+ expect(full_paths_for_part("recipes")).to include(full_path("recipes/woot.rb"))
+ expect(full_paths_for_part("recipes")).to_not include(full_path("recipes/ignoreme.rb"))
end
end
diff --git a/spec/unit/cookbook/file_vendor_spec.rb b/spec/unit/cookbook/file_vendor_spec.rb
index 164fbd8177..557e1b8775 100644
--- a/spec/unit/cookbook/file_vendor_spec.rb
+++ b/spec/unit/cookbook/file_vendor_spec.rb
@@ -16,6 +16,7 @@
# limitations under the License.
#
require "spec_helper"
+require "chef/cookbook_version"
describe Chef::Cookbook::FileVendor do
@@ -25,6 +26,12 @@ describe Chef::Cookbook::FileVendor do
let(:http) { double("Chef::ServerAPI") }
+ # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest
+ let(:manifest) do
+ cbv = Chef::CookbookVersion.new("bob", Array(Dir.tmpdir))
+ cbv.cookbook_manifest
+ end
+
before do
file_vendor_class.fetch_from_remote(http)
end
@@ -39,8 +46,11 @@ describe Chef::Cookbook::FileVendor do
context "with a manifest from a cookbook version" do
- # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest
- let(:manifest) { { :cookbook_name => "bob", :name => "bob-1.2.3" } }
+ # # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest
+ # let(:manifest) do
+ # cbv = Chef::CookbookVersion.new("bob", Array(Dir.tmpdir))
+ # cbv.cookbook_manifest
+ # end
it "creates a RemoteFileVendor for a given manifest" do
file_vendor = file_vendor_class.create_from_manifest(manifest)
@@ -53,9 +63,6 @@ describe Chef::Cookbook::FileVendor do
context "with a manifest from a cookbook artifact" do
- # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest
- let(:manifest) { { :name => "bob" } }
-
it "creates a RemoteFileVendor for a given manifest" do
file_vendor = file_vendor_class.create_from_manifest(manifest)
expect(file_vendor).to be_a_kind_of(Chef::Cookbook::RemoteFileVendor)
@@ -70,8 +77,10 @@ describe Chef::Cookbook::FileVendor do
let(:cookbook_path) { %w{/var/chef/cookbooks /var/chef/other_cookbooks} }
- # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest
- let(:manifest) { { :cookbook_name => "bob" } }
+ let(:manifest) do
+ cbv = Chef::CookbookVersion.new("bob", Array(Dir.tmpdir))
+ cbv.cookbook_manifest
+ end
before do
file_vendor_class.fetch_from_disk(cookbook_path)
@@ -97,8 +106,10 @@ describe Chef::Cookbook::FileVendor do
context "when vendoring a cookbook with a name mismatch" do
let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks") }
- # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest
- let(:manifest) { { :cookbook_name => "name-mismatch" } }
+ let(:manifest) do
+ cbv = Chef::CookbookVersion.new("name-mismatch", Array(Dir.tmpdir))
+ cbv.cookbook_manifest
+ end
before do
file_vendor_class.fetch_from_disk(cookbook_path)
diff --git a/spec/unit/cookbook/gem_installer_spec.rb b/spec/unit/cookbook/gem_installer_spec.rb
new file mode 100644
index 0000000000..91e6959331
--- /dev/null
+++ b/spec/unit/cookbook/gem_installer_spec.rb
@@ -0,0 +1,85 @@
+require "spec_helper"
+require "bundler/dsl"
+
+describe Chef::Cookbook::GemInstaller do
+ let(:cookbook_collection) do
+ {
+ test: double(
+ :cookbook,
+ metadata: double(
+ :metadata,
+ gems: [["httpclient"], ["nokogiri"]]
+ )
+ ),
+ test2: double(
+ :cookbook,
+ metadata: double(
+ :metadata,
+ gems: [["httpclient", ">= 2.0"]]
+ )
+ ),
+ test3: double(
+ :cookbook,
+ metadata: double(
+ :metadata,
+ gems: [["httpclient", ">= 1.0"]]
+ )
+ ),
+ }
+ end
+
+ let(:gem_installer) do
+ described_class.new(cookbook_collection, Chef::EventDispatch::Dispatcher.new)
+ end
+
+ let(:gemfile) do
+ StringIO.new
+ end
+
+ let(:shell_out) do
+ double(:shell_out, stdout: "")
+ end
+
+ let(:bundler_dsl) do
+ b = Bundler::Dsl.new
+ b.instance_eval(gemfile.string)
+ b
+ end
+
+ before(:each) do
+ # Prepare mocks: using a StringIO instead of a File
+ expect(Dir).to receive(:mktmpdir).and_yield("")
+ expect(File).to receive(:open).and_yield(gemfile)
+ expect(gemfile).to receive(:path).and_return("")
+ expect(IO).to receive(:read).and_return("")
+ expect(gem_installer).to receive(:shell_out!).and_return(shell_out)
+
+ end
+
+ it "generates a valid Gemfile" do
+ expect { gem_installer.install }.to_not raise_error
+
+ expect { bundler_dsl }.to_not raise_error
+ end
+
+ it "generate a Gemfile with all constraints" do
+ expect { gem_installer.install }.to_not raise_error
+
+ expect(bundler_dsl.dependencies.find { |d| d.name == "httpclient" }.requirements_list.length).to eql(2)
+ end
+
+ it "generates a valid Gemfile when Chef::Config[:rubygems_url] is set to a String" do
+ Chef::Config[:rubygems_url] = "https://www.rubygems.org"
+ expect { gem_installer.install }.to_not raise_error
+
+ expect(bundler_dsl.dependencies.find { |d| d.name == "httpclient" }.requirements_list.length).to eql(2)
+ end
+
+ it "generates a valid Gemfile when Chef::Config[:rubygems_url] is set to an Array" do
+ Chef::Config[:rubygems_url] = [ "https://www.rubygems.org" ]
+
+ expect { gem_installer.install }.to_not raise_error
+
+ expect(bundler_dsl.dependencies.find { |d| d.name == "httpclient" }.requirements_list.length).to eql(2)
+ end
+end
diff --git a/spec/unit/cookbook/manifest_v0_spec.rb b/spec/unit/cookbook/manifest_v0_spec.rb
new file mode 100644
index 0000000000..0f5cfbe7a4
--- /dev/null
+++ b/spec/unit/cookbook/manifest_v0_spec.rb
@@ -0,0 +1,133 @@
+#
+# Copyright:: Copyright 2017, 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 "chef/cookbook_manifest"
+require "chef/digester"
+require "pathname"
+
+describe Chef::Cookbook::ManifestV0 do
+ let(:version) { "1.2.3" }
+
+ let(:identifier) { "9e10455ce2b4a4e29424b7064b1d67a1a25c9d3b" }
+
+ let(:metadata) do
+ Chef::Cookbook::Metadata.new.tap do |m|
+ m.version(version)
+ end
+ end
+
+ let(:cookbook_root) { "/tmp/blah" }
+
+ let(:cookbook_version) do
+ Chef::CookbookVersion.new("tatft", cookbook_root).tap do |c|
+ c.metadata = metadata
+ c.identifier = identifier
+ end
+ end
+
+ let(:cookbook_manifest) { Chef::CookbookManifest.new(cookbook_version) }
+
+ let(:cookbook_root) { File.join(CHEF_SPEC_DATA, "cb_version_cookbooks", "tatft") }
+
+ let(:all_files) { Dir[File.join(cookbook_root, "**", "**")].reject { |f| File.directory? f } }
+
+ let(:expected_hash) do
+ {
+ "attributes" => [{ "name" => "default.rb", "path" => "attributes/default.rb", "checksum" => "a88697db56181498a8828d5531271ad9", "specificity" => "default" }],
+ "chef_type" => "cookbook_version",
+ "cookbook_name" => "tatft",
+ "definitions" => [{ "name" => "runit_service.rb", "path" => "definitions/runit_service.rb", "checksum" => "c40cf9b4c6eb15a8e49e31602f701161", "specificity" => "default" }],
+ "files" => [{ "name" => "giant_blob.tgz", "path" => "files/default/giant_blob.tgz", "checksum" => "5b4b194bb80938bb18da7af5c823cb1b", "specificity" => "default" }],
+ "frozen?" => false,
+ "libraries" => [{ "name" => "ownage.rb", "path" => "libraries/ownage.rb", "checksum" => "4686edd9968909034692e09e058d90d9", "specificity" => "default" }],
+ "name" => "tatft-1.2.3",
+ "providers" => [{ "name" => "lwp.rb", "path" => "providers/lwp.rb", "checksum" => "bc189d68f77bb054d1070aeff7669557", "specificity" => "default" }],
+ "recipes" => [{ "name" => "default.rb", "path" => "recipes/default.rb", "checksum" => "09bc749f00c68717d288de9c8d7c644f", "specificity" => "default" }],
+ "resources" => [{ "name" => "lwr.rb", "path" => "resources/lwr.rb", "checksum" => "609c40d3d3f269e7edf230277a240ef5", "specificity" => "default" }],
+ "root_files" => [{ "name" => "README.rdoc", "path" => "README.rdoc", "checksum" => "cd7be9a1b9b1f33e3bcd9c3f4bc8dde5", "specificity" => "default" }],
+ "templates" => [{ "name" => "configuration.erb", "path" => "templates/default/configuration.erb", "checksum" => "d41d8cd98f00b204e9800998ecf8427e", "specificity" => "default" }],
+ "version" => "1.2.3",
+ }
+ end
+
+ describe "#from_hash" do
+ let(:source_hash) do
+ {
+ "attributes" => [{ "name" => "default.rb", "path" => "attributes/default.rb", "checksum" => "a88697db56181498a8828d5531271ad9", "specificity" => "default" }],
+ "recipes" => [{ "name" => "default.rb", "path" => "recipes/default.rb", "checksum" => "09bc749f00c68717d288de9c8d7c644f", "specificity" => "default" }],
+ "root_files" => [{ "name" => "README.rdoc", "path" => "README.rdoc", "checksum" => "cd7be9a1b9b1f33e3bcd9c3f4bc8dde5", "specificity" => "default" }],
+ "name" => "tatft-1.2.3",
+ "version" => "1.2.3",
+ }
+ end
+
+ it "preserves the version" do
+ result = described_class.from_hash(source_hash)
+ expect(result["version"]).to eq "1.2.3"
+ end
+
+ it "creates an all_files key and populates it" do
+ result = described_class.from_hash(source_hash)
+ expect(result[:all_files].map { |f| f["name"] }).to match_array %w{ recipes/default.rb attributes/default.rb README.rdoc }
+ end
+
+ it "deletes unwanted segment types" do
+ result = described_class.from_hash(source_hash)
+ expect(result["attributes"]).to be_nil
+ end
+
+ it "preserves frozeness" do
+ source_hash["frozen?"] = true
+ result = described_class.from_hash(source_hash)
+ expect(result["frozen?"]).to be true
+ end
+ end
+
+ describe "#to_hash" do
+ it "accepts a cookbook manifest" do
+ result = described_class.to_hash(cookbook_manifest)
+ expect(result).to be_a(Hash)
+ end
+
+ it "preserves frozeness" do
+ cookbook_version.freeze_version
+ expect(described_class.to_hash(cookbook_manifest)["frozen?"]).to be true
+ end
+ end
+
+ context "ensures that all segments exist" do
+ Chef::Cookbook::ManifestV0::COOKBOOK_SEGMENTS.each do |segment|
+ it "with #{segment}" do
+ result = described_class.to_hash(cookbook_manifest)
+ expect(result[segment]).to be_empty
+ end
+ end
+ end
+
+ context "when given a cookbook with some files" do
+ before do
+ cookbook_version.all_files = all_files
+ end
+
+ Chef::Cookbook::ManifestV0::COOKBOOK_SEGMENTS.each do |segment|
+ it "places the files for #{segment} correctly" do
+ result = described_class.to_hash(cookbook_manifest)
+ expect(result[segment]).to eq(expected_hash[segment])
+ end
+ end
+ end
+end
diff --git a/spec/unit/cookbook/manifest_v2_spec.rb b/spec/unit/cookbook/manifest_v2_spec.rb
new file mode 100644
index 0000000000..23df950f4a
--- /dev/null
+++ b/spec/unit/cookbook/manifest_v2_spec.rb
@@ -0,0 +1,70 @@
+#
+# Copyright:: Copyright 2017, 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 "chef/cookbook_manifest"
+require "chef/digester"
+require "pathname"
+
+describe Chef::Cookbook::ManifestV2 do
+ let(:version) { "1.2.3" }
+
+ let(:identifier) { "9e10455ce2b4a4e29424b7064b1d67a1a25c9d3b" }
+
+ let(:metadata) do
+ Chef::Cookbook::Metadata.new.tap do |m|
+ m.version(version)
+ end
+ end
+
+ let(:cookbook_root) { "/tmp/blah" }
+
+ let(:cookbook_version) do
+ Chef::CookbookVersion.new("tatft", cookbook_root).tap do |c|
+ c.metadata = metadata
+ c.identifier = identifier
+ end
+ end
+
+ let(:cookbook_manifest) { Chef::CookbookManifest.new(cookbook_version) }
+
+ let(:cookbook_root) { File.join(CHEF_SPEC_DATA, "cb_version_cookbooks", "tatft") }
+
+ let(:all_files) { Dir[File.join(cookbook_root, "**", "**")].reject { |f| File.directory? f } }
+
+ describe "#to_hash" do
+ it "accepts a cookbook manifest" do
+ result = described_class.to_hash(cookbook_manifest)
+ expect(result).to be_a(Hash)
+ end
+
+ it "preserves frozeness" do
+ cookbook_version.freeze_version
+ expect(described_class.to_hash(cookbook_manifest)["frozen?"]).to be true
+ end
+ end
+
+ context "when given a cookbook with some files" do
+ before do
+ cookbook_version.all_files = all_files
+ end
+
+ it "populates all_files correctly" do
+ result = described_class.to_hash(cookbook_manifest)
+ expect(result["all_files"][0]).not_to include(:full_path)
+ end
+ end
+end
diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb
index d1117127f1..2fdc43c289 100644
--- a/spec/unit/cookbook/metadata_spec.rb
+++ b/spec/unit/cookbook/metadata_spec.rb
@@ -28,8 +28,7 @@ describe Chef::Cookbook::Metadata do
before do
@fields = [ :name, :description, :long_description, :maintainer,
:maintainer_email, :license, :platforms, :dependencies,
- :recommendations, :suggestions, :conflicting, :providing,
- :replacing, :attributes, :groupings, :recipes, :version,
+ :providing, :attributes, :recipes, :version,
:source_url, :issues_url, :privacy, :ohai_versions, :chef_versions,
:gems ]
end
@@ -114,30 +113,10 @@ describe Chef::Cookbook::Metadata do
expect(metadata.dependencies).to eq(Mash.new)
end
- it "has an empty recommends list" do
- expect(metadata.recommendations).to eq(Mash.new)
- end
-
- it "has an empty suggestions list" do
- expect(metadata.suggestions).to eq(Mash.new)
- end
-
- it "has an empty conflicts list" do
- expect(metadata.conflicting).to eq(Mash.new)
- end
-
- it "has an empty replaces list" do
- expect(metadata.replacing).to eq(Mash.new)
- end
-
it "has an empty attributes list" do
expect(metadata.attributes).to eq(Mash.new)
end
- it "has an empty groupings list" do
- expect(metadata.groupings).to eq(Mash.new)
- end
-
it "has an empty recipes list" do
expect(metadata.recipes).to eq(Mash.new)
end
@@ -234,11 +213,7 @@ describe Chef::Cookbook::Metadata do
dep_types = {
:depends => [ :dependencies, "foo::bar", "> 0.2" ],
- :recommends => [ :recommendations, "foo::bar", ">= 0.2" ],
- :suggests => [ :suggestions, "foo::bar", "> 0.2" ],
- :conflicts => [ :conflicting, "foo::bar", "~> 0.2" ],
:provides => [ :providing, "foo::bar", "<= 0.2" ],
- :replaces => [ :replacing, "foo::bar", "= 0.2.1" ],
}
dep_types.sort_by(&:to_s).each do |dep, dep_args|
check_with = dep_args.shift
@@ -255,11 +230,7 @@ describe Chef::Cookbook::Metadata do
dep_types = {
:depends => [ :dependencies, "foo::bar", ">0.2", "> 0.2" ],
- :recommends => [ :recommendations, "foo::bar", ">=0.2", ">= 0.2" ],
- :suggests => [ :suggestions, "foo::bar", ">0.2", "> 0.2" ],
- :conflicts => [ :conflicting, "foo::bar", "~>0.2", "~> 0.2" ],
:provides => [ :providing, "foo::bar", "<=0.2", "<= 0.2" ],
- :replaces => [ :replacing, "foo::bar", "=0.2.1", "= 0.2.1" ],
}
dep_types.sort_by(&:to_s).each do |dep, dep_args|
check_with = dep_args.shift
@@ -278,11 +249,7 @@ describe Chef::Cookbook::Metadata do
describe "in the obsoleted format" do
dep_types = {
:depends => [ "foo::bar", "> 0.2", "< 1.0" ],
- :recommends => [ "foo::bar", ">= 0.2", "< 1.0" ],
- :suggests => [ "foo::bar", "> 0.2", "< 1.0" ],
- :conflicts => [ "foo::bar", "> 0.2", "< 1.0" ],
:provides => [ "foo::bar", "> 0.2", "< 1.0" ],
- :replaces => [ "foo::bar", "> 0.2.1", "< 1.0" ],
}
dep_types.each do |dep, dep_args|
@@ -295,11 +262,7 @@ describe Chef::Cookbook::Metadata do
describe "with obsolete operators" do
dep_types = {
:depends => [ "foo::bar", ">> 0.2"],
- :recommends => [ "foo::bar", ">> 0.2"],
- :suggests => [ "foo::bar", ">> 0.2"],
- :conflicts => [ "foo::bar", ">> 0.2"],
:provides => [ "foo::bar", ">> 0.2"],
- :replaces => [ "foo::bar", ">> 0.2.1"],
}
dep_types.each do |dep, dep_args|
@@ -452,33 +415,6 @@ describe Chef::Cookbook::Metadata do
end
end
- describe "attribute groupings" do
- it "should allow you set a grouping" do
- group = {
- "title" => "MySQL Tuning",
- "description" => "Setting from the my.cnf file that allow you to tune your mysql server",
- }
- expect(metadata.grouping("/db/mysql/databases/tuning", group)).to eq(group)
- end
- it "should not accept anything but a string for display_name" do
- expect do
- metadata.grouping("db/mysql/databases", :title => "foo")
- end.not_to raise_error
- expect do
- metadata.grouping("db/mysql/databases", :title => Hash.new)
- end.to raise_error(ArgumentError)
- end
-
- it "should not accept anything but a string for the description" do
- expect do
- metadata.grouping("db/mysql/databases", :description => "foo")
- end.not_to raise_error
- expect do
- metadata.grouping("db/mysql/databases", :description => Hash.new)
- end.to raise_error(ArgumentError)
- end
- end
-
describe "cookbook attributes" do
it "should allow you set an attributes metadata" do
attrs = {
@@ -765,7 +701,10 @@ describe Chef::Cookbook::Metadata do
describe "recipes" do
let(:cookbook) do
c = Chef::CookbookVersion.new("test_cookbook")
- c.recipe_files = [ "default.rb", "enlighten.rb" ]
+ c.manifest = { all_files: [
+ { name: "recipes/default.rb", path: "recipes/default.rb", checksum: "my_only_friend" },
+ { name: "recipes/enlighten.rb", path: "recipes/enlighten.rb", checksum: "my_only_friend" },
+ ] }
c
end
@@ -801,11 +740,7 @@ describe Chef::Cookbook::Metadata do
metadata.depends "bobo", "= 1.0"
metadata.depends "bubu", "=1.0"
metadata.depends "bobotclown", "= 1.1"
- metadata.recommends "snark", "< 3.0"
- metadata.suggests "kindness", "> 2.0"
- metadata.conflicts "hatred"
metadata.provides "foo(:bar, :baz)"
- metadata.replaces "snarkitron"
metadata.recipe "test_cookbook::enlighten", "is your buddy"
metadata.attribute "bizspark/has_login",
:display_name => "You have nothing"
@@ -840,11 +775,7 @@ describe Chef::Cookbook::Metadata do
license
platforms
dependencies
- suggestions
- recommendations
- conflicting
providing
- replacing
attributes
recipes
version
@@ -885,11 +816,7 @@ describe Chef::Cookbook::Metadata do
license
platforms
dependencies
- suggestions
- recommendations
- conflicting
providing
- replacing
attributes
recipes
version
@@ -911,40 +838,34 @@ describe Chef::Cookbook::Metadata do
@hash = metadata.to_hash
end
- [:dependencies,
- :recommendations,
- :suggestions,
- :conflicting,
- :replacing].each do |to_check|
- it "should transform deprecated greater than syntax for :#{to_check}" do
- @hash[to_check.to_s]["foo::bar"] = ">> 0.2"
- deserial = Chef::Cookbook::Metadata.from_hash(@hash)
- expect(deserial.send(to_check)["foo::bar"]).to eq("> 0.2")
- end
+ it "should transform deprecated greater than syntax for :dependencies" do
+ @hash[:dependencies.to_s]["foo::bar"] = ">> 0.2"
+ deserial = Chef::Cookbook::Metadata.from_hash(@hash)
+ expect(deserial.send(:dependencies)["foo::bar"]).to eq("> 0.2")
+ end
- it "should transform deprecated less than syntax for :#{to_check}" do
- @hash[to_check.to_s]["foo::bar"] = "<< 0.2"
- deserial = Chef::Cookbook::Metadata.from_hash(@hash)
- expect(deserial.send(to_check)["foo::bar"]).to eq("< 0.2")
- end
+ it "should transform deprecated less than syntax for :dependencies" do
+ @hash[:dependencies.to_s]["foo::bar"] = "<< 0.2"
+ deserial = Chef::Cookbook::Metadata.from_hash(@hash)
+ expect(deserial.send(:dependencies)["foo::bar"]).to eq("< 0.2")
+ end
- it "should ignore multiple dependency constraints for :#{to_check}" do
- @hash[to_check.to_s]["foo::bar"] = [ ">= 1.0", "<= 5.2" ]
- deserial = Chef::Cookbook::Metadata.from_hash(@hash)
- expect(deserial.send(to_check)["foo::bar"]).to eq([])
- end
+ it "should ignore multiple dependency constraints for :dependencies" do
+ @hash[:dependencies.to_s]["foo::bar"] = [ ">= 1.0", "<= 5.2" ]
+ deserial = Chef::Cookbook::Metadata.from_hash(@hash)
+ expect(deserial.send(:dependencies)["foo::bar"]).to eq([])
+ end
- it "should accept an empty array of dependency constraints for :#{to_check}" do
- @hash[to_check.to_s]["foo::bar"] = []
- deserial = Chef::Cookbook::Metadata.from_hash(@hash)
- expect(deserial.send(to_check)["foo::bar"]).to eq([])
- end
+ it "should accept an empty array of dependency constraints for :dependencies" do
+ @hash[:dependencies.to_s]["foo::bar"] = []
+ deserial = Chef::Cookbook::Metadata.from_hash(@hash)
+ expect(deserial.send(:dependencies)["foo::bar"]).to eq([])
+ end
- it "should accept single-element arrays of dependency constraints for :#{to_check}" do
- @hash[to_check.to_s]["foo::bar"] = [ ">= 2.0" ]
- deserial = Chef::Cookbook::Metadata.from_hash(@hash)
- expect(deserial.send(to_check)["foo::bar"]).to eq(">= 2.0")
- end
+ it "should accept single-element arrays of dependency constraints for :dependencies" do
+ @hash[:dependencies.to_s]["foo::bar"] = [ ">= 2.0" ]
+ deserial = Chef::Cookbook::Metadata.from_hash(@hash)
+ expect(deserial.send(:dependencies)["foo::bar"]).to eq(">= 2.0")
end
end
diff --git a/spec/unit/cookbook/synchronizer_spec.rb b/spec/unit/cookbook/synchronizer_spec.rb
index 82876273e7..77e64482da 100644
--- a/spec/unit/cookbook/synchronizer_spec.rb
+++ b/spec/unit/cookbook/synchronizer_spec.rb
@@ -62,6 +62,7 @@ describe Chef::CookbookSynchronizer do
let(:cookbook_a_default_recipe) do
{
"path" => "recipes/default.rb",
+ "name" => "recipes/default.rb",
"url" => "http://chef.example.com/abc123",
"checksum" => "abc123",
}
@@ -70,6 +71,7 @@ describe Chef::CookbookSynchronizer do
let(:cookbook_a_default_attrs) do
{
"path" => "attributes/default.rb",
+ "name" => "attributes/default.rb",
"url" => "http://chef.example.com/abc456",
"checksum" => "abc456",
}
@@ -78,6 +80,7 @@ describe Chef::CookbookSynchronizer do
let(:cookbook_a_template) do
{
"path" => "templates/default/apache2.conf.erb",
+ "name" => "templates/apache2.conf.erb",
"url" => "http://chef.example.com/ffffff",
"checksum" => "abc125",
}
@@ -86,18 +89,14 @@ describe Chef::CookbookSynchronizer do
let(:cookbook_a_file) do
{
"path" => "files/default/megaman.conf",
+ "name" => "files/megaman.conf",
"url" => "http://chef.example.com/megaman.conf",
"checksum" => "abc124",
}
end
let(:cookbook_a_manifest) do
- segments = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ]
- cookbook_a_manifest = segments.inject({}) { |h, segment| h[segment.to_s] = []; h }
- cookbook_a_manifest["recipes"] = [ cookbook_a_default_recipe ]
- cookbook_a_manifest["attributes"] = [ cookbook_a_default_attrs ]
- cookbook_a_manifest["templates"] = [ cookbook_a_template ]
- cookbook_a_manifest["files"] = [ cookbook_a_file ]
+ cookbook_a_manifest = { all_files: [ cookbook_a_default_recipe, cookbook_a_default_attrs, cookbook_a_template, cookbook_a_file ] }
cookbook_a_manifest
end
diff --git a/spec/unit/cookbook/syntax_check_spec.rb b/spec/unit/cookbook/syntax_check_spec.rb
index aa6fe49eb9..a24fa3ab2a 100644
--- a/spec/unit/cookbook/syntax_check_spec.rb
+++ b/spec/unit/cookbook/syntax_check_spec.rb
@@ -60,6 +60,7 @@ describe Chef::Cookbook::SyntaxCheck do
openldap_stuff.conf.erb
nested_openldap_partials.erb
nested_partial.erb
+ openldap_nested_variable_stuff.erb
openldap_variable_stuff.conf.erb
test.erb
some_windows_line_endings.erb
diff --git a/spec/unit/cookbook_loader_spec.rb b/spec/unit/cookbook_loader_spec.rb
index eef5d2afd5..a5fb622da0 100644
--- a/spec/unit/cookbook_loader_spec.rb
+++ b/spec/unit/cookbook_loader_spec.rb
@@ -31,6 +31,10 @@ describe Chef::CookbookLoader do
let(:cookbook_loader) { Chef::CookbookLoader.new(repo_paths) }
+ def full_paths_for_part(cb, part)
+ cookbook_loader[cb].files_for(part).inject([]) { |memo, f| memo << f[:full_path]; memo }
+ end
+
it "checks each directory only once when loading (CHEF-3487)" do
cookbook_paths = []
repo_paths.each do |repo_path|
@@ -95,13 +99,7 @@ describe Chef::CookbookLoader do
cookbook_loader.each do |cookbook_name, cookbook|
seen << cookbook_name
end
- expect(seen[0]).to eq("angrybash")
- expect(seen[1]).to eq("apache2")
- expect(seen[2]).to eq("borken")
- expect(seen[3]).to eq("ignorken")
- expect(seen[4]).to eq("java")
- expect(seen[5]).to eq("name-mismatch")
- expect(seen[6]).to eq("openldap")
+ expect(seen).to eq %w{angrybash apache2 borken ignorken java name-mismatch openldap preseed supports-platform-constraints}
end
end
@@ -112,61 +110,61 @@ describe Chef::CookbookLoader do
end
it "should allow you to override an attribute file via cookbook_path" do
- expect(cookbook_loader[:openldap].attribute_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "attributes").detect do |f|
f =~ /cookbooks\/openldap\/attributes\/default.rb/
end).not_to eql(nil)
- expect(cookbook_loader[:openldap].attribute_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "attributes").detect do |f|
f =~ /kitchen\/openldap\/attributes\/default.rb/
end).to eql(nil)
end
it "should load different attribute files from deeper paths" do
- expect(cookbook_loader[:openldap].attribute_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "attributes").detect do |f|
f =~ /kitchen\/openldap\/attributes\/robinson.rb/
end).not_to eql(nil)
end
it "should allow you to override a definition file via cookbook_path" do
- expect(cookbook_loader[:openldap].definition_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "definitions").detect do |f|
f =~ /cookbooks\/openldap\/definitions\/client.rb/
end).not_to eql(nil)
- expect(cookbook_loader[:openldap].definition_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "definitions").detect do |f|
f =~ /kitchen\/openldap\/definitions\/client.rb/
end).to eql(nil)
end
it "should load definition files from deeper paths" do
- expect(cookbook_loader[:openldap].definition_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "definitions").detect do |f|
f =~ /kitchen\/openldap\/definitions\/drewbarrymore.rb/
end).not_to eql(nil)
end
it "should allow you to override a recipe file via cookbook_path" do
- expect(cookbook_loader[:openldap].recipe_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "recipes").detect do |f|
f =~ /cookbooks\/openldap\/recipes\/gigantor.rb/
end).not_to eql(nil)
- expect(cookbook_loader[:openldap].recipe_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "recipes").detect do |f|
f =~ /kitchen\/openldap\/recipes\/gigantor.rb/
end).to eql(nil)
end
it "should load recipe files from deeper paths" do
- expect(cookbook_loader[:openldap].recipe_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "recipes").detect do |f|
f =~ /kitchen\/openldap\/recipes\/woot.rb/
end).not_to eql(nil)
end
it "should allow you to have an 'ignore' file, which skips loading files in later cookbooks" do
- expect(cookbook_loader[:openldap].recipe_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "recipes").detect do |f|
f =~ /kitchen\/openldap\/recipes\/ignoreme.rb/
end).to eql(nil)
end
it "should find files that start with a ." do
- expect(cookbook_loader[:openldap].file_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "files").detect do |f|
f =~ /\.dotfile$/
end).to match(/\.dotfile$/)
- expect(cookbook_loader[:openldap].file_filenames.detect do |f|
+ expect(full_paths_for_part(:openldap, "files").detect do |f|
f =~ /\.ssh\/id_rsa$/
end).to match(/\.ssh\/id_rsa$/)
end
diff --git a/spec/unit/cookbook_manifest_spec.rb b/spec/unit/cookbook_manifest_spec.rb
index acf0ade9f9..d77c07e0f7 100644
--- a/spec/unit/cookbook_manifest_spec.rb
+++ b/spec/unit/cookbook_manifest_spec.rb
@@ -81,11 +81,6 @@ describe Chef::CookbookManifest do
expect(cookbook_manifest.frozen_version?).to be(false)
end
- it "delegates `segment_filenames' to cookbook_version" do
- expect(cookbook_version).to receive(:segment_filenames).with(:recipes).and_return([])
- expect(cookbook_manifest.segment_filenames(:recipes)).to eq([])
- end
-
end
context "when given an empty cookbook" do
@@ -101,15 +96,7 @@ describe Chef::CookbookManifest do
"frozen?" => false,
- "recipes" => [],
- "definitions" => [],
- "libraries" => [],
- "attributes" => [],
- "files" => [],
- "templates" => [],
- "resources" => [],
- "providers" => [],
- "root_files" => [],
+ "all_files" => [],
}
end
@@ -123,16 +110,7 @@ describe Chef::CookbookManifest do
let(:cookbook_root) { File.join(CHEF_SPEC_DATA, "cb_version_cookbooks", "tatft") }
- let(:attribute_filenames) { Dir[File.join(cookbook_root, "attributes", "**", "*.rb")] }
- let(:definition_filenames) { Dir[File.join(cookbook_root, "definitions", "**", "*.rb")] }
- let(:file_filenames) { Dir[File.join(cookbook_root, "files", "**", "*.tgz")] }
- let(:recipe_filenames) { Dir[File.join(cookbook_root, "recipes", "**", "*.rb")] }
- let(:template_filenames) { Dir[File.join(cookbook_root, "templates", "**", "*.erb")] }
- let(:library_filenames) { Dir[File.join(cookbook_root, "libraries", "**", "*.rb")] }
- let(:resource_filenames) { Dir[File.join(cookbook_root, "resources", "**", "*.rb")] }
- let(:provider_filenames) { Dir[File.join(cookbook_root, "providers", "**", "*.rb")] }
- let(:root_filenames) { Array(File.join(cookbook_root, "README.rdoc")) }
- let(:metadata_filenames) { Array(File.join(cookbook_root, "metadata.json")) }
+ let(:all_files) { Dir[File.join(cookbook_root, "**", "**")].reject { |f| File.directory? f } }
let(:match_md5) { /[0-9a-f]{32}/ }
@@ -141,8 +119,15 @@ describe Chef::CookbookManifest do
relative_path = Pathname.new(path).relative_path_from(Pathname.new(cookbook_root)).to_s
+ parts = relative_path.split("/")
+ name = if %w{templates files}.include?(parts[0]) && parts.length == 3
+ File.join(parts[0], parts[2])
+ else
+ relative_path
+ end
+
{
- "name" => File.basename(path),
+ "name" => name,
"path" => relative_path,
"checksum" => Chef::Digester.generate_md5_checksum_for_file(path),
"specificity" => "default",
@@ -161,29 +146,12 @@ describe Chef::CookbookManifest do
"frozen?" => false,
- "recipes" => map_to_file_specs(recipe_filenames),
- "definitions" => map_to_file_specs(definition_filenames),
- "libraries" => map_to_file_specs(library_filenames),
- "attributes" => map_to_file_specs(attribute_filenames),
- "files" => map_to_file_specs(file_filenames),
- "templates" => map_to_file_specs(template_filenames),
- "resources" => map_to_file_specs(resource_filenames),
- "providers" => map_to_file_specs(provider_filenames),
- "root_files" => map_to_file_specs(root_filenames),
+ "all_files" => map_to_file_specs(all_files),
}
end
before do
- cookbook_version.attribute_filenames = attribute_filenames
- cookbook_version.definition_filenames = definition_filenames
- cookbook_version.file_filenames = file_filenames
- cookbook_version.recipe_filenames = recipe_filenames
- cookbook_version.template_filenames = template_filenames
- cookbook_version.library_filenames = library_filenames
- cookbook_version.resource_filenames = resource_filenames
- cookbook_version.provider_filenames = provider_filenames
- cookbook_version.root_filenames = root_filenames
- cookbook_version.metadata_filenames = metadata_filenames
+ cookbook_version.all_files = all_files
end
it "converts the CookbookVersion to a ruby Hash representation" do
diff --git a/spec/unit/cookbook_site_streaming_uploader_spec.rb b/spec/unit/cookbook_site_streaming_uploader_spec.rb
index 10963386dd..0e9c277b11 100644
--- a/spec/unit/cookbook_site_streaming_uploader_spec.rb
+++ b/spec/unit/cookbook_site_streaming_uploader_spec.rb
@@ -49,10 +49,6 @@ describe Chef::CookbookSiteStreamingUploader do
cookbook = @loader[:openldap]
files_count = Dir.glob(File.join(@cookbook_repo, cookbook.name.to_s, "**", "*"), File::FNM_DOTMATCH).count { |file| File.file?(file) }
- # The fixture cookbook contains a spec/spec_helper.rb file, which is not
- # a part of any cookbook segment, so it is not uploaded.
- files_count -= 1
-
expect(Tempfile).to receive(:new).with("chef-#{cookbook.name}-build").and_return(FakeTempfile.new("chef-#{cookbook.name}-build"))
expect(FileUtils).to receive(:mkdir_p).exactly(files_count + 1).times
expect(FileUtils).to receive(:cp).exactly(files_count).times
diff --git a/spec/unit/cookbook_spec.rb b/spec/unit/cookbook_spec.rb
index 33b4a3ccd8..ac3a1373ea 100644
--- a/spec/unit/cookbook_spec.rb
+++ b/spec/unit/cookbook_spec.rb
@@ -19,7 +19,8 @@
require "spec_helper"
describe Chef::CookbookVersion do
-# COOKBOOK_PATH = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks", "openldap"))
+ COOKBOOK_PATH = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks", "openldap"))
+
before(:each) do
@cookbook_repo = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks"))
cl = Chef::CookbookLoader.new(@cookbook_repo)
@@ -37,26 +38,21 @@ describe Chef::CookbookVersion do
end
it "should allow you to set the list of attribute files and create the mapping from short names to paths" do
- @cookbook.attribute_filenames = [ "attributes/one.rb", "attributes/two.rb" ]
- expect(@cookbook.attribute_filenames).to eq([ "attributes/one.rb", "attributes/two.rb" ])
- expect(@cookbook.attribute_filenames_by_short_filename.keys.sort).to eql(%w{one two})
- expect(@cookbook.attribute_filenames_by_short_filename["one"]).to eq("attributes/one.rb")
- expect(@cookbook.attribute_filenames_by_short_filename["two"]).to eq("attributes/two.rb")
+ expect(@cookbook.attribute_filenames_by_short_filename.keys.sort).to eql(%w{default smokey})
+ expect(@cookbook.attribute_filenames_by_short_filename["default"]).to eq(File.join(COOKBOOK_PATH, "attributes/default.rb"))
+ expect(@cookbook.attribute_filenames_by_short_filename["smokey"]).to eq(File.join(COOKBOOK_PATH, "attributes/smokey.rb"))
end
it "should allow you to set the list of recipe files and create the mapping of recipe short name to filename" do
- @cookbook.recipe_filenames = [ "recipes/one.rb", "recipes/two.rb" ]
- expect(@cookbook.recipe_filenames).to eq([ "recipes/one.rb", "recipes/two.rb" ])
- expect(@cookbook.recipe_filenames_by_name.keys.sort).to eql(%w{one two})
- expect(@cookbook.recipe_filenames_by_name["one"]).to eq("recipes/one.rb")
- expect(@cookbook.recipe_filenames_by_name["two"]).to eq("recipes/two.rb")
+ expect(@cookbook.recipe_filenames_by_name.keys.sort).to eql(%w{default gigantor one return})
+ expect(@cookbook.recipe_filenames_by_name["one"]).to eq(File.join(COOKBOOK_PATH, "recipes/one.rb"))
+ expect(@cookbook.recipe_filenames_by_name["gigantor"]).to eq(File.join(COOKBOOK_PATH, "recipes/gigantor.rb"))
end
it "should generate a list of recipes by fully-qualified name" do
- @cookbook.recipe_filenames = [ "recipes/one.rb", "/recipes/two.rb", "three.rb" ]
expect(@cookbook.fully_qualified_recipe_names.include?("openldap::one")).to eq(true)
- expect(@cookbook.fully_qualified_recipe_names.include?("openldap::two")).to eq(true)
- expect(@cookbook.fully_qualified_recipe_names.include?("openldap::three")).to eq(true)
+ expect(@cookbook.fully_qualified_recipe_names.include?("openldap::gigantor")).to eq(true)
+ expect(@cookbook.fully_qualified_recipe_names.include?("openldap::return")).to eq(true)
end
it "should raise an ArgumentException if you try to load a bad recipe name" do
diff --git a/spec/unit/cookbook_uploader_spec.rb b/spec/unit/cookbook_uploader_spec.rb
index c30df71e34..2c36c2c9c7 100644
--- a/spec/unit/cookbook_uploader_spec.rb
+++ b/spec/unit/cookbook_uploader_spec.rb
@@ -65,7 +65,7 @@ describe Chef::CookbookUploader do
it "creates an HTTP client with default configuration when not initialized with one" do
default_http_client = double("Chef::ServerAPI")
- expect(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_url]).and_return(default_http_client)
+ expect(Chef::ServerAPI).to receive(:new).with(Chef::Config[:chef_server_url], version_class: Chef::CookbookManifestVersions).and_return(default_http_client)
uploader = described_class.new(cookbooks_to_upload)
expect(uploader.rest).to eq(default_http_client)
end
diff --git a/spec/unit/cookbook_version_file_specificity_spec.rb b/spec/unit/cookbook_version_file_specificity_spec.rb
index 3b5450cb2d..ba7aaa59f5 100644
--- a/spec/unit/cookbook_version_file_specificity_spec.rb
+++ b/spec/unit/cookbook_version_file_specificity_spec.rb
@@ -23,177 +23,204 @@ describe Chef::CookbookVersion, "file specificity" do
before(:each) do
@cookbook = Chef::CookbookVersion.new("test-cookbook", "/cookbook-folder")
@cookbook.manifest = {
- "files" =>
+ "all_files" =>
[
# afile.rb
{
- :name => "afile.rb",
+ :name => "files/afile.rb",
:path => "files/host-examplehost.example.org/afile.rb",
+ :full_path => "/cookbook-folder/files/host-examplehost.example.org/afile.rb",
:checksum => "csum-host",
:specificity => "host-examplehost.example.org",
},
{
- :name => "afile.rb",
+ :name => "files/afile.rb",
:path => "files/ubuntu-9.10/afile.rb",
+ :full_path => "/cookbook-folder/files/ubuntu-9.10/afile.rb",
:checksum => "csum-platver-full",
:specificity => "ubuntu-9.10",
},
{
- :name => "afile.rb",
+ :name => "files/afile.rb",
:path => "files/newubuntu-9/afile.rb",
+ :full_path => "/cookbook-folder/files/newubuntu-9/afile.rb",
:checksum => "csum-platver-partial",
:specificity => "newubuntu-9",
},
{
- :name => "afile.rb",
+ :name => "files/afile.rb",
:path => "files/ubuntu/afile.rb",
+ :full_path => "/cookbook-folder/files/ubuntu/afile.rb",
:checksum => "csum-plat",
:specificity => "ubuntu",
},
{
- :name => "afile.rb",
+ :name => "files/afile.rb",
:path => "files/default/afile.rb",
+ :full_path => "/cookbook-folder/files/default/afile.rb",
:checksum => "csum-default",
:specificity => "default",
},
# for different/odd platform_versions
{
- :name => "bfile.rb",
+ :name => "files/bfile.rb",
:path => "files/fakeos-2.0.rc.1/bfile.rb",
+ :full_path => "/cookbook-folder/files/fakeos-2.0.rc.1/bfile.rb",
:checksum => "csum2-platver-full",
:specificity => "fakeos-2.0.rc.1",
},
{
- :name => "bfile.rb",
+ :name => "files/bfile.rb",
:path => "files/newfakeos-2.0.rc/bfile.rb",
+ :full_path => "/cookbook-folder/files/newfakeos-2.0.rc/bfile.rb",
:checksum => "csum2-platver-partial",
:specificity => "newfakeos-2.0.rc",
},
{
- :name => "bfile.rb",
+ :name => "files/bfile.rb",
:path => "files/fakeos-maple tree/bfile.rb",
+ :full_path => "/cookbook-folder/files/fakeos-maple tree/bfile.rb",
:checksum => "csum3-platver-full",
:specificity => "maple tree",
},
{
- :name => "bfile.rb",
+ :name => "files/bfile.rb",
:path => "files/fakeos-1/bfile.rb",
+ :full_path => "/cookbook-folder/files/fakeos-1/bfile.rb",
:checksum => "csum4-platver-full",
:specificity => "fakeos-1",
},
# directory adirectory
{
- :name => "anotherfile1.rb",
+ :name => "files/anotherfile1.rb",
:path => "files/host-examplehost.example.org/adirectory/anotherfile1.rb.host",
+ :full_path => "/cookbook-folder/files/host-examplehost.example.org/adirectory/anotherfile1.rb.host",
:checksum => "csum-host-1",
:specificity => "host-examplehost.example.org",
},
{
- :name => "anotherfile2.rb",
+ :name => "files/anotherfile2.rb",
:path => "files/host-examplehost.example.org/adirectory/anotherfile2.rb.host",
+ :full_path => "/cookbook-folder/files/host-examplehost.example.org/adirectory/anotherfile2.rb.host",
:checksum => "csum-host-2",
:specificity => "host-examplehost.example.org",
},
{
- :name => "anotherfile1.rb",
+ :name => "files/anotherfile1.rb",
:path => "files/ubuntu-9.10/adirectory/anotherfile1.rb.platform-full-version",
+ :full_path => "/cookbook-folder/files/ubuntu-9.10/adirectory/anotherfile1.rb.platform-full-version",
:checksum => "csum-platver-full-1",
:specificity => "ubuntu-9.10",
},
{
- :name => "anotherfile2.rb",
+ :name => "files/anotherfile2.rb",
:path => "files/ubuntu-9.10/adirectory/anotherfile2.rb.platform-full-version",
+ :full_path => "/cookbook-folder/files/ubuntu-9.10/adirectory/anotherfile2.rb.platform-full-version",
:checksum => "csum-platver-full-2",
:specificity => "ubuntu-9.10",
},
{
- :name => "anotherfile1.rb",
+ :name => "files/anotherfile1.rb",
:path => "files/newubuntu-9/adirectory/anotherfile1.rb.platform-partial-version",
+ :full_path => "/cookbook-folder/files/newubuntu-9/adirectory/anotherfile1.rb.platform-partial-version",
:checksum => "csum-platver-partial-1",
:specificity => "newubuntu-9",
},
{
- :name => "anotherfile2.rb",
+ :name => "files/anotherfile2.rb",
:path => "files/newubuntu-9/adirectory/anotherfile2.rb.platform-partial-version",
+ :full_path => "/cookbook-folder/files/newubuntu-9/adirectory/anotherfile2.rb.platform-partial-version",
:checksum => "csum-platver-partial-2",
:specificity => "nweubuntu-9",
},
{
- :name => "anotherfile1.rb",
+ :name => "files/anotherfile1.rb",
:path => "files/ubuntu/adirectory/anotherfile1.rb.platform",
+ :full_path => "/cookbook-folder/files/ubuntu/adirectory/anotherfile1.rb.platform",
:checksum => "csum-plat-1",
:specificity => "ubuntu",
},
{
- :name => "anotherfile2.rb",
+ :name => "files/anotherfile2.rb",
:path => "files/ubuntu/adirectory/anotherfile2.rb.platform",
+ :full_path => "/cookbook-folder/files/ubuntu/adirectory/anotherfile2.rb.platform",
:checksum => "csum-plat-2",
:specificity => "ubuntu",
},
{
- :name => "anotherfile1.rb",
+ :name => "files/anotherfile1.rb",
:path => "files/default/adirectory/anotherfile1.rb.default",
+ :full_path => "/cookbook-folder/files/default/adirectory/anotherfile1.rb.default",
:checksum => "csum-default-1",
:specificity => "default",
},
{
- :name => "anotherfile2.rb",
+ :name => "files/anotherfile2.rb",
:path => "files/default/adirectory/anotherfile2.rb.default",
+ :full_path => "/cookbook-folder/files/default/adirectory/anotherfile2.rb.default",
:checksum => "csum-default-2",
:specificity => "default",
},
# for different/odd platform_versions
{
- :name => "anotherfile1.rb",
+ :name => "files/anotherfile1.rb",
:path => "files/fakeos-2.0.rc.1/adirectory/anotherfile1.rb.platform-full-version",
+ :full_path => "/cookbook-folder/files/fakeos-2.0.rc.1/adirectory/anotherfile1.rb.platform-full-version",
:checksum => "csum2-platver-full-1",
:specificity => "fakeos-2.0.rc.1",
},
{
- :name => "anotherfile2.rb",
+ :name => "files/anotherfile2.rb",
:path => "files/fakeos-2.0.rc.1/adirectory/anotherfile2.rb.platform-full-version",
+ :full_path => "/cookbook-folder/files/fakeos-2.0.rc.1/adirectory/anotherfile2.rb.platform-full-version",
:checksum => "csum2-platver-full-2",
:specificity => "fakeos-2.0.rc.1",
},
{
- :name => "anotherfile1.rb",
+ :name => "files/anotherfile1.rb",
:path => "files/newfakeos-2.0.rc.1/adirectory/anotherfile1.rb.platform-partial-version",
+ :full_path => "/cookbook-folder/files/newfakeos-2.0.rc.1/adirectory/anotherfile1.rb.platform-partial-version",
:checksum => "csum2-platver-partial-1",
:specificity => "newfakeos-2.0.rc",
},
{
- :name => "anotherfile2.rb",
+ :name => "files/anotherfile2.rb",
:path => "files/newfakeos-2.0.rc.1/adirectory/anotherfile2.rb.platform-partial-version",
+ :full_path => "/cookbook-folder/files/newfakeos-2.0.rc.1/adirectory/anotherfile2.rb.platform-partial-version",
:checksum => "csum2-platver-partial-2",
:specificity => "newfakeos-2.0.rc",
},
{
- :name => "anotherfile1.rb",
+ :name => "files/anotherfile1.rb",
:path => "files/fakeos-maple tree/adirectory/anotherfile1.rb.platform-full-version",
+ :full_path => "/cookbook-folder/files/fakeos-maple tree/adirectory/anotherfile1.rb.platform-full-version",
:checksum => "csum3-platver-full-1",
:specificity => "fakeos-maple tree",
},
{
- :name => "anotherfile2.rb",
+ :name => "files/anotherfile2.rb",
:path => "files/fakeos-maple tree/adirectory/anotherfile2.rb.platform-full-version",
+ :full_path => "/cookbook-folder/files/fakeos-maple tree/adirectory/anotherfile2.rb.platform-full-version",
:checksum => "csum3-platver-full-2",
:specificity => "fakeos-maple tree",
},
{
- :name => "anotherfile1.rb",
+ :name => "files/anotherfile1.rb",
:path => "files/fakeos-1/adirectory/anotherfile1.rb.platform-full-version",
+ :full_path => "/cookbook-folder/files/fakeos-1/adirectory/anotherfile1.rb.platform-full-version",
:checksum => "csum4-platver-full-1",
:specificity => "fakeos-1",
},
{
- :name => "anotherfile2.rb",
+ :name => "files/anotherfile2.rb",
:path => "files/fakeos-1/adirectory/anotherfile2.rb.platform-full-version",
+ :full_path => "/cookbook-folder/files/fakeos-1/adirectory/anotherfile2.rb.platform-full-version",
:checksum => "csum4-platver-full-2",
:specificity => "fakeos-1",
},
diff --git a/spec/unit/cookbook_version_spec.rb b/spec/unit/cookbook_version_spec.rb
index 81ea161bfe..83fb3f578f 100644
--- a/spec/unit/cookbook_version_spec.rb
+++ b/spec/unit/cookbook_version_spec.rb
@@ -25,38 +25,6 @@ describe Chef::CookbookVersion do
expect(cookbook_version.name).to eq("tatft")
end
- it "has no attribute files" do
- expect(cookbook_version.attribute_filenames).to be_empty
- end
-
- it "has no resource definition files" do
- expect(cookbook_version.definition_filenames).to be_empty
- end
-
- it "has no cookbook files" do
- expect(cookbook_version.file_filenames).to be_empty
- end
-
- it "has no recipe files" do
- expect(cookbook_version.recipe_filenames).to be_empty
- end
-
- it "has no library files" do
- expect(cookbook_version.library_filenames).to be_empty
- end
-
- it "has no LWRP resource files" do
- expect(cookbook_version.resource_filenames).to be_empty
- end
-
- it "has no LWRP provider files" do
- expect(cookbook_version.provider_filenames).to be_empty
- end
-
- it "has no metadata files" do
- expect(cookbook_version.metadata_filenames).to be_empty
- end
-
it "has an empty set of all_files" do
expect(cookbook_version.all_files).to be_empty
end
@@ -82,17 +50,7 @@ describe Chef::CookbookVersion do
let(:cookbook_paths_by_type) do
{
# Dunno if the paths here are representitive of what is set by CookbookLoader...
- all_files: Dir[File.join(cookbook_root, "**", "*.rb")],
- attribute_filenames: Dir[File.join(cookbook_root, "attributes", "**", "*.rb")],
- definition_filenames: Dir[File.join(cookbook_root, "definitions", "**", "*.rb")],
- file_filenames: Dir[File.join(cookbook_root, "files", "**", "*.tgz")],
- recipe_filenames: Dir[File.join(cookbook_root, "recipes", "**", "*.rb")],
- template_filenames: Dir[File.join(cookbook_root, "templates", "**", "*.erb")],
- library_filenames: Dir[File.join(cookbook_root, "libraries", "**", "*.rb")],
- resource_filenames: Dir[File.join(cookbook_root, "resources", "**", "*.rb")],
- provider_filenames: Dir[File.join(cookbook_root, "providers", "**", "*.rb")],
- root_filenames: Array(File.join(cookbook_root, "README.rdoc")),
- metadata_filenames: Array(File.join(cookbook_root, "metadata.json")),
+ all_files: Dir[File.join(cookbook_root, "**", "**")],
}
end
@@ -102,18 +60,9 @@ describe Chef::CookbookVersion do
let(:cookbook_version) do
Chef::CookbookVersion.new("tatft", cookbook_root).tap do |c|
- # Currently the cookbook loader finds all the files then tells CookbookVersion
- # where they are.
- c.attribute_filenames = cookbook_paths_by_type[:attribute_filenames]
- c.definition_filenames = cookbook_paths_by_type[:definition_filenames]
- c.recipe_filenames = cookbook_paths_by_type[:recipe_filenames]
- c.template_filenames = cookbook_paths_by_type[:template_filenames]
- c.file_filenames = cookbook_paths_by_type[:file_filenames]
- c.library_filenames = cookbook_paths_by_type[:library_filenames]
- c.resource_filenames = cookbook_paths_by_type[:resource_filenames]
- c.provider_filenames = cookbook_paths_by_type[:provider_filenames]
- c.root_filenames = cookbook_paths_by_type[:root_filenames]
- c.metadata_filenames = cookbook_paths_by_type[:metadata_filenames]
+ # Currently the cookbook loader finds all the files then tells CookbookVersion
+ # where they are.
+ c.all_files = cookbook_paths_by_type[:all_files]
end
end
@@ -168,18 +117,7 @@ describe Chef::CookbookVersion do
let(:cookbook_paths_by_type) do
{
- # Dunno if the paths here are representitive of what is set by CookbookLoader...
- all_files: Dir[File.join(cookbook_root, "**", "*.rb")],
- attribute_filenames: Dir[File.join(cookbook_root, "attributes", "**", "*.rb")],
- definition_filenames: Dir[File.join(cookbook_root, "definitions", "**", "*.rb")],
- file_filenames: Dir[File.join(cookbook_root, "files", "**", "*.*")],
- recipe_filenames: Dir[File.join(cookbook_root, "recipes", "**", "*.rb")],
- template_filenames: Dir[File.join(cookbook_root, "templates", "**", "*.*")],
- library_filenames: Dir[File.join(cookbook_root, "libraries", "**", "*.rb")],
- resource_filenames: Dir[File.join(cookbook_root, "resources", "**", "*.rb")],
- provider_filenames: Dir[File.join(cookbook_root, "providers", "**", "*.rb")],
- root_filenames: Array(File.join(cookbook_root, "README.rdoc")),
- metadata_filenames: Array(File.join(cookbook_root, "metadata.json")),
+ all_files: Dir[File.join(cookbook_root, "**", "**")],
}
end
@@ -187,16 +125,7 @@ describe Chef::CookbookVersion do
let(:cookbook_version) do
Chef::CookbookVersion.new("cookbook2", cookbook_root).tap do |c|
- c.attribute_filenames = cookbook_paths_by_type[:attribute_filenames]
- c.definition_filenames = cookbook_paths_by_type[:definition_filenames]
- c.recipe_filenames = cookbook_paths_by_type[:recipe_filenames]
- c.template_filenames = cookbook_paths_by_type[:template_filenames]
- c.file_filenames = cookbook_paths_by_type[:file_filenames]
- c.library_filenames = cookbook_paths_by_type[:library_filenames]
- c.resource_filenames = cookbook_paths_by_type[:resource_filenames]
- c.provider_filenames = cookbook_paths_by_type[:provider_filenames]
- c.root_filenames = cookbook_paths_by_type[:root_filenames]
- c.metadata_filenames = cookbook_paths_by_type[:metadata_filenames]
+ c.all_files = cookbook_paths_by_type[:all_files]
end
end
@@ -255,19 +184,19 @@ describe Chef::CookbookVersion do
it "should sort based on the version number" do
examples = [
- # smaller, larger
- ["1.0", "2.0"],
- ["1.2.3", "1.2.4"],
- ["1.2.3", "1.3.0"],
- ["1.2.3", "1.3"],
- ["1.2.3", "2.1.1"],
- ["1.2.3", "2.1"],
- ["1.2", "1.2.4"],
- ["1.2", "1.3.0"],
- ["1.2", "1.3"],
- ["1.2", "2.1.1"],
- ["1.2", "2.1"],
- ]
+ # smaller, larger
+ ["1.0", "2.0"],
+ ["1.2.3", "1.2.4"],
+ ["1.2.3", "1.3.0"],
+ ["1.2.3", "1.3"],
+ ["1.2.3", "2.1.1"],
+ ["1.2.3", "2.1"],
+ ["1.2", "1.2.4"],
+ ["1.2", "1.3.0"],
+ ["1.2", "1.3"],
+ ["1.2", "2.1.1"],
+ ["1.2", "2.1"],
+ ]
examples.each do |smaller, larger|
sm = Chef::CookbookVersion.new("foo", "/tmp/blah")
lg = Chef::CookbookVersion.new("foo", "/tmp/blah")
@@ -318,42 +247,4 @@ describe Chef::CookbookVersion do
end
- describe "when deprecation warnings are errors" do
-
- subject(:cbv) { Chef::CookbookVersion.new("version validation", "/tmp/blah") }
-
- it "errors on #status and #status=" do
- expect { cbv.status = :wat }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
- expect { cbv.status }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
- end
-
- end
-
- describe "deprecated features" do
-
- subject(:cbv) { Chef::CookbookVersion.new("tatft", "/tmp/blah").tap { |c| c.version = "1.2.3" } }
-
- before do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- end
-
- it "gives a save URL for the standard cookbook API" do
- expect(cbv.save_url).to eq("cookbooks/tatft/1.2.3")
- end
-
- it "gives a force save URL for the standard cookbook API" do
- expect(cbv.force_save_url).to eq("cookbooks/tatft/1.2.3?force=true")
- end
-
- it "is \"ready\"" do
- # WTF is this? what are the valid states? and why aren't they set with encapsulating methods?
- # [Dan 15-Jul-2010]
- expect(cbv.status).to eq(:ready)
- end
-
- include_examples "to_json equivalent to Chef::JSONCompat.to_json" do
- let(:jsonable) { Chef::CookbookVersion.new("tatft", "/tmp/blah") }
- end
-
- end
end
diff --git a/spec/unit/data_bag_item_spec.rb b/spec/unit/data_bag_item_spec.rb
index e83f0ca0ec..7094a7b1f7 100644
--- a/spec/unit/data_bag_item_spec.rb
+++ b/spec/unit/data_bag_item_spec.rb
@@ -52,6 +52,10 @@ describe Chef::DataBagItem do
expect { data_bag_item.raw_data = { "id" => "octahedron" } }.not_to raise_error
end
+ it "should let you set the raw_data with a hash containing symbols" do
+ expect { data_bag_item.raw_data = { :id => "octahedron" } }.not_to raise_error
+ end
+
it "should let you set the raw_data from a mash" do
expect { data_bag_item.raw_data = Mash.new({ "id" => "octahedron" }) }.not_to raise_error
end
diff --git a/spec/unit/data_collector/messages_spec.rb b/spec/unit/data_collector/messages_spec.rb
index 5c6ec8736c..f5df85a988 100644
--- a/spec/unit/data_collector/messages_spec.rb
+++ b/spec/unit/data_collector/messages_spec.rb
@@ -116,6 +116,141 @@ describe Chef::DataCollector::Messages do
deprecations
}
end
+ let(:optional_fields) { %w{error policy_group policy_name} }
+
+ before do
+ allow(run_status).to receive(:exception).and_return(nil)
+ end
+
+ it "is not missing any required fields" do
+ missing_fields = required_fields.select do |key|
+ !Chef::DataCollector::Messages.run_end_message(reporter_data).key?(key)
+ end
+ expect(missing_fields).to eq([])
+ end
+
+ it "does not have any extra fields" do
+ extra_fields = Chef::DataCollector::Messages.run_end_message(reporter_data).keys.select do |key|
+ !required_fields.include?(key) && !optional_fields.include?(key)
+ end
+ expect(extra_fields).to eq([])
+ end
+
+ it "only includes updated resources in its count" do
+ message = Chef::DataCollector::Messages.run_end_message(reporter_data)
+ expect(message["total_resource_count"]).to eq(2)
+ expect(message["updated_resource_count"]).to eq(1)
+ end
+ end
+
+ context "when the run was not successful" do
+ let(:required_fields) do
+ %w{
+ chef_server_fqdn
+ entity_uuid
+ id
+ end_time
+ error
+ expanded_run_list
+ message_type
+ message_version
+ node
+ node_name
+ organization_name
+ resources
+ run_id
+ run_list
+ source
+ start_time
+ status
+ total_resource_count
+ updated_resource_count
+ deprecations
+ }
+ end
+ let(:optional_fields) { %w{policy_group policy_name} }
+
+ before do
+ allow(run_status).to receive(:exception).and_return(RuntimeError.new("an error happened"))
+ end
+
+ it "is not missing any required fields" do
+ missing_fields = required_fields.select do |key|
+ !Chef::DataCollector::Messages.run_end_message(reporter_data).key?(key)
+ end
+ expect(missing_fields).to eq([])
+ end
+
+ it "does not have any extra fields" do
+ extra_fields = Chef::DataCollector::Messages.run_end_message(reporter_data).keys.select do |key|
+ !required_fields.include?(key) && !optional_fields.include?(key)
+ end
+ expect(extra_fields).to eq([])
+ end
+ end
+ end
+
+ describe "#run_end_message in policy mode" do
+ let(:node) { Chef::Node.new }
+ let(:run_status) { Chef::RunStatus.new(node, Chef::EventDispatch::Dispatcher.new) }
+ let(:report1) { double("report1", report_data: { "status" => "updated" }) }
+ let(:report2) { double("report2", report_data: { "status" => "skipped" }) }
+ let(:reporter_data) do
+ {
+ run_status: run_status,
+ resources: [report1, report2],
+ }
+ end
+
+ before do
+ allow(run_status).to receive(:start_time).and_return(Time.now)
+ allow(run_status).to receive(:end_time).and_return(Time.now)
+ node.policy_group = "test"
+ node.policy_name = "policy-test"
+ end
+
+ it "includes a valid node object in the payload" do
+ message = Chef::DataCollector::Messages.run_end_message(reporter_data)
+ expect(message["node"]).to be_an_instance_of(Chef::Node)
+ end
+
+ it "returns a sane JSON representation of the node object" do
+ node.chef_environment = "my_test_environment"
+ node.run_list.add("recipe[my_test_cookbook::default]")
+ message = FFI_Yajl::Parser.parse(Chef::DataCollector::Messages.run_end_message(reporter_data).to_json)
+
+ expect(message["node"]["chef_environment"]).to eq("my_test_environment")
+ expect(message["node"]["run_list"]).to eq(["recipe[my_test_cookbook::default]"])
+ expect(message["node"]["policy_name"]).to eq("policy-test")
+ expect(message["node"]["policy_group"]).to eq("test")
+ end
+
+ context "when the run was successful" do
+ let(:required_fields) do
+ %w{
+ chef_server_fqdn
+ entity_uuid
+ id
+ end_time
+ expanded_run_list
+ message_type
+ message_version
+ node
+ node_name
+ organization_name
+ resources
+ run_id
+ run_list
+ source
+ start_time
+ status
+ total_resource_count
+ updated_resource_count
+ deprecations
+ policy_name
+ policy_group
+ }
+ end
let(:optional_fields) { %w{error} }
before do
@@ -166,6 +301,8 @@ describe Chef::DataCollector::Messages do
total_resource_count
updated_resource_count
deprecations
+ policy_name
+ policy_group
}
end
let(:optional_fields) { [] }
diff --git a/spec/unit/formatters/error_description_spec.rb b/spec/unit/formatters/error_description_spec.rb
index 8b088308fa..cf6372ed49 100644
--- a/spec/unit/formatters/error_description_spec.rb
+++ b/spec/unit/formatters/error_description_spec.rb
@@ -49,7 +49,21 @@ describe Chef::Formatters::ErrorDescription do
describe "#display" do
before do
- stub_const("RUBY_PLATFORM", "ruby-foo-9000")
+ stub_const("Chef::VERSION", "1.2.3")
+ stub_const("RUBY_DESCRIPTION", "ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]")
+ allow(subject).to receive(:caller) { Kernel.caller + ["/test/bin/chef-client:1:in `<main>'"] }
+ allow(File).to receive(:realpath).and_call_original
+ allow(File).to receive(:realpath).with("/test/bin/chef-client").and_return("/test/bin/chef-client")
+ end
+
+ around do |ex|
+ old_program_name = $PROGRAM_NAME
+ begin
+ $PROGRAM_NAME = "chef-client"
+ ex.run
+ ensure
+ $PROGRAM_NAME = old_program_name
+ end
end
context "when no sections have been added" do
@@ -60,9 +74,12 @@ describe Chef::Formatters::ErrorDescription do
test title
================================================================================
-Platform:
----------
-ruby-foo-9000
+System Info:
+------------
+chef_version=1.2.3
+ruby=ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
+program_name=chef-client
+executable=/test/bin/chef-client
END
end
@@ -84,9 +101,37 @@ test heading
------------
test text
-Platform:
----------
-ruby-foo-9000
+System Info:
+------------
+chef_version=1.2.3
+ruby=ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
+program_name=chef-client
+executable=/test/bin/chef-client
+
+ END
+ end
+
+ end
+
+ context "when node object is available" do
+ it "should output the expected sections" do
+ # This can't be in a before block because the spec-wide helper calls a
+ # reset on global values.
+ Chef.set_node({ "platform" => "openvms", "platform_version" => "8.4-2L1" })
+ subject.display(out)
+ expect(out.out.string).to eq <<-END
+================================================================================
+test title
+================================================================================
+
+System Info:
+------------
+chef_version=1.2.3
+platform=openvms
+platform_version=8.4-2L1
+ruby=ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
+program_name=chef-client
+executable=/test/bin/chef-client
END
end
diff --git a/spec/unit/http/socketless_chef_zero_client_spec.rb b/spec/unit/http/socketless_chef_zero_client_spec.rb
index 637e562799..4f3aed13c5 100644
--- a/spec/unit/http/socketless_chef_zero_client_spec.rb
+++ b/spec/unit/http/socketless_chef_zero_client_spec.rb
@@ -132,7 +132,7 @@ describe Chef::HTTP::SocketlessChefZeroClient do
let(:method) { :GET }
let(:relative_url) { "clients" }
- let(:headers) { { "Accept" => "application/json" } }
+ let(:headers) { { "Accept" => "application/json", "X-Ops-Server-API-Version" => "2" } }
let(:body) { false }
let(:expected_rack_req) do
@@ -144,6 +144,7 @@ describe Chef::HTTP::SocketlessChefZeroClient do
"QUERY_STRING" => uri.query,
"SERVER_PORT" => uri.port,
"HTTP_HOST" => "localhost:#{uri.port}",
+ "HTTP_X_OPS_SERVER_API_VERSION" => "2",
"rack.url_scheme" => "chefzero",
"rack.input" => an_instance_of(StringIO),
}
diff --git a/spec/unit/knife/configure_client_spec.rb b/spec/unit/knife/configure_client_spec.rb
index 3ecb89f827..0f83897564 100644
--- a/spec/unit/knife/configure_client_spec.rb
+++ b/spec/unit/knife/configure_client_spec.rb
@@ -58,8 +58,6 @@ describe Chef::Knife::ConfigureClient do
it "should write out the config file" do
allow(FileUtils).to receive(:mkdir_p)
@knife.run
- expect(@client_file.string).to match /log_level\s+\:info/
- expect(@client_file.string).to match /log_location\s+STDOUT/
expect(@client_file.string).to match /chef_server_url\s+'https\:\/\/chef\.example\.com'/
expect(@client_file.string).to match /validation_client_name\s+'chef-validator'/
end
diff --git a/spec/unit/knife/cookbook_create_spec.rb b/spec/unit/knife/cookbook_create_spec.rb
index f860a8bce8..ef86a0cd2b 100644
--- a/spec/unit/knife/cookbook_create_spec.rb
+++ b/spec/unit/knife/cookbook_create_spec.rb
@@ -34,228 +34,9 @@ describe Chef::Knife::CookbookCreate do
# Fixes CHEF-2579
it "should expand the path of the cookbook directory" do
- expect(File).to receive(:expand_path).with("~/tmp/monkeypants")
- @knife.config = { :cookbook_path => "~/tmp/monkeypants" }
- allow(@knife).to receive(:create_cookbook)
- allow(@knife).to receive(:create_readme)
- allow(@knife).to receive(:create_changelog)
- allow(@knife).to receive(:create_metadata)
+ expect(Chef::Log).to receive(:fatal).with("knife cookbook create has been removed. Please use `chef generate cookbook` from the ChefDK")
@knife.run
end
- it "should create a new cookbook with default values to copyright name, email, readme format and license if those are not supplied" do
- @dir = Dir.tmpdir
- @knife.config = { :cookbook_path => @dir }
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "YOUR_COMPANY_NAME", "none")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "YOUR_COMPANY_NAME", "YOUR_EMAIL", "none", "md")
- @knife.run
- end
-
- it "should create a new cookbook with specified company name in the copyright section if one is specified" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "none")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "YOUR_EMAIL", "none", "md")
- @knife.run
- end
-
- it "should create a new cookbook with specified copyright name and email if they are specified" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "none")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "none", "md")
- @knife.run
- end
-
- it "should create a new cookbook with specified copyright name and email and license information (true) if they are specified" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => "apachev2",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "apachev2")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "apachev2", "md")
- @knife.run
- end
-
- it "should create a new cookbook with specified copyright name and email and license information (false) if they are specified" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => false,
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "none")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "none", "md")
- @knife.run
- end
-
- it "should create a new cookbook with specified copyright name and email and license information ('false' as string) if they are specified" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => "false",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "none")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "none", "md")
- @knife.run
- end
-
- it "should allow specifying a gpl2 license" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => "gplv2",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "gplv2")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "gplv2", "md")
- @knife.run
- end
-
- it "should allow specifying a gplv3 license" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => "gplv3",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "gplv3")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "gplv3", "md")
- @knife.run
- end
-
- it "should allow specifying the mit license" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => "mit",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "md")
- @knife.run
- end
-
- it "should allow specifying the rdoc readme format" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => "mit",
- :readme_format => "rdoc",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "rdoc")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "rdoc")
- @knife.run
- end
-
- it "should allow specifying the md readme format" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => "mit",
- :readme_format => "mkd",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "mkd")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "mkd")
- @knife.run
- end
-
- it "should allow specifying the txt readme format" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => "mit",
- :readme_format => "txt",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "txt")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "txt")
- @knife.run
- end
-
- it "should allow specifying an arbitrary readme format" do
- @dir = Dir.tmpdir
- @knife.config = {
- :cookbook_path => @dir,
- :cookbook_copyright => "Chef Software, Inc.",
- :cookbook_email => "test@chef.io",
- :cookbook_license => "mit",
- :readme_format => "foo",
- }
- @knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
- expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "foo")
- expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "foo")
- @knife.run
- end
-
- context "when the cookbooks path is set to nil" do
- before do
- Chef::Config[:cookbook_path] = nil
- end
-
- it "should throw an argument error" do
- @dir = Dir.tmpdir
- expect { @knife.run }.to raise_error(ArgumentError)
- end
- end
-
end
end
diff --git a/spec/unit/knife/cookbook_download_spec.rb b/spec/unit/knife/cookbook_download_spec.rb
index 38a4974774..1fb995f71d 100644
--- a/spec/unit/knife/cookbook_download_spec.rb
+++ b/spec/unit/knife/cookbook_download_spec.rb
@@ -47,44 +47,62 @@ describe Chef::Knife::CookbookDownload do
@rest_mock = double("rest")
allow(@knife).to receive(:rest).and_return(@rest_mock)
- @manifest_data = {
- :recipes => [
- { "path" => "recipes/foo.rb",
- "url" => "http://example.org/files/foo.rb" },
- { "path" => "recipes/bar.rb",
- "url" => "http://example.org/files/bar.rb" },
- ],
- :templates => [
- { "path" => "templates/default/foo.erb",
- "url" => "http://example.org/files/foo.erb" },
- { "path" => "templates/default/bar.erb",
- "url" => "http://example.org/files/bar.erb" },
- ],
- :attributes => [
- { "path" => "attributes/default.rb",
- "url" => "http://example.org/files/default.rb" },
+ expect(Chef::CookbookVersion).to receive(:load).with("foobar", "1.0.0").
+ and_return(cookbook)
+ end
+
+ let(:manifest_data) do
+ {
+ :all_files => [
+ {
+ "path" => "recipes/foo.rb",
+ "name" => "recipes/foo.rb",
+ "url" => "http://example.org/files/foo.rb",
+ },
+ {
+ "path" => "recipes/bar.rb",
+ "name" => "recipes/bar.rb",
+ "url" => "http://example.org/files/bar.rb",
+ },
+ {
+ "path" => "templates/default/foo.erb",
+ "name" => "templates/foo.erb",
+ "url" => "http://example.org/files/foo.erb",
+ },
+ {
+ "path" => "templates/default/bar.erb",
+ "name" => "templates/bar.erb",
+ "url" => "http://example.org/files/bar.erb",
+ },
+ {
+ "path" => "attributes/default.rb",
+ "name" => "attributes/default.rb",
+ "url" => "http://example.org/files/default.rb",
+ },
],
}
+ end
- @cookbook_mock = double("cookbook")
- allow(@cookbook_mock).to receive(:version).and_return("1.0.0")
- allow(@cookbook_mock).to receive(:manifest).and_return(@manifest_data)
- expect(Chef::CookbookVersion).to receive(:load).with("foobar", "1.0.0").
- and_return(@cookbook_mock)
+ let (:cookbook) do
+ cb = Chef::CookbookVersion.new("foobar")
+ cb.version = "1.0.0"
+ cb.manifest = manifest_data
+ cb
end
- it "should determine which version if one was not explicitly specified" do
- allow(@cookbook_mock).to receive(:manifest).and_return({})
- expect(@knife).to receive(:determine_version).and_return("1.0.0")
- expect(File).to receive(:exists?).with("/var/tmp/chef/foobar-1.0.0").and_return(false)
- allow(Chef::CookbookVersion).to receive(:COOKBOOK_SEGEMENTS).and_return([])
- @knife.run
+ describe "and no version" do
+ let (:manifest_data) { { all_files: [] } }
+ it "should determine which version to download" do
+ expect(@knife).to receive(:determine_version).and_return("1.0.0")
+ expect(File).to receive(:exists?).with("/var/tmp/chef/foobar-1.0.0").and_return(false)
+ @knife.run
+ end
end
describe "and a version" do
before(:each) do
@knife.name_args << "1.0.0"
- @files = @manifest_data.values.map { |v| v.map { |i| i["path"] } }.flatten.uniq
+ @files = manifest_data.values.map { |v| v.map { |i| i["path"] } }.flatten.uniq
@files_mocks = {}
@files.map { |f| File.basename(f) }.flatten.uniq.each do |f|
@files_mocks[f] = double("#{f}_mock")
diff --git a/spec/unit/knife/cookbook_show_spec.rb b/spec/unit/knife/cookbook_show_spec.rb
index 749e50c647..1e8ea836d7 100644
--- a/spec/unit/knife/cookbook_show_spec.rb
+++ b/spec/unit/knife/cookbook_show_spec.rb
@@ -47,9 +47,9 @@ describe Chef::Knife::CookbookShow do
let (:manifest) do
{
- "recipes" => [
+ "all_files" => [
{
- :name => "default.rb",
+ :name => "recipes/default.rb",
:path => "recipes/default.rb",
:checksum => "1234",
:url => "http://example.org/files/default.rb",
@@ -101,9 +101,42 @@ describe Chef::Knife::CookbookShow do
knife.name_args << "0.1.0"
end
+ let(:output) do
+ { "cookbook_name" => "cookbook_name",
+ "name" => "cookbook_name-0.0.0",
+ "frozen?" => false,
+ "version" => "0.0.0",
+ "metadata" => {
+ "name" => nil,
+ "description" => "",
+ "long_description" => "",
+ "maintainer" => nil,
+ "maintainer_email" => nil,
+ "license" => "All rights reserved",
+ "platforms" => {},
+ "dependencies" => {},
+ "providing" => {},
+ "attributes" => {},
+ "recipes" => {},
+ "version" => "0.0.0",
+ "source_url" => "",
+ "issues_url" => "",
+ "privacy" => false,
+ "chef_versions" => [],
+ "ohai_versions" => [],
+ "gems" => [],
+ },
+ "recipes" =>
+ [{ "name" => "recipes/default.rb",
+ "path" => "recipes/default.rb",
+ "checksum" => "1234",
+ "url" => "http://example.org/files/default.rb" }],
+ }
+ end
+
it "should show the specific part of a cookbook" do
expect(Chef::CookbookVersion).to receive(:load).with("cookbook_name", "0.1.0").and_return(cb)
- expect(knife).to receive(:output).with(cb)
+ expect(knife).to receive(:output).with(output)
knife.run
end
end
@@ -115,7 +148,7 @@ describe Chef::Knife::CookbookShow do
it "should print the json of the part" do
expect(Chef::CookbookVersion).to receive(:load).with("cookbook_name", "0.1.0").and_return(cb)
- expect(knife).to receive(:output).with(cb.manifest["recipes"])
+ expect(knife).to receive(:output).with(cb.files_for("recipes"))
knife.run
end
end
@@ -137,30 +170,30 @@ describe Chef::Knife::CookbookShow do
before(:each) do
knife.name_args = [ "cookbook_name", "0.1.0", "files", "afile.rb" ]
cb.manifest = {
- "files" => [
+ "all_files" => [
{
- :name => "afile.rb",
+ :name => "files/afile.rb",
:path => "files/host-examplehost.example.org/afile.rb",
:checksum => "1111",
:specificity => "host-examplehost.example.org",
:url => "http://example.org/files/1111",
},
{
- :name => "afile.rb",
+ :name => "files/afile.rb",
:path => "files/ubuntu-9.10/afile.rb",
:checksum => "2222",
:specificity => "ubuntu-9.10",
:url => "http://example.org/files/2222",
},
{
- :name => "afile.rb",
+ :name => "files/afile.rb",
:path => "files/ubuntu/afile.rb",
:checksum => "3333",
:specificity => "ubuntu",
:url => "http://example.org/files/3333",
},
{
- :name => "afile.rb",
+ :name => "files/afile.rb",
:path => "files/default/afile.rb",
:checksum => "4444",
:specificity => "default",
diff --git a/spec/unit/knife/core/cookbook_scm_repo_spec.rb b/spec/unit/knife/core/cookbook_scm_repo_spec.rb
index 137bdddafb..3c16f93533 100644
--- a/spec/unit/knife/core/cookbook_scm_repo_spec.rb
+++ b/spec/unit/knife/core/cookbook_scm_repo_spec.rb
@@ -83,7 +83,7 @@ BRANCHES
it "exits when the git repo is dirty" do
@dirty_status = Mixlib::ShellOut.new
@dirty_status.stdout.replace(<<-DIRTY)
- M chef/lib/chef/knife/cookbook_site_vendor.rb
+ M chef/lib/chef/knife/cookbook_site_install.rb
DIRTY
expect(@cookbook_repo).to receive(:shell_out!).with("git status --porcelain", :cwd => @repo_path).and_return(@dirty_status)
expect { @cookbook_repo.sanity_check }.to raise_error(SystemExit)
diff --git a/spec/unit/knife/core/custom_manifest_loader_spec.rb b/spec/unit/knife/core/custom_manifest_loader_spec.rb
deleted file mode 100644
index 814ac8a027..0000000000
--- a/spec/unit/knife/core/custom_manifest_loader_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# 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.
-#
-
-require "spec_helper"
-
-describe Chef::Knife::SubcommandLoader::CustomManifestLoader do
- let(:ec2_server_create_plugin) { "/usr/lib/ruby/gems/knife-ec2-0.5.12/lib/chef/knife/ec2_server_create.rb" }
- let(:manifest_content) do
- { "plugins" => {
- "knife-ec2" => {
- "paths" => [
- ec2_server_create_plugin,
- ],
- },
- },
- }
- end
- let(:loader) do
- Chef::Knife::SubcommandLoader::CustomManifestLoader.new(File.join(CHEF_SPEC_DATA, "knife-site-subcommands"),
- manifest_content)
- end
-
- it "uses paths from the manifest instead of searching gems" do
- expect(Gem::Specification).not_to receive(:latest_specs).and_call_original
- expect(loader.subcommand_files).to include(ec2_server_create_plugin)
- end
-end
diff --git a/spec/unit/knife/core/subcommand_loader_spec.rb b/spec/unit/knife/core/subcommand_loader_spec.rb
index b235102a0b..5db0bb73e5 100644
--- a/spec/unit/knife/core/subcommand_loader_spec.rb
+++ b/spec/unit/knife/core/subcommand_loader_spec.rb
@@ -43,12 +43,6 @@ describe Chef::Knife::SubcommandLoader do
allow(File).to receive(:read).with(File.join(home, ".chef", "plugin_manifest.json")).and_return("{ \"_autogenerated_command_paths\": {}}")
expect(Chef::Knife::SubcommandLoader.for_config(config_dir)).to be_a Chef::Knife::SubcommandLoader::HashedCommandLoader
end
-
- it "creates a CustomManifestLoader with then manifest has a key other than _autogenerated_command_paths" do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- allow(File).to receive(:read).with(File.join(home, ".chef", "plugin_manifest.json")).and_return("{ \"plugins\": {}}")
- expect(Chef::Knife::SubcommandLoader.for_config(config_dir)).to be_a Chef::Knife::SubcommandLoader::CustomManifestLoader
- end
end
context "when ~/.chef/plugin_manifest.json does not exist" do
diff --git a/spec/unit/knife/core/ui_spec.rb b/spec/unit/knife/core/ui_spec.rb
index 38614f44d9..0b986258b7 100644
--- a/spec/unit/knife/core/ui_spec.rb
+++ b/spec/unit/knife/core/ui_spec.rb
@@ -3,7 +3,7 @@
# Author:: Tim Hinderliter (<tim@chef.io>)
# Author:: Daniel DeLeo (<dan@chef.io>)
# Author:: John Keiser (<jkeiser@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -31,7 +31,6 @@ describe Chef::Knife::UI do
:field_separator => ".",
}
@ui = Chef::Knife::UI.new(@out, @err, @in, @config)
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
end
class TestObject < OpenStruct
diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb
index 9569526b2a..00c629b680 100644
--- a/spec/unit/knife_spec.rb
+++ b/spec/unit/knife_spec.rb
@@ -144,9 +144,9 @@ describe Chef::Knife do
end
it "finds a subcommand class based on ARGV" do
- Chef::Knife.subcommands["cookbook_site_vendor"] = :CookbookSiteVendor
+ Chef::Knife.subcommands["cookbook_site_install"] = :CookbookSiteInstall
Chef::Knife.subcommands["cookbook"] = :Cookbook
- expect(Chef::Knife.subcommand_class_from(%w{cookbook site vendor --help foo bar baz})).to eq(:CookbookSiteVendor)
+ expect(Chef::Knife.subcommand_class_from(%w{cookbook site install --help foo bar baz})).to eq(:CookbookSiteInstall)
end
it "special case sets the subcommand_loader to GemGlobLoader when running rehash" do
diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb
index 28773a3c30..75ebbb8f02 100644
--- a/spec/unit/lwrp_spec.rb
+++ b/spec/unit/lwrp_spec.rb
@@ -417,9 +417,8 @@ describe "LWRP" do
Chef::Config[:treat_deprecation_warnings_as_errors] = @old_treat_deprecation_warnings_as_errors
end
- it "should load the provider into a properly-named class" do
- expect(Chef::Provider.const_get("LwrpBuckPasser")).to be_kind_of(Class)
- expect(Chef::Provider::LwrpBuckPasser <= Chef::Provider::LWRPBase).to be_truthy
+ it "should not load the provider into a const" do
+ expect(defined?(Chef::Provider::LwrpBuckPasser)).to be_nil
end
it "should create a method for each action" do
@@ -571,55 +570,28 @@ describe "LWRP" do
end
context "resource class created" do
+ let(:test_lwrp_class) { @test_lwrp_class }
before(:context) do
@tmpdir = Dir.mktmpdir("lwrp_test")
resource_path = File.join(@tmpdir, "once.rb")
IO.write(resource_path, "default_action :create")
-
- @old_treat_deprecation_warnings_as_errors = Chef::Config[:treat_deprecation_warnings_as_errors]
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- Chef::Resource::LWRPBase.build_from_file("lwrp", resource_path, nil)
+ @test_lwrp_class = Chef::Resource::LWRPBase.build_from_file("lwrp", resource_path, nil)
end
after(:context) do
FileUtils.remove_entry @tmpdir
- Chef::Config[:treat_deprecation_warnings_as_errors] = @old_treat_deprecation_warnings_as_errors
end
- it "should load the resource into a properly-named class" do
- expect(Chef::Resource::LwrpOnce).to be_kind_of(Class)
- expect(Chef::Resource::LwrpOnce <= Chef::Resource::LWRPBase).to be_truthy
+ it "should not load the resource into a const" do
+ expect(defined?(Chef::Resource::LwrpOnce)).to be_nil
end
- it "get_lwrp(:lwrp_once).new is a Chef::Resource::LwrpOnce" do
+ it "get_lwrp(:lwrp_once).new is an instance of the LWRP class" do
lwrp = get_lwrp(:lwrp_once).new("hi")
- expect(lwrp.kind_of?(Chef::Resource::LwrpOnce)).to be_truthy
- expect(lwrp.is_a?(Chef::Resource::LwrpOnce)).to be_truthy
- expect(get_lwrp(:lwrp_once) === lwrp).to be_truthy
- expect(Chef::Resource::LwrpOnce === lwrp).to be_truthy
- end
-
- it "Chef::Resource::LwrpOnce.new is a get_lwrp(:lwrp_once)" do
- lwrp = Chef::Resource::LwrpOnce.new("hi")
- expect(lwrp.kind_of?(get_lwrp(:lwrp_once))).to be_truthy
- expect(lwrp.is_a?(get_lwrp(:lwrp_once))).to be_truthy
+ expect(lwrp.kind_of?(test_lwrp_class)).to be_truthy
+ expect(lwrp.is_a?(test_lwrp_class)).to be_truthy
expect(get_lwrp(:lwrp_once) === lwrp).to be_truthy
- expect(Chef::Resource::LwrpOnce === lwrp).to be_truthy
- end
-
- it "works even if LwrpOnce exists in the top level" do
- module ::LwrpOnce
- end
- expect(Chef::Resource::LwrpOnce).not_to eq(::LwrpOnce)
- end
-
- it "allows monkey patching of the lwrp through Chef::Resource" do
- monkey = Module.new do
- def issue_3607
- end
- end
- Chef::Resource::LwrpOnce.send(:include, monkey)
- expect { get_lwrp(:lwrp_once).new("blah").issue_3607 }.not_to raise_error
+ expect(test_lwrp_class === lwrp).to be_truthy
end
context "with a subclass of get_lwrp(:lwrp_once)" do
@@ -634,54 +606,12 @@ describe "LWRP" do
expect(subclass === lwrp).to be_truthy
expect(lwrp.class === subclass)
end
- it "subclass.new is a Chef::Resource::LwrpOnce" do
- lwrp = subclass.new("hi")
- expect(lwrp.kind_of?(Chef::Resource::LwrpOnce)).to be_truthy
- expect(lwrp.is_a?(Chef::Resource::LwrpOnce)).to be_truthy
- expect(Chef::Resource::LwrpOnce === lwrp).to be_truthy
- expect(lwrp.class === Chef::Resource::LwrpOnce)
- end
- it "subclass.new is a get_lwrp(:lwrp_once)" do
- lwrp = subclass.new("hi")
- expect(lwrp.kind_of?(get_lwrp(:lwrp_once))).to be_truthy
- expect(lwrp.is_a?(get_lwrp(:lwrp_once))).to be_truthy
- expect(get_lwrp(:lwrp_once) === lwrp).to be_truthy
- expect(lwrp.class === get_lwrp(:lwrp_once))
- end
- it "Chef::Resource::LwrpOnce.new is *not* a subclass" do
- lwrp = Chef::Resource::LwrpOnce.new("hi")
- expect(lwrp.kind_of?(subclass)).to be_falsey
- expect(lwrp.is_a?(subclass)).to be_falsey
- expect(subclass === lwrp.class).to be_falsey
- expect(subclass === Chef::Resource::LwrpOnce).to be_falsey
- end
- it "get_lwrp(:lwrp_once).new is *not* a subclass" do
- lwrp = get_lwrp(:lwrp_once).new("hi")
- expect(lwrp.kind_of?(subclass)).to be_falsey
- expect(lwrp.is_a?(subclass)).to be_falsey
- expect(subclass === lwrp.class).to be_falsey
- expect(subclass === get_lwrp(:lwrp_once)).to be_falsey
- end
- end
-
- context "with a subclass of Chef::Resource::LwrpOnce" do
- let(:subclass) do
- Class.new(Chef::Resource::LwrpOnce)
- end
-
- it "subclass.new is a subclass" do
- lwrp = subclass.new("hi")
- expect(lwrp.kind_of?(subclass)).to be_truthy
- expect(lwrp.is_a?(subclass)).to be_truthy
- expect(subclass === lwrp).to be_truthy
- expect(lwrp.class === subclass)
- end
- it "subclass.new is a Chef::Resource::LwrpOnce" do
+ it "subclass.new is an instance of the LWRP class" do
lwrp = subclass.new("hi")
- expect(lwrp.kind_of?(Chef::Resource::LwrpOnce)).to be_truthy
- expect(lwrp.is_a?(Chef::Resource::LwrpOnce)).to be_truthy
- expect(Chef::Resource::LwrpOnce === lwrp).to be_truthy
- expect(lwrp.class === Chef::Resource::LwrpOnce)
+ expect(lwrp.kind_of?(test_lwrp_class)).to be_truthy
+ expect(lwrp.is_a?(test_lwrp_class)).to be_truthy
+ expect(test_lwrp_class === lwrp).to be_truthy
+ expect(lwrp.class === test_lwrp_class)
end
it "subclass.new is a get_lwrp(:lwrp_once)" do
lwrp = subclass.new("hi")
@@ -690,13 +620,6 @@ describe "LWRP" do
expect(get_lwrp(:lwrp_once) === lwrp).to be_truthy
expect(lwrp.class === get_lwrp(:lwrp_once))
end
- it "Chef::Resource::LwrpOnce.new is *not* a subclass" do
- lwrp = Chef::Resource::LwrpOnce.new("hi")
- expect(lwrp.kind_of?(subclass)).to be_falsey
- expect(lwrp.is_a?(subclass)).to be_falsey
- expect(subclass === lwrp.class).to be_falsey
- expect(subclass === Chef::Resource::LwrpOnce).to be_falsey
- end
it "get_lwrp(:lwrp_once).new is *not* a subclass" do
lwrp = get_lwrp(:lwrp_once).new("hi")
expect(lwrp.kind_of?(subclass)).to be_falsey
@@ -721,8 +644,6 @@ describe "LWRP" do
end
class MyAwesomeProvider < Chef::Provider::LWRPBase
- use_inline_resources
-
provides :my_awesome_resource
action :create do
diff --git a/spec/unit/mixin/command_spec.rb b/spec/unit/mixin/command_spec.rb
deleted file mode 100644
index e9f0dacad6..0000000000
--- a/spec/unit/mixin/command_spec.rb
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# Author:: Hongli Lai (hongli@phusion.nl)
-# Copyright:: Copyright 2009-2016, Phusion
-# 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::Mixin::Command, :volatile do
-
- if windows?
-
- skip("TODO MOVE: this is a platform specific integration test.")
-
- else
-
- describe "popen4" do
- include Chef::Mixin::Command
-
- it "should be possible to read the child process's stdout and stderr" do
- popen4("sh -c 'echo hello && echo world >&2'") do |pid, stdin, stdout, stderr|
- expect(stdout.read).to eq("hello\n")
- expect(stderr.read).to eq("world\n")
- end
- end
-
- it "should default all commands to be run in the POSIX standard C locale" do
- popen4("echo $LC_ALL") do |pid, stdin, stdout, stderr|
- expect(stdout.read.strip).to eq("C")
- end
- end
-
- it "should respect locale when specified explicitly" do
- popen4("echo $LC_ALL", :environment => { "LC_ALL" => "es" }) do |pid, stdin, stdout, stderr|
- expect(stdout.read.strip).to eq("es")
- end
- end
-
- it "should end when the child process reads from STDIN and a block is given" do
- expect do
- Timeout.timeout(10) do
- popen4("ruby -e 'while gets; end'", :waitlast => true) do |pid, stdin, stdout, stderr|
- (1..5).each { |i| stdin.puts "#{i}" }
- end
- end
- end.not_to raise_error
- end
-
- describe "when a process detaches but doesn't close STDOUT and STDERR [CHEF-584]" do
-
- it "returns immediately after the first child process exits" do
- expect do
- Timeout.timeout(10) do
- evil_forker = "exit if fork; 10.times { sleep 1}"
- popen4("ruby -e '#{evil_forker}'") do |pid, stdin, stdout, stderr|
- end
- end end.not_to raise_error
- end
-
- end
-
- end
-
- describe "run_command" do
- include Chef::Mixin::Command
-
- it "logs the command's stderr and stdout output if the command failed" do
- allow(Chef::Log).to receive(:level).and_return(:debug)
- begin
- run_command(:command => "sh -c 'echo hello; echo world >&2; false'")
- violated "Exception expected, but nothing raised."
- rescue => e
- expect(e.message).to match(/STDOUT: hello/)
- expect(e.message).to match(/STDERR: world/)
- end
- end
-
- describe "when a process detaches but doesn't close STDOUT and STDERR [CHEF-584]" do
- it "returns successfully" do
- # CHEF-2916 might have added a slight delay here, or our CI
- # infrastructure is burdened. Bumping timeout from 2 => 4 --
- # btm
- # Serdar - During Solaris tests, we've seen that processes
- # are taking a long time to exit. Bumping timeout now to 10.
- expect do
- Timeout.timeout(10) do
- evil_forker = "exit if fork; 10.times { sleep 1}"
- run_command(:command => "ruby -e '#{evil_forker}'")
- end end.not_to raise_error
- end
-
- end
- end
- end
-end
diff --git a/spec/unit/mixin/path_sanity_spec.rb b/spec/unit/mixin/path_sanity_spec.rb
index 675b5722be..c9ed4e2595 100644
--- a/spec/unit/mixin/path_sanity_spec.rb
+++ b/spec/unit/mixin/path_sanity_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
-# Copyright:: Copyright 2011-2016, Chef Software Inc.
+# Copyright:: Copyright 2011-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,19 +41,19 @@ describe Chef::Mixin::PathSanity do
it "adds all useful PATHs even if environment is an empty hash" do
env = {}
@sanity.enforce_path_sanity(env)
- expect(env["PATH"]).to eq("#{@ruby_bindir}:#{@gem_bindir}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
+ expect(env["PATH"]).to eq("#{@gem_bindir}:#{@ruby_bindir}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
end
it "adds all useful PATHs that are not yet in PATH to PATH" do
env = { "PATH" => "" }
@sanity.enforce_path_sanity(env)
- expect(env["PATH"]).to eq("#{@ruby_bindir}:#{@gem_bindir}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
+ expect(env["PATH"]).to eq("#{@gem_bindir}:#{@ruby_bindir}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
end
it "does not re-add paths that already exist in PATH" do
env = { "PATH" => "/usr/bin:/sbin:/bin" }
@sanity.enforce_path_sanity(env)
- expect(env["PATH"]).to eq("/usr/bin:/sbin:/bin:#{@ruby_bindir}:#{@gem_bindir}:/usr/local/sbin:/usr/local/bin:/usr/sbin")
+ expect(env["PATH"]).to eq("#{@gem_bindir}:#{@ruby_bindir}:/usr/bin:/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin")
end
it "creates path with utf-8 encoding" do
@@ -65,7 +65,7 @@ describe Chef::Mixin::PathSanity do
it "adds the current executing Ruby's bindir and Gem bindir to the PATH" do
env = { "PATH" => "" }
@sanity.enforce_path_sanity(env)
- expect(env["PATH"]).to eq("#{@ruby_bindir}:#{@gem_bindir}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
+ expect(env["PATH"]).to eq("#{@gem_bindir}:#{@ruby_bindir}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
end
it "does not create entries for Ruby/Gem bindirs if they exist in SANE_PATH or PATH" do
@@ -75,7 +75,7 @@ describe Chef::Mixin::PathSanity do
allow(RbConfig::CONFIG).to receive(:[]).with("bindir").and_return(ruby_bindir)
env = { "PATH" => gem_bindir }
@sanity.enforce_path_sanity(env)
- expect(env["PATH"]).to eq("/yo/gabba/gabba:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
+ expect(env["PATH"]).to eq("/usr/bin:/yo/gabba/gabba:/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/bin")
end
it "builds a valid windows path" do
@@ -86,7 +86,7 @@ describe Chef::Mixin::PathSanity do
allow(ChefConfig).to receive(:windows?).and_return(true)
env = { "PATH" => 'C:\Windows\system32;C:\mr\softie' }
@sanity.enforce_path_sanity(env)
- expect(env["PATH"]).to eq("C:\\Windows\\system32;C:\\mr\\softie;#{ruby_bindir};#{gem_bindir}")
+ expect(env["PATH"]).to eq("#{gem_bindir};#{ruby_bindir};C:\\Windows\\system32;C:\\mr\\softie")
end
end
end
diff --git a/spec/unit/mixin/shell_out_spec.rb b/spec/unit/mixin/shell_out_spec.rb
index aa38639c1c..9b12969026 100644
--- a/spec/unit/mixin/shell_out_spec.rb
+++ b/spec/unit/mixin/shell_out_spec.rb
@@ -21,91 +21,19 @@
#
require "spec_helper"
+require "chef/mixin/path_sanity"
describe Chef::Mixin::ShellOut do
+ include Chef::Mixin::PathSanity
+
let(:shell_out_class) { Class.new { include Chef::Mixin::ShellOut } }
subject(:shell_out_obj) { shell_out_class.new }
- describe "#run_command_compatible_options" do
- subject { shell_out_obj.run_command_compatible_options(command_args) }
- let(:command_args) { [ cmd, options ] }
- let(:cmd) { "echo '#{rand(1000)}'" }
-
- let(:output) { StringIO.new }
- let!(:capture_log_output) { Chef::Log.logger = Logger.new(output) }
- let(:assume_deprecation_log_level) { allow(Chef::Log).to receive(:level).and_return(:warn) }
-
- before do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- end
-
- context "without options" do
- let(:command_args) { [ cmd ] }
-
- it "should not edit command args" do
- is_expected.to eql(command_args)
- end
- end
-
- context "without deprecated options" do
- let(:options) { { :environment => environment } }
- let(:environment) { { "LC_ALL" => "C", "LANG" => "C", "LANGUAGE" => "C" } }
-
- it "should not edit command args" do
- is_expected.to eql(command_args)
- end
- end
-
- def self.should_emit_deprecation_warning_about(old_option, new_option)
- it "should emit a deprecation warning" do
- assume_deprecation_log_level && capture_log_output
- subject
- expect(output.string).to match Regexp.escape(old_option.to_s)
- expect(output.string).to match Regexp.escape(new_option.to_s)
- end
- end
-
- context "with :command_log_level option" do
- let(:options) { { :command_log_level => command_log_level } }
- let(:command_log_level) { :warn }
-
- it "should convert :command_log_level to :log_level" do
- is_expected.to eql [ cmd, { :log_level => command_log_level } ]
- end
-
- should_emit_deprecation_warning_about :command_log_level, :log_level
- end
-
- context "with :command_log_prepend option" do
- let(:options) { { :command_log_prepend => command_log_prepend } }
- let(:command_log_prepend) { "PROVIDER:" }
-
- it "should convert :command_log_prepend to :log_tag" do
- is_expected.to eql [ cmd, { :log_tag => command_log_prepend } ]
- end
-
- should_emit_deprecation_warning_about :command_log_prepend, :log_tag
- end
-
- context "with 'command_log_level' option" do
- let(:options) { { "command_log_level" => command_log_level } }
- let(:command_log_level) { :warn }
-
- it "should convert 'command_log_level' to :log_level" do
- is_expected.to eql [ cmd, { :log_level => command_log_level } ]
- end
-
- should_emit_deprecation_warning_about :command_log_level, :log_level
- end
-
- context "with 'command_log_prepend' option" do
- let(:options) { { "command_log_prepend" => command_log_prepend } }
- let(:command_log_prepend) { "PROVIDER:" }
-
- it "should convert 'command_log_prepend' to :log_tag" do
- is_expected.to eql [ cmd, { :log_tag => command_log_prepend } ]
- end
- should_emit_deprecation_warning_about :command_log_prepend, :log_tag
+ def env_path
+ if Chef::Platform.windows?
+ "Path"
+ else
+ "PATH"
end
end
@@ -127,13 +55,13 @@ describe Chef::Mixin::ShellOut do
describe "when the last argument is a Hash" do
describe "and environment is an option" do
it "should not change environment language settings when they are set to nil" do
- options = { :environment => { "LC_ALL" => nil, "LANGUAGE" => nil, "LANG" => nil } }
+ options = { :environment => { "LC_ALL" => nil, "LANGUAGE" => nil, "LANG" => nil, env_path => nil } }
expect(shell_out_obj).to receive(:shell_out_command).with(cmd, options).and_return(true)
shell_out_obj.shell_out(cmd, options)
end
it "should not change environment language settings when they are set to non-nil" do
- options = { :environment => { "LC_ALL" => "en_US.UTF-8", "LANGUAGE" => "en_US.UTF-8", "LANG" => "en_US.UTF-8" } }
+ options = { :environment => { "LC_ALL" => "en_US.UTF-8", "LANGUAGE" => "en_US.UTF-8", "LANG" => "en_US.UTF-8", env_path => "foo:bar:baz" } }
expect(shell_out_obj).to receive(:shell_out_command).with(cmd, options).and_return(true)
shell_out_obj.shell_out(cmd, options)
end
@@ -146,6 +74,7 @@ describe Chef::Mixin::ShellOut do
"LC_ALL" => Chef::Config[:internal_locale],
"LANG" => Chef::Config[:internal_locale],
"LANGUAGE" => Chef::Config[:internal_locale],
+ env_path => sanitized_path,
},
}).and_return(true)
shell_out_obj.shell_out(cmd, options)
@@ -159,6 +88,7 @@ describe Chef::Mixin::ShellOut do
"LC_ALL" => Chef::Config[:internal_locale],
"LANG" => Chef::Config[:internal_locale],
"LANGUAGE" => Chef::Config[:internal_locale],
+ env_path => sanitized_path,
},
}).and_return(true)
shell_out_obj.shell_out(cmd, options)
@@ -168,13 +98,13 @@ describe Chef::Mixin::ShellOut do
describe "and env is an option" do
it "should not change env when langauge options are set to nil" do
- options = { :env => { "LC_ALL" => nil, "LANG" => nil, "LANGUAGE" => nil } }
+ options = { :env => { "LC_ALL" => nil, "LANG" => nil, "LANGUAGE" => nil, env_path => nil } }
expect(shell_out_obj).to receive(:shell_out_command).with(cmd, options).and_return(true)
shell_out_obj.shell_out(cmd, options)
end
it "should not change env when language options are set to non-nil" do
- options = { :env => { "LC_ALL" => "de_DE.UTF-8", "LANG" => "de_DE.UTF-8", "LANGUAGE" => "de_DE.UTF-8" } }
+ options = { :env => { "LC_ALL" => "de_DE.UTF-8", "LANG" => "de_DE.UTF-8", "LANGUAGE" => "de_DE.UTF-8", env_path => "foo:bar:baz" } }
expect(shell_out_obj).to receive(:shell_out_command).with(cmd, options).and_return(true)
shell_out_obj.shell_out(cmd, options)
end
@@ -187,6 +117,7 @@ describe Chef::Mixin::ShellOut do
"LC_ALL" => Chef::Config[:internal_locale],
"LANG" => Chef::Config[:internal_locale],
"LANGUAGE" => Chef::Config[:internal_locale],
+ env_path => sanitized_path,
},
}).and_return(true)
shell_out_obj.shell_out(cmd, options)
@@ -200,6 +131,7 @@ describe Chef::Mixin::ShellOut do
"LC_ALL" => Chef::Config[:internal_locale],
"LANG" => Chef::Config[:internal_locale],
"LANGUAGE" => Chef::Config[:internal_locale],
+ env_path => sanitized_path,
},
}).and_return(true)
shell_out_obj.shell_out(cmd, options)
@@ -216,6 +148,7 @@ describe Chef::Mixin::ShellOut do
"LC_ALL" => Chef::Config[:internal_locale],
"LANG" => Chef::Config[:internal_locale],
"LANGUAGE" => Chef::Config[:internal_locale],
+ env_path => sanitized_path,
},
}).and_return(true)
shell_out_obj.shell_out(cmd, options)
@@ -230,6 +163,7 @@ describe Chef::Mixin::ShellOut do
"LC_ALL" => Chef::Config[:internal_locale],
"LANG" => Chef::Config[:internal_locale],
"LANGUAGE" => Chef::Config[:internal_locale],
+ env_path => sanitized_path,
},
}).and_return(true)
shell_out_obj.shell_out(cmd)
diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb
index 40780e523b..73f0e6da09 100644
--- a/spec/unit/node_spec.rb
+++ b/spec/unit/node_spec.rb
@@ -265,12 +265,6 @@ describe Chef::Node do
expect(node[:snoopy][:is_a_puppy]).to eq(true)
end
- it "should allow you to set an attribute with set_unless with method_missing but emit a deprecation warning" do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- node.normal_unless.snoopy.is_a_puppy = false
- expect(node[:snoopy][:is_a_puppy]).to eq(false)
- end
-
it "should allow you to set an attribute with set_unless" do
node.normal_unless[:snoopy][:is_a_puppy] = false
expect(node[:snoopy][:is_a_puppy]).to eq(false)
diff --git a/spec/unit/policy_builder/policyfile_spec.rb b/spec/unit/policy_builder/policyfile_spec.rb
index 307bd45c18..c9086c2f63 100644
--- a/spec/unit/policy_builder/policyfile_spec.rb
+++ b/spec/unit/policy_builder/policyfile_spec.rb
@@ -100,8 +100,8 @@ describe Chef::PolicyBuilder::Policyfile do
http = double("Chef::ServerAPI")
server_url = "https://api.opscode.com/organizations/example"
Chef::Config[:chef_server_url] = server_url
- expect(Chef::ServerAPI).to receive(:new).with(server_url).and_return(http)
- expect(policy_builder.http_api).to eq(http)
+ expect(Chef::ServerAPI).to receive(:new).with(server_url, version_class: Chef::CookbookManifestVersions).and_return(http)
+ expect(policy_builder.api_service).to eq(http)
end
describe "reporting unsupported features" do
@@ -150,7 +150,7 @@ describe Chef::PolicyBuilder::Policyfile do
describe "loading policy data" do
- let(:http_api) { double("Chef::ServerAPI") }
+ let(:api_service) { double("Chef::ServerAPI") }
let(:configured_environment) { nil }
@@ -172,7 +172,7 @@ describe Chef::PolicyBuilder::Policyfile do
before do
Chef::Config[:policy_document_native_api] = false
Chef::Config[:deployment_group] = "example-policy-stage"
- allow(policy_builder).to receive(:http_api).and_return(http_api)
+ allow(policy_builder).to receive(:api_service).and_return(api_service)
end
describe "when using compatibility mode (policy_document_native_api == false)" do
@@ -185,7 +185,7 @@ describe Chef::PolicyBuilder::Policyfile do
let(:error404) { Net::HTTPServerException.new("404 message", :body) }
before do
- expect(http_api).to receive(:get).
+ expect(api_service).to receive(:get).
with("data/policyfiles/example-policy-stage").
and_raise(error404)
end
@@ -212,7 +212,7 @@ describe Chef::PolicyBuilder::Policyfile do
let(:policy_relative_url) { "data/policyfiles/example-policy-stage" }
before do
- expect(http_api).to receive(:get).with(policy_relative_url).and_return(parsed_policyfile_json)
+ expect(api_service).to receive(:get).with(policy_relative_url).and_return(parsed_policyfile_json)
end
it "fetches the policy file from a data bag item" do
@@ -253,7 +253,7 @@ describe Chef::PolicyBuilder::Policyfile do
let(:policy_relative_url) { "policy_groups/policy-stage/policies/example" }
before do
- expect(http_api).to receive(:get).with(policy_relative_url).and_return(parsed_policyfile_json)
+ expect(api_service).to receive(:get).with(policy_relative_url).and_return(parsed_policyfile_json)
end
it "fetches the policy file from a data bag item" do
@@ -617,7 +617,7 @@ describe Chef::PolicyBuilder::Policyfile do
policy_builder.finish_load_node(node)
policy_builder.build_node
- expect(http_api).to receive(:get).with(cookbook1_url).
+ expect(api_service).to receive(:get).with(cookbook1_url).
and_raise(error404)
end
@@ -687,9 +687,9 @@ describe Chef::PolicyBuilder::Policyfile do
context "when the cookbooks exist on the server" do
before do
- expect(http_api).to receive(:get).with(cookbook1_url).
+ expect(api_service).to receive(:get).with(cookbook1_url).
and_return(example1_cookbook_data)
- expect(http_api).to receive(:get).with(cookbook2_url).
+ expect(api_service).to receive(:get).with(cookbook2_url).
and_return(example2_cookbook_data)
expect(Chef::CookbookVersion).to receive(:from_cb_artifact_data).with(example1_cookbook_data).
@@ -720,9 +720,9 @@ describe Chef::PolicyBuilder::Policyfile do
context "when the cookbooks exist on the server" do
before do
- expect(http_api).to receive(:get).with(cookbook1_url).
+ expect(api_service).to receive(:get).with(cookbook1_url).
and_return(example1_cookbook_data)
- expect(http_api).to receive(:get).with(cookbook2_url).
+ expect(api_service).to receive(:get).with(cookbook2_url).
and_return(example2_cookbook_data)
expect(Chef::CookbookVersion).to receive(:from_cb_artifact_data).with(example1_cookbook_data).
diff --git a/spec/unit/property_spec.rb b/spec/unit/property_spec.rb
index 79ec05ea6d..b8cf7f5d1b 100644
--- a/spec/unit/property_spec.rb
+++ b/spec/unit/property_spec.rb
@@ -522,22 +522,41 @@ describe "Chef::Resource.property" do
end
end
- context "hash default" do
- context "(deprecations allowed)" do
- before { Chef::Config[:treat_deprecation_warnings_as_errors] = false }
+ context "string default" do
+ with_property ":x, default: ''" do
+ it "when x is not set, it returns ''" do
+ expect(resource.x).to eq ""
+ end
+ it "x is immutable" do
+ expect { resource.x << "foo" }.to raise_error(RuntimeError, "can't modify frozen String")
+ end
+ end
- with_property ":x, default: {}" do
- it "when x is not set, it returns {}" do
- expect(resource.x).to eq({})
- end
- it "The same exact value is returned multiple times in a row" do
- value = resource.x
- expect(value).to eq({})
- expect(resource.x.object_id).to eq(value.object_id)
- end
- it "Multiple instances of x receive the exact same value" do
- expect(resource.x.object_id).to eq(resource_class.new("blah2").x.object_id)
- end
+ with_property ":x, default: lazy { '' }" do
+ it "x is immutable" do
+ expect(resource.x).to eq ""
+ resource.x << "foo"
+ expect(resource.x).to eq "foo"
+ expect(resource_class.new("other").x).to eq ""
+ end
+ end
+ end
+
+ context "hash default" do
+ with_property ":x, default: {}" do
+ it "when x is not set, it returns {}" do
+ expect(resource.x).to eq({})
+ end
+ it "x is immutable" do
+ expect { resource.x["foo"] = "bar" }.to raise_error(RuntimeError, "can't modify frozen Hash")
+ end
+ it "The same exact value is returned multiple times in a row" do
+ value = resource.x
+ expect(value).to eq({})
+ expect(resource.x.object_id).to eq(value.object_id)
+ end
+ it "Multiple instances of x receive the exact same value" do
+ expect(resource.x.object_id).to eq(resource_class.new("blah2").x.object_id)
end
end
@@ -545,17 +564,34 @@ describe "Chef::Resource.property" do
it "when x is not set, it returns {}" do
expect(resource.x).to eq({})
end
- # it "The value is different each time it is called" do
- # value = resource.x
- # expect(value).to eq({})
- # expect(resource.x.object_id).not_to eq(value.object_id)
- # end
+ it "The value is the same each time it is called" do
+ value = resource.x
+ expect(value).to eq({})
+ expect(resource.x.object_id).to eq(value.object_id)
+ end
it "Multiple instances of x receive different values" do
expect(resource.x.object_id).not_to eq(resource_class.new("blah2").x.object_id)
end
end
end
+ context "complex, nested default" do
+ with_property ":x, default: [{foo: 'bar'}]" do
+ it "when x is not set, it returns [{foo: 'bar'}]" do
+ expect(resource.x).to eq([{ foo: "bar" }])
+ end
+ it "x is immutable" do
+ expect { resource.x << :other }.to raise_error(RuntimeError, "can't modify frozen Array")
+ end
+ it "x.first is immutable" do
+ expect { resource.x.first[:foo] = "other" }.to raise_error(RuntimeError, "can't modify frozen Hash")
+ end
+ it "x.first[:foo] is immutable" do
+ expect { resource.x.first[:foo] << "other" }.to raise_error(RuntimeError, "can't modify frozen String")
+ end
+ end
+ end
+
context "with a class with 'blah' as both class and instance methods" do
before do
resource_class.class_eval do
@@ -576,7 +612,6 @@ describe "Chef::Resource.property" do
it "x is run in the context of each instance it is run in" do
expect(resource.x).to eq "blah1"
expect(resource_class.new("another").x).to eq "another2"
- # expect(resource.x).to eq "blah3"
end
end
@@ -587,7 +622,6 @@ describe "Chef::Resource.property" do
it "x is passed the value of each instance it is run in" do
expect(resource.x).to eq "classblah1"
expect(resource_class.new("another").x).to eq "classanother2"
- # expect(resource.x).to eq "classblah3"
end
end
end
diff --git a/spec/unit/provider/cron_spec.rb b/spec/unit/provider/cron_spec.rb
index 64916ef454..ef629ebd52 100644
--- a/spec/unit/provider/cron_spec.rb
+++ b/spec/unit/provider/cron_spec.rb
@@ -880,8 +880,7 @@ MAILTO=foo@example.com
describe "read_crontab" do
before :each do
- @status = double("Status", :exitstatus => 0)
- @stdout = StringIO.new(<<-CRONTAB)
+ @stdout = <<-CRONTAB
0 2 * * * /some/other/command
# Chef Name: something else
@@ -889,11 +888,12 @@ MAILTO=foo@example.com
# Another comment
CRONTAB
- allow(@provider).to receive(:popen4).and_yield(1234, StringIO.new, @stdout, StringIO.new).and_return(@status)
+ @status = double("Status", exitstatus: 0, stdout: @stdout)
+ allow(@provider).to receive(:shell_out!).and_return(@status)
end
it "should call crontab -l with the user" do
- expect(@provider).to receive(:popen4).with("crontab -l -u #{@new_resource.user}").and_return(@status)
+ expect(@provider).to receive(:shell_out!).with("crontab -l -u #{@new_resource.user}", returns: [0, 1]).and_return(@status)
@provider.send(:read_crontab)
end
@@ -910,60 +910,36 @@ MAILTO=foo@example.com
end
it "should return nil if the user has no crontab" do
- status = double("Status", :exitstatus => 1)
- allow(@provider).to receive(:popen4).and_return(status)
+ @status = double("Status", exitstatus: 1, stdout: "")
+ allow(@provider).to receive(:shell_out!).and_return(@status)
expect(@provider.send(:read_crontab)).to eq(nil)
end
it "should raise an exception if another error occurs" do
- status = double("Status", :exitstatus => 2)
- allow(@provider).to receive(:popen4).and_return(status)
- expect do
- @provider.send(:read_crontab)
- end.to raise_error(Chef::Exceptions::Cron, "Error determining state of #{@new_resource.name}, exit: 2")
+ @status = double("Status", exitstatus: 2)
+ allow(@provider).to receive(:shell_out!).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ expect { @provider.send(:read_crontab) }.to raise_error(Chef::Exceptions::Cron)
end
end
describe "write_crontab" do
before :each do
- @status = double("Status", :exitstatus => 0)
- @stdin = StringIO.new
- allow(@provider).to receive(:popen4).and_yield(1234, @stdin, StringIO.new, StringIO.new).and_return(@status)
+ @status = double("Status", exitstatus: 0)
+ allow(@provider).to receive(:shell_out!).and_return(@status)
end
it "should call crontab for the user" do
- expect(@provider).to receive(:popen4).with("crontab -u #{@new_resource.user} -", :waitlast => true).and_return(@status)
+ expect(@provider).to receive(:shell_out!).with("crontab -u #{@new_resource.user} -", input: "Foo").and_return(@status)
@provider.send(:write_crontab, "Foo")
end
- it "should write the given string to the crontab command" do
- @provider.send(:write_crontab, "Foo\n# wibble\n wah!!")
- expect(@stdin.string).to eq("Foo\n# wibble\n wah!!")
- end
-
it "should raise an exception if the command returns non-zero" do
- allow(@status).to receive(:exitstatus).and_return(1)
- expect do
- @provider.send(:write_crontab, "Foo")
- end.to raise_error(Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: 1")
- end
-
- it "should raise an exception if the command die's and parent tries to write" do
- class WriteErrPipe
- def write(str)
- raise Errno::EPIPE, "Test"
- end
- end
- allow(@status).to receive(:exitstatus).and_return(1)
- allow(@provider).to receive(:popen4).and_yield(1234, WriteErrPipe.new, StringIO.new, StringIO.new).and_return(@status)
-
- expect(Chef::Log).to receive(:debug).with("Broken pipe - Test")
-
+ @status = double("Status", exitstatus: 1)
+ allow(@provider).to receive(:shell_out!).and_raise(Mixlib::ShellOut::ShellCommandFailed)
expect do
@provider.send(:write_crontab, "Foo")
- end.to raise_error(Chef::Exceptions::Cron, "Error updating state of #{@new_resource.name}, exit: 1")
+ end.to raise_error(Chef::Exceptions::Cron)
end
-
end
describe "weekday_in_crontab" do
diff --git a/spec/unit/provider/erl_call_spec.rb b/spec/unit/provider/erl_call_spec.rb
index f1c229028a..b5d3ae8c07 100644
--- a/spec/unit/provider/erl_call_spec.rb
+++ b/spec/unit/provider/erl_call_spec.rb
@@ -31,11 +31,8 @@ describe Chef::Provider::ErlCall do
@provider = Chef::Provider::ErlCall.new(@new_resource, @run_context)
- allow(@provider).to receive(:popen4).and_return(@status)
- @stdin = StringIO.new
- @stdout = StringIO.new("{ok, woohoo}")
- @stderr = StringIO.new
- @pid = 2342999
+ @status = double("Status", stdout: "{ok, woohoo}", stderr: "")
+ allow(@provider).to receive(:shell_out!).and_return(@status)
end
it "should return a Chef::Provider::ErlCall object" do
@@ -56,12 +53,9 @@ describe Chef::Provider::ErlCall do
it "should write to stdin of the erl_call command" do
expected_cmd = "erl_call -e -s -sname chef@localhost -c nomnomnom"
- expect(@provider).to receive(:popen4).with(expected_cmd, :waitlast => true).and_return([@pid, @stdin, @stdout, @stderr])
- expect(Process).to receive(:wait).with(@pid)
+ expect(@provider).to receive(:shell_out!).with(expected_cmd, input: @new_resource.code).and_return(@status)
@provider.action_run
-
- expect(@stdin.string).to eq("#{@new_resource.code}\n")
end
end
@@ -73,12 +67,10 @@ describe Chef::Provider::ErlCall do
end
it "should write to stdin of the erl_call command" do
- expect(@provider).to receive(:popen4).with("erl_call -e -name chef@localhost ", :waitlast => true).and_return([@pid, @stdin, @stdout, @stderr])
- expect(Process).to receive(:wait).with(@pid)
+ expected_cmd = "erl_call -e -name chef@localhost "
+ expect(@provider).to receive(:shell_out!).with(expected_cmd, input: @new_resource.code).and_return(@status)
@provider.action_run
-
- expect(@stdin.string).to eq("#{@new_resource.code}\n")
end
end
diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb
index 53c82f2f70..c40eed50cf 100644
--- a/spec/unit/provider/package/rubygems_spec.rb
+++ b/spec/unit/provider/package/rubygems_spec.rb
@@ -341,6 +341,7 @@ describe Chef::Provider::Package::Rubygems do
let(:bindir) { "/usr/bin/ruby" }
let(:options) { nil }
let(:source) { nil }
+ let(:include_default_source) { true }
let(:new_resource) do
new_resource = Chef::Resource::GemPackage.new(gem_name)
@@ -348,6 +349,7 @@ describe Chef::Provider::Package::Rubygems do
new_resource.gem_binary(gem_binary) if gem_binary
new_resource.options(options) if options
new_resource.source(source) if source
+ new_resource.include_default_source(include_default_source)
new_resource
end
@@ -534,17 +536,56 @@ describe Chef::Provider::Package::Rubygems do
end
end
+ context "when the source is from the rubygems_uri" do
+ it "determines the candidate version by querying the remote gem servers" do
+ Chef::Config[:rubygems_url] = "https://mirror1/"
+ expect(provider.gem_env).to receive(:candidate_version_from_remote)
+ .with(gem_dep, "https://mirror1/")
+ .and_return(Gem::Version.new(target_version))
+ expect(provider.candidate_version).to eq(target_version)
+ end
+ end
+
context "when the requested source is a remote server" do
let(:source) { "http://mygems.example.com" }
it "determines the candidate version by querying the remote gem servers" do
expect(provider.gem_env).to receive(:candidate_version_from_remote)
+ .with(gem_dep, source, Chef::Config[:rubygems_url])
+ .and_return(Gem::Version.new(target_version))
+ expect(provider.candidate_version).to eq(target_version)
+ end
+
+ it "overwrites the config variable" do
+ new_resource.include_default_source false
+ Chef::Config[:rubygems_url] = "https://overridden"
+ expect(provider.gem_env).to receive(:candidate_version_from_remote)
.with(gem_dep, source)
.and_return(Gem::Version.new(target_version))
expect(provider.candidate_version).to eq(target_version)
end
end
+ context "when the requested source is an array" do
+ let(:source) { [ "https://mirror1", "https://mirror2" ] }
+
+ it "determines the candidate version by querying the remote gem servers" do
+ expect(provider.gem_env).to receive(:candidate_version_from_remote)
+ .with(gem_dep, *[source, Chef::Config[:rubygems_url] ].flatten)
+ .and_return(Gem::Version.new(target_version))
+ expect(provider.candidate_version).to eq(target_version)
+ end
+
+ it "overwrites the config variable" do
+ new_resource.include_default_source false
+ Chef::Config[:rubygems_url] = "https://overridden"
+ expect(provider.gem_env).to receive(:candidate_version_from_remote)
+ .with(gem_dep, *source)
+ .and_return(Gem::Version.new(target_version))
+ expect(provider.candidate_version).to eq(target_version)
+ end
+ end
+
context "when the requested source is a file" do
let(:gem_name) { "chef-integration-test" }
let(:source) { CHEF_SPEC_DATA + "/gems/chef-integration-test-0.1.0.gem" }
@@ -566,18 +607,17 @@ describe Chef::Provider::Package::Rubygems do
current_resource
end
+ let(:version) { Gem::Version.new(candidate_version) }
+
before do
- version = Gem::Version.new(candidate_version)
- args = [gem_dep]
- args << source if source
- allow(provider.gem_env).to receive(:candidate_version_from_remote)
- .with(*args)
- .and_return(version)
+ expected_source = [ source ]
+ expected_source << Chef::Config[:rubygems_url] if include_default_source
+ allow(provider.gem_env).to receive(:candidate_version_from_remote).with(gem_dep, *expected_source.flatten.compact).and_return(version)
end
describe "in the current gem environment" do
it "installs the gem via the gems api when no explicit options are used" do
- expect(provider.gem_env).to receive(:install).with(gem_dep, sources: nil)
+ expect(provider.gem_env).to receive(:install).with(gem_dep, sources: [ Chef::Config[:rubygems_url] ])
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -586,7 +626,7 @@ describe Chef::Provider::Package::Rubygems do
let(:source) { "http://gems.example.org" }
it "installs the gem via the gems api" do
- expect(provider.gem_env).to receive(:install).with(gem_dep, sources: [source])
+ expect(provider.gem_env).to receive(:install).with(gem_dep, sources: [source, Chef::Config[:rubygems_url]])
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -617,7 +657,7 @@ describe Chef::Provider::Package::Rubygems do
it "installs the gem via the gems api, when the package has no file separator characters in it, but a matching file exists in cwd" do
allow(::File).to receive(:exist?).and_return(true)
new_resource.package_name("rspec-core")
- expect(provider.gem_env).to receive(:install).with(gem_dep, sources: nil)
+ expect(provider.gem_env).to receive(:install).with(gem_dep, sources: [ Chef::Config[:rubygems_url] ])
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -626,7 +666,20 @@ describe Chef::Provider::Package::Rubygems do
let(:options) { "-i /alt/install/location" }
it "installs the gem by shelling out when options are provided as a String" do
- expected = "gem install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" #{options}"
+ expected = "gem install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=https://www.rubygems.org #{options}"
+ expect(provider).to receive(:shell_out!).with(expected, env: nil, timeout: 900)
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+
+ context "when the Chef::Config[:rubygems_url] option is provided" do
+ let(:gem_binary) { "/foo/bar" }
+
+ it "installs the gem with rubygems.org as an added source" do
+ Chef::Config[:rubygems_url] = "https://mirror1"
+ expect(provider.gem_env).to receive(:candidate_version_from_remote).with(gem_dep, Chef::Config[:rubygems_url]).and_return(version)
+ expected = "#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=https://mirror1"
expect(provider).to receive(:shell_out!).with(expected, env: nil, timeout: 900)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
@@ -638,11 +691,47 @@ describe Chef::Provider::Package::Rubygems do
let(:gem_binary) { "/foo/bar" }
it "installs the gem with rubygems.org as an added source" do
- expected = "#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=#{source} --source=https://rubygems.org"
+ expected = "#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=#{source} --source=https://www.rubygems.org"
+ expect(provider).to receive(:shell_out!).with(expected, env: nil, timeout: 900)
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ context "with include_default_source false" do
+ let(:include_default_source) { false }
+
+ it "ignores the Chef::Config setting" do
+ Chef::Config[:rubygems_url] = "https://ignored"
+ expected = "#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=#{source}"
+ expect(provider).to receive(:shell_out!).with(expected, env: nil, timeout: 900)
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+ end
+
+ context "when the source is an array" do
+ let(:source) { [ "https://mirror1" , "https://mirror2" ] }
+ let(:gem_binary) { "/foo/bar" }
+
+ it "installs the gem with an array as an added source" do
+ expected = "#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=https://mirror1 --source=https://mirror2 --source=https://www.rubygems.org"
expect(provider).to receive(:shell_out!).with(expected, env: nil, timeout: 900)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
+
+ context "with include_default_source false" do
+ let(:include_default_source) { false }
+
+ it "ignores the Chef::Config setting" do
+ Chef::Config[:rubygems_url] = "https://ignored"
+ expected = "#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=https://mirror1 --source=https://mirror2"
+ expect(provider).to receive(:shell_out!).with(expected, env: nil, timeout: 900)
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
end
context "when we have cleared sources and an explict source is specified" do
@@ -651,7 +740,7 @@ describe Chef::Provider::Package::Rubygems do
it "installs the gem" do
new_resource.clear_sources(true)
- expected = "#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --clear-sources --source=#{source}"
+ expected = "#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --clear-sources --source=#{source} --source=https://www.rubygems.org"
expect(provider).to receive(:shell_out!).with(expected, env: nil, timeout: 900)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
@@ -663,7 +752,7 @@ describe Chef::Provider::Package::Rubygems do
let(:options) { "-i /alt/install/location" }
it "installs the gem by shelling out when options are provided but no version is given" do
- expected = "gem install rspec-core -q --no-rdoc --no-ri -v \"#{candidate_version}\" #{options}"
+ expected = "gem install rspec-core -q --no-rdoc --no-ri -v \"#{candidate_version}\" --source=https://www.rubygems.org #{options}"
expect(provider).to receive(:shell_out!).with(expected, env: nil, timeout: 900)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
@@ -674,7 +763,7 @@ describe Chef::Provider::Package::Rubygems do
let(:options) { { install_dir: "/alt/install/location" } }
it "installs the gem via the gems api when options are given as a Hash" do
- expect(provider.gem_env).to receive(:install).with(gem_dep, { sources: nil }.merge(options))
+ expect(provider.gem_env).to receive(:install).with(gem_dep, { sources: [ Chef::Config[:rubygems_url] ] }.merge(options))
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -684,7 +773,7 @@ describe Chef::Provider::Package::Rubygems do
let(:target_version) { "9000.0.2" }
it "installs the gem via the gems api" do
- expect(provider.gem_env).to receive(:install).with(gem_dep, sources: nil)
+ expect(provider.gem_env).to receive(:install).with(gem_dep, sources: [ Chef::Config[:rubygems_url] ] )
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -727,7 +816,7 @@ describe Chef::Provider::Package::Rubygems do
let(:gem_binary) { "/usr/weird/bin/gem" }
it "installs the gem by shelling out to gem install" do
- expect(provider).to receive(:shell_out!).with("#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\"", env: nil, timeout: 900)
+ expect(provider).to receive(:shell_out!).with("#{gem_binary} install rspec-core -q --no-rdoc --no-ri -v \"#{target_version}\" --source=https://www.rubygems.org", env: nil, timeout: 900)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
diff --git a/spec/unit/provider/package/windows/msi_spec.rb b/spec/unit/provider/package/windows/msi_spec.rb
index c8099c38d0..aa528ab90e 100644
--- a/spec/unit/provider/package/windows/msi_spec.rb
+++ b/spec/unit/provider/package/windows/msi_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Bryan McLellan <btm@loftninjas.org>
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/spec/unit/provider/package/yum_spec.rb b/spec/unit/provider/package/yum_spec.rb
index e0a5f8c862..e8eb830f65 100644
--- a/spec/unit/provider/package/yum_spec.rb
+++ b/spec/unit/provider/package/yum_spec.rb
@@ -278,31 +278,31 @@ describe Chef::Provider::Package::Yum do
end
it "should flush the cache if :before is true" do
- allow(@new_resource).to receive(:flush_cache).and_return({ :after => false, :before => true })
+ @new_resource.flush_cache({ :after => false, :before => true })
expect(@yum_cache).to receive(:reload).once
@provider.load_current_resource
end
it "should flush the cache if :before is false" do
- allow(@new_resource).to receive(:flush_cache).and_return({ :after => false, :before => false })
+ @new_resource.flush_cache({ :after => false, :before => false })
expect(@yum_cache).not_to receive(:reload)
@provider.load_current_resource
end
it "should detect --enablerepo or --disablerepo when passed among options, collect them preserving order and notify the yum cache" do
- allow(@new_resource).to receive(:options).and_return("--stuff --enablerepo=foo --otherthings --disablerepo=a,b,c --enablerepo=bar")
+ @new_resource.options("--stuff --enablerepo=foo --otherthings --disablerepo=a,b,c --enablerepo=bar")
expect(@yum_cache).to receive(:enable_extra_repo_control).with("--enablerepo=foo --disablerepo=a,b,c --enablerepo=bar")
@provider.load_current_resource
end
it "should let the yum cache know extra repos are disabled if --enablerepo or --disablerepo aren't among options" do
- allow(@new_resource).to receive(:options).and_return("--stuff --otherthings")
+ @new_resource.options("--stuff --otherthings")
expect(@yum_cache).to receive(:disable_extra_repo_control)
@provider.load_current_resource
end
it "should let the yum cache know extra repos are disabled if options aren't set" do
- allow(@new_resource).to receive(:options).and_return(nil)
+ @new_resource.options(nil)
expect(@yum_cache).to receive(:disable_extra_repo_control)
@provider.load_current_resource
end
@@ -558,7 +558,7 @@ describe Chef::Provider::Package::Yum do
it "installs the package with the options given in the resource" do
@provider.load_current_resource
allow(@provider).to receive(:candidate_version).and_return("11")
- allow(@new_resource).to receive(:options).and_return("--disablerepo epmd")
+ @new_resource.options("--disablerepo epmd")
allow(Chef::Provider::Package::Yum::RPMUtils).to receive(:rpmvercmp).and_return(-1)
expect(@provider).to receive(:yum_command).with(
"-d0 -e0 -y --disablerepo epmd install cups-11"
@@ -2261,7 +2261,7 @@ describe "Chef::Provider::Package::Yum - Multi" do
expect(@provider).to receive(:yum_command).with(
"-d0 -e0 -y --disablerepo epmd install cups-1.2.4-11.19.el5 vim-1.0"
)
- allow(@new_resource).to receive(:options).and_return("--disablerepo epmd")
+ @new_resource.options("--disablerepo epmd")
@provider.install_package(%w{cups vim}, ["1.2.4-11.19.el5", "1.0"])
end
diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb
index 7e6f204b64..f3c31dc730 100644
--- a/spec/unit/provider/package/zypper_spec.rb
+++ b/spec/unit/provider/package/zypper_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software, Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -111,23 +111,29 @@ describe Chef::Provider::Package::Zypper do
describe "install_package" do
it "should run zypper install with the package name and version" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(true)
shell_out_expectation!(
"zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
- it "should run zypper install without gpg checks" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
+
+ it "should run zypper install with gpg checks" do
shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
- it "should warn about gpg checks on zypper install" do
- expect(Chef::Log).to receive(:warn).with(
- /All packages will be installed without gpg signature checks/
+
+ 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"
)
+ provider.install_package(["emacs"], ["1.0"])
+ end
+
+ 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"
)
@@ -137,29 +143,20 @@ describe Chef::Provider::Package::Zypper do
describe "upgrade_package" do
it "should run zypper update with the package name and version" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(true)
shell_out_expectation!(
"zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
- it "should run zypper update without gpg checks" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
- shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
- )
- provider.upgrade_package(["emacs"], ["1.0"])
- end
- it "should warn about gpg checks on zypper upgrade" do
- expect(Chef::Log).to receive(:warn).with(
- /All packages will be installed without gpg signature checks/
- )
+ 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"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
- it "should run zypper upgrade without gpg checks" do
+ 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"
)
@@ -171,7 +168,6 @@ describe Chef::Provider::Package::Zypper do
context "when package version is not explicitly specified" do
it "should run zypper remove with the package name" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(true)
shell_out_expectation!(
"zypper", "--non-interactive", "remove", "emacs"
)
@@ -181,25 +177,22 @@ describe Chef::Provider::Package::Zypper do
context "when package version is explicitly specified" do
it "should run zypper remove with the package name" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(true)
shell_out_expectation!(
"zypper", "--non-interactive", "remove", "emacs=1.0"
)
provider.remove_package(["emacs"], ["1.0"])
end
it "should run zypper remove without gpg checks" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
+ new_resource.gpg_check false
shell_out_expectation!(
"zypper", "--non-interactive", "--no-gpg-checks", "remove", "emacs=1.0"
)
provider.remove_package(["emacs"], ["1.0"])
end
- it "should warn about gpg checks on zypper remove" do
- expect(Chef::Log).to receive(:warn).with(
- /All packages will be installed without gpg signature checks/
- )
+ it "should run zypper remove without gpg checks when the config is false" do
+ Chef::Config[:zypper_check_gpg] = false
shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "remove", "emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "remove", "emacs=1.0"
)
provider.remove_package(["emacs"], ["1.0"])
end
@@ -209,21 +202,19 @@ describe Chef::Provider::Package::Zypper do
describe "purge_package" do
it "should run remove with the name and version and --clean-deps" do
shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "remove", "--clean-deps", "emacs=1.0"
+ "zypper", "--non-interactive", "remove", "--clean-deps", "emacs=1.0"
)
provider.purge_package(["emacs"], ["1.0"])
end
it "should run zypper purge without gpg checks" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
+ new_resource.gpg_check false
shell_out_expectation!(
"zypper", "--non-interactive", "--no-gpg-checks", "remove", "--clean-deps", "emacs=1.0"
)
provider.purge_package(["emacs"], ["1.0"])
end
- it "should warn about gpg checks on zypper purge" do
- expect(Chef::Log).to receive(:warn).with(
- /All packages will be installed without gpg signature checks/
- )
+ it "should run zypper purge without gpg checks when the config is false" do
+ Chef::Config[:zypper_check_gpg] = false
shell_out_expectation!(
"zypper", "--non-interactive", "--no-gpg-checks", "remove", "--clean-deps", "emacs=1.0"
)
@@ -233,29 +224,13 @@ describe Chef::Provider::Package::Zypper do
describe "lock_package" do
it "should run zypper addlock with the package name" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(true)
shell_out_expectation!(
"zypper", "--non-interactive", "addlock", "emacs"
)
provider.lock_package(["emacs"], [nil])
end
it "should run zypper addlock without gpg checks" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
- shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "addlock", "emacs"
- )
- provider.lock_package(["emacs"], [nil])
- end
- it "should warn about gpg checks on zypper addlock" do
- expect(Chef::Log).to receive(:warn).with(
- /All packages will be installed without gpg signature checks/
- )
- shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "addlock", "emacs"
- )
- provider.lock_package(["emacs"], [nil])
- end
- it "should run zypper addlock without gpg checks" do
+ new_resource.gpg_check false
shell_out_expectation!(
"zypper", "--non-interactive", "--no-gpg-checks", "addlock", "emacs"
)
@@ -265,29 +240,13 @@ describe Chef::Provider::Package::Zypper do
describe "unlock_package" do
it "should run zypper removelock with the package name" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(true)
shell_out_expectation!(
"zypper", "--non-interactive", "removelock", "emacs"
)
provider.unlock_package(["emacs"], [nil])
end
it "should run zypper removelock without gpg checks" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
- shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "removelock", "emacs"
- )
- provider.unlock_package(["emacs"], [nil])
- end
- it "should warn about gpg checks on zypper removelock" do
- expect(Chef::Log).to receive(:warn).with(
- /All packages will be installed without gpg signature checks/
- )
- shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "removelock", "emacs"
- )
- provider.unlock_package(["emacs"], [nil])
- end
- it "should run zypper removelock without gpg checks" do
+ new_resource.gpg_check false
shell_out_expectation!(
"zypper", "--non-interactive", "--no-gpg-checks", "removelock", "emacs"
)
@@ -303,7 +262,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", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "-y", "emacs"
+ "zypper", "install", "--auto-agree-with-licenses", "-y", "emacs"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -312,7 +271,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", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "-y", "emacs"
+ "zypper", "install", "--auto-agree-with-licenses", "-y", "emacs"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
@@ -321,7 +280,7 @@ describe Chef::Provider::Package::Zypper do
describe "remove_package" do
it "should run zypper remove with the package name" do
shell_out_expectation!(
- "zypper", "--no-gpg-checks", "remove", "-y", "emacs"
+ "zypper", "remove", "-y", "emacs"
)
provider.remove_package(["emacs"], ["1.0"])
end
@@ -330,17 +289,15 @@ 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
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0", "vim=2.0"
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "emacs=1.0", "vim=2.0"
)
provider.install_package(%w{emacs vim}, ["1.0", "2.0"])
end
it "should remove an array of package names and versions" do
- allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
shell_out_expectation!(
- "zypper", "--non-interactive", "--no-gpg-checks", "remove", "emacs=1.0", "vim=2.0"
+ "zypper", "--non-interactive", "remove", "emacs=1.0", "vim=2.0"
)
provider.remove_package(%w{emacs vim}, ["1.0", "2.0"])
end
diff --git a/spec/unit/provider/service/debian_service_spec.rb b/spec/unit/provider/service/debian_service_spec.rb
index 799ed991a3..d944192755 100644
--- a/spec/unit/provider/service/debian_service_spec.rb
+++ b/spec/unit/provider/service/debian_service_spec.rb
@@ -59,11 +59,10 @@ describe Chef::Provider::Service::Debian do
/etc/rc6.d/K20chef
UPDATE_RC_D_SUCCESS
- @stdout = StringIO.new(result)
- @stderr = StringIO.new
- @status = double("Status", :exitstatus => 0, :stdout => @stdout)
+ @stdout = result
+ @stderr = ""
+ @status = double("Status", :exitstatus => 0, :stdout => @stdout, :stderr => @stderr)
allow(@provider).to receive(:shell_out!).and_return(@status)
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
end
it "says the service is enabled" do
@@ -80,13 +79,9 @@ describe Chef::Provider::Service::Debian do
context "when update-rc.d shows init isn't linked to rc*.d/" do
before do
allow(@provider).to receive(:assert_update_rcd_available)
- @status = double("Status", :exitstatus => 0)
- @stdout = StringIO.new(
- " Removing any system startup links for /etc/init.d/chef ...")
- @stderr = StringIO.new
- @status = double("Status", :exitstatus => 0, :stdout => @stdout)
+ @stdout = " Removing any system startup links for /etc/init.d/chef ..."
+ @status = double("Status", :exitstatus => 0, :stdout => @stdout, stderr: "")
allow(@provider).to receive(:shell_out!).and_return(@status)
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
end
it "says the service is disabled" do
@@ -102,11 +97,12 @@ describe Chef::Provider::Service::Debian do
context "when update-rc.d fails" do
before do
- @status = double("Status", :exitstatus => -1)
- allow(@provider).to receive(:popen4).and_return(@status)
+ @status = double("Status", exitstatus: -1, stdout: "", stderr: "")
+ allow(@provider).to receive(:shell_out!).and_return(@status)
end
it "raises an error" do
+ @provider.load_current_resource
@provider.define_resource_requirements
expect do
@provider.process_resource_requirements
@@ -198,11 +194,10 @@ insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop
before do
allow(@provider).to receive(:assert_update_rcd_available)
- @stdout = StringIO.new(expected_results["linked"]["stdout"])
- @stderr = StringIO.new(expected_results["linked"]["stderr"])
- @status = double("Status", :exitstatus => 0, :stdout => @stdout)
+ @stdout = expected_results["linked"]["stdout"]
+ @stderr = expected_results["linked"]["stderr"]
+ @status = double("Status", exitstatus: 0, stdout: @stdout, stderr: @stderr)
allow(@provider).to receive(:shell_out!).and_return(@status)
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
end
it "says the service is enabled" do
@@ -224,11 +219,10 @@ insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop
context "when update-rc.d shows init isn't linked to rc*.d/" do
before do
allow(@provider).to receive(:assert_update_rcd_available)
- @stdout = StringIO.new(expected_results["not linked"]["stdout"])
- @stderr = StringIO.new(expected_results["not linked"]["stderr"])
- @status = double("Status", :exitstatus => 0, :stdout => @stdout)
+ @stdout = expected_results["not linked"]["stdout"]
+ @stderr = expected_results["not linked"]["stderr"]
+ @status = double("Status", exitstatus: 0, stdout: @stdout, stderr: @stderr)
allow(@provider).to receive(:shell_out!).and_return(@status)
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
end
it "says the service is disabled" do
diff --git a/spec/unit/provider/service/upstart_service_spec.rb b/spec/unit/provider/service/upstart_service_spec.rb
index 0245dd038c..5c47259f52 100644
--- a/spec/unit/provider/service/upstart_service_spec.rb
+++ b/spec/unit/provider/service/upstart_service_spec.rb
@@ -71,12 +71,8 @@ describe Chef::Provider::Service::Upstart do
@current_resource = Chef::Resource::Service.new("rsyslog")
allow(Chef::Resource::Service).to receive(:new).and_return(@current_resource)
- @status = double("Status", :exitstatus => 0)
- allow(@provider).to receive(:popen4).and_return(@status)
- @stdin = StringIO.new
- @stdout = StringIO.new
- @stderr = StringIO.new
- @pid = double("PID")
+ @status = double("Status", exitstatus: 0, stdout: "", stderr: "")
+ allow(@provider).to receive(:shell_out).and_return(@status)
allow(::File).to receive(:exists?).and_return(true)
allow(::File).to receive(:open).and_return(true)
@@ -100,28 +96,25 @@ describe Chef::Provider::Service::Upstart do
end
it "should run '/sbin/status rsyslog'" do
- expect(@provider).to receive(:popen4).with("/sbin/status rsyslog").and_return(@status)
+ expect(@provider).to receive(:shell_out).with("/sbin/status rsyslog").and_return(@status)
@provider.load_current_resource
end
describe "when the status command uses the new format" do
it "should set running to true if the goal state is 'start'" do
- @stdout = StringIO.new("rsyslog start/running")
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ expect(@status).to receive(:stdout).and_return("rsyslog start/running")
@provider.load_current_resource
expect(@current_resource.running).to be_truthy
end
it "should set running to true if the goal state is 'start' but current state is not 'running'" do
- @stdout = StringIO.new("rsyslog start/starting")
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ expect(@status).to receive(:stdout).and_return("rsyslog start/starting")
@provider.load_current_resource
expect(@current_resource.running).to be_truthy
end
it "should set running to false if the goal state is 'stop'" do
- @stdout = StringIO.new("rsyslog stop/waiting")
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ expect(@status).to receive(:stdout).and_return("rsyslog stop/waiting")
@provider.load_current_resource
expect(@current_resource.running).to be_falsey
end
@@ -129,22 +122,19 @@ describe Chef::Provider::Service::Upstart do
describe "when the status command uses the new format with an instance" do
it "should set running to true if the goal state is 'start'" do
- @stdout = StringIO.new("rsyslog (test) start/running, process 100")
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ expect(@status).to receive(:stdout).and_return("rsyslog (test) start/running, process 100")
@provider.load_current_resource
expect(@current_resource.running).to be_truthy
end
it "should set running to true if the goal state is 'start' but current state is not 'running'" do
- @stdout = StringIO.new("rsyslog (test) start/starting, process 100")
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ expect(@status).to receive(:stdout).and_return("rsyslog (test) start/starting, process 100")
@provider.load_current_resource
expect(@current_resource.running).to be_truthy
end
it "should set running to false if the goal state is 'stop'" do
- @stdout = StringIO.new("rsyslog (test) stop/waiting, process 100")
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ expect(@status).to receive(:stdout).and_return("rsyslog (test) stop/waiting, process 100")
@provider.load_current_resource
expect(@current_resource.running).to be_falsey
end
@@ -152,22 +142,19 @@ describe Chef::Provider::Service::Upstart do
describe "when the status command uses the old format" do
it "should set running to true if the goal state is 'start'" do
- @stdout = StringIO.new("rsyslog (start) running, process 32225")
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ expect(@status).to receive(:stdout).and_return("rsyslog (start) running, process 32225")
@provider.load_current_resource
expect(@current_resource.running).to be_truthy
end
it "should set running to true if the goal state is 'start' but current state is not 'running'" do
- @stdout = StringIO.new("rsyslog (start) starting, process 32225")
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ expect(@status).to receive(:stdout).and_return("rsyslog (start) starting, process 32225")
@provider.load_current_resource
expect(@current_resource.running).to be_truthy
end
it "should set running to false if the goal state is 'stop'" do
- @stdout = StringIO.new("rsyslog (stop) waiting")
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ expect(@status).to receive(:stdout).and_return("rsyslog (stop) waiting")
@provider.load_current_resource
expect(@current_resource.running).to be_falsey
end
diff --git a/spec/unit/provider/subversion_spec.rb b/spec/unit/provider/subversion_spec.rb
index a4ab4ae42c..55d6dc5d24 100644
--- a/spec/unit/provider/subversion_spec.rb
+++ b/spec/unit/provider/subversion_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -43,7 +43,7 @@ describe Chef::Provider::Subversion do
ENV.update(@original_env)
end
- it "converts resource attributes to options for run_command and popen4" do
+ it "converts resource attributes to options for shell_out" do
expect(@provider.run_options).to eq({})
@resource.user "deployninja"
expect(@provider.run_options).to eq({ :user => "deployninja" })
diff --git a/spec/unit/provider/user/pw_spec.rb b/spec/unit/provider/user/pw_spec.rb
index 3637ce0b95..913b0ae0ab 100644
--- a/spec/unit/provider/user/pw_spec.rb
+++ b/spec/unit/provider/user/pw_spec.rb
@@ -155,11 +155,7 @@ describe Chef::Provider::User::Pw do
describe "when modifying the password" do
before(:each) do
@status = double("Status", exitstatus: 0)
- allow(@provider).to receive(:popen4).and_return(@status)
- @pid = nil
- @stdin = nil
- @stdout = nil
- @stderr = nil
+ allow(@provider).to receive(:shell_out!).and_return(@status)
end
describe "and the new password has not been specified" do
@@ -206,24 +202,16 @@ describe Chef::Provider::User::Pw do
end
it "should run pw usermod with the username and the option -H 0" do
- expect(@provider).to receive(:popen4).with("pw usermod adam -H 0", waitlast: true).and_return(@status)
+ expect(@provider).to receive(:shell_out!).with("pw usermod adam -H 0", { :input => "abracadabra" }).and_return(@status)
@provider.modify_password
end
- it "should send the new password to the stdin of pw usermod" do
- @stdin = StringIO.new
- allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
- @provider.modify_password
- expect(@stdin.string).to eq("abracadabra\n")
- end
-
it "should raise an exception if pw usermod fails" do
- expect(@status).to receive(:exitstatus).and_return(1)
- expect { @provider.modify_password }.to raise_error(Chef::Exceptions::User)
+ expect(@provider).to receive(:shell_out!).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ expect { @provider.modify_password }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
end
it "should not raise an exception if pw usermod succeeds" do
- expect(@status).to receive(:exitstatus).and_return(0)
expect { @provider.modify_password }.not_to raise_error
end
end
diff --git a/spec/unit/provider/windows_task_spec.rb b/spec/unit/provider/windows_task_spec.rb
new file mode 100644
index 0000000000..80038aa6db
--- /dev/null
+++ b/spec/unit/provider/windows_task_spec.rb
@@ -0,0 +1,392 @@
+#
+# Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
+# Copyright:: Copyright 2008-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"
+
+describe Chef::Provider::WindowsTask do
+ let(:new_resource) { Chef::Resource::WindowsTask.new("sample_task") }
+
+ let(:provider) do
+ node = Chef::Node.new
+ events = Chef::EventDispatch::Dispatcher.new
+ run_context = Chef::RunContext.new(node, {}, events)
+ Chef::Provider::WindowsTask.new(new_resource, run_context)
+ end
+
+ let(:task_hash) do
+ {
+ :"" => "",
+ :Folder => "\\",
+ :HostName => "NIMISHA-PC",
+ :TaskName => "\\sample_task",
+ :NextRunTime => "3/30/2017 2:42:00 PM",
+ :Status => "Ready",
+ :LogonMode => "Interactive/Background",
+ :LastRunTime => "3/30/2017 2:27:00 PM",
+ :LastResult => "1",
+ :Author => "Administrator",
+ :TaskToRun => "chef-client",
+ :StartIn => "N/A",
+ :Comment => "N/A",
+ :ScheduledTaskState => "Enabled",
+ :IdleTime => "Disabled",
+ :PowerManagement => "Stop On Battery Mode, No Start On Batteries",
+ :RunAsUser => "SYSTEM",
+ :DeleteTaskIfNotRescheduled => "Enabled",
+ :StopTaskIfRunsXHoursandXMins => "72:00:00",
+ :Schedule => "Scheduling data is not available in this format.",
+ :ScheduleType => "One Time Only, Minute",
+ :StartTime => "1:12:00 PM",
+ :StartDate => "3/30/2017",
+ :EndDate => "N/A",
+ :Days => "N/A",
+ :Months => "N/A",
+ :"Repeat:Every" => "0 Hour(s), 15 Minute(s)",
+ :"Repeat:Until:Time" => "None",
+ :"Repeat:Until:Duration" => "Disabled",
+ :"Repeat:StopIfStillRunning" => "Disabled",
+ :run_level => "HighestAvailable",
+ :repetition_interval => "PT15M",
+ :execution_time_limit => "PT72H",
+ }
+ end
+
+ let(:task_xml) do
+ "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\r\n<Task version=\"1.2\" xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">\r\r\n <RegistrationInfo>\r\r\n <Date>2017-03-31T15:34:44</Date>\r\r\n <Author>Administrator</Author>\r\r\n </RegistrationInfo>\r\r\n<Triggers>\r\r\n <TimeTrigger>\r\r\n <Repetition>\r\r\n <Interval>PT15M</Interval>\r\r\n <StopAtDurationEnd>false</StopAtDurationEnd>\r\r\n </Repetition>\r\r\n <StartBoundary>2017-03-31T15:34:00</StartBoundary>\r\r\n <Enabled>true</Enabled>\r\r\n </TimeTrigger>\r\r\n </Triggers>\r\r\n <Principals>\r\r\n <Principal id=\"Author\">\r\r\n <RunLevel>HighestAvailable</RunLevel>\r\r\n <UserId>S-1-5-18</UserId>\r\r\n </Principal>\r\r\n </Principals>\r\r\n <Settings>\r\r\n <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>\r\r\n <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>\r\r\n <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>\r\r\n <AllowHardTerminate>true</AllowHardTerminate>\r\r\n <StartWhenAvailable>false</StartWhenAvailable>\r\r\n <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>\r\r\n <IdleSettings>\r\r\n <Duration>PT10M</Duration>\r\r\n<WaitTimeout>PT1H</WaitTimeout>\r\r\n <StopOnIdleEnd>true</StopOnIdleEnd>\r\r\n <RestartOnIdle>false</RestartOnIdle>\r\r\n </IdleSettings>\r\r\n <AllowStartOnDemand>true</AllowStartOnDemand>\r\r\n <Enabled>true</Enabled>\r\r\n <Hidden>false</Hidden>\r\r\n<RunOnlyIfIdle>false</RunOnlyIfIdle>\r\r\n <WakeToRun>false</WakeToRun>\r\r\n <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>\r\r\n<Priority>7</Priority>\r\r\n </Settings>\r\r\n <Actions Context=\"Author\">\r\r\n <Exec>\r\r\n <Command>chef-client</Command>\r\r\n </Exec>\r\r\n </Actions>\r\r\n</Task>"
+ end
+
+ describe "#load_current_resource" do
+ it "returns a current_resource" do
+ allow(provider).to receive(:load_task_hash)
+ expect(provider.load_current_resource).to be_kind_of(Chef::Resource::WindowsTask)
+ end
+
+ context "if the given task name already exists" do
+ before do
+ allow(provider).to receive(:load_task_hash).and_return({ :TaskName => "\\sample_task" })
+ end
+
+ it "calls set_current_resource" do
+ expect(provider).to receive(:set_current_resource)
+ provider.load_current_resource
+ end
+ end
+
+ it "sets the attributes of current_resource" do
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ current_resource = provider.load_current_resource
+ expect(current_resource.exists).to be(true)
+ expect(current_resource.command).to eq("chef-client")
+ expect(current_resource.user).to eq("SYSTEM")
+ expect(current_resource.run_level).to eq(:highest)
+ expect(current_resource.frequency).to eq(:minute)
+ expect(current_resource.frequency_modifier).to eq(15)
+ expect(current_resource.execution_time_limit).to eq("PT72H")
+ expect(current_resource.enabled).to be(true)
+ end
+ end
+
+ describe "#action_create" do
+ it "doesn't create the same task if it's already existing" do
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ allow(provider).to receive(:task_need_update?).and_return(false)
+ provider.run_action(:create)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ context "when task is not existing" do
+ before do
+ allow(provider).to receive(:load_task_hash)
+ provider.load_current_resource
+ end
+
+ it "creates the task if it's not already existing" do
+ allow(provider).to receive(:task_need_update?).and_return(true)
+ expect(provider).to receive(:run_schtasks).with("CREATE", { "F" => "", "SC" => :hourly, "MO" => 1, "TR" => nil, "RU" => "SYSTEM" })
+ provider.run_action(:create)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "updates the task XML if random_delay is provided" do
+ new_resource.random_delay "20"
+ allow(provider).to receive(:task_need_update?).and_return(true)
+ expect(provider).to receive(:run_schtasks).with("CREATE", { "F" => "", "SC" => :hourly, "MO" => 1, "TR" => nil, "RU" => "SYSTEM" })
+ expect(provider).to receive(:update_task_xml)
+ provider.run_action(:create)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "updates the task XML if execution_time_limit is provided" do
+ new_resource.execution_time_limit "20"
+ allow(provider).to receive(:task_need_update?).and_return(true)
+ expect(provider).to receive(:run_schtasks).with("CREATE", { "F" => "", "SC" => :hourly, "MO" => 1, "TR" => nil, "RU" => "SYSTEM" })
+ expect(provider).to receive(:update_task_xml)
+ provider.run_action(:create)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+ end
+
+ describe "#action_run" do
+ it "does nothing if the task doesn't exist" do
+ allow(provider).to receive(:load_task_hash)
+ provider.load_current_resource
+ provider.run_action(:run)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ context "when the task exists" do
+ it "does nothing if the task is already running" do
+ task_hash[:Status] = "Running"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ provider.run_action(:run)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "runs the task" do
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ expect(provider).to receive(:run_schtasks).with("RUN")
+ provider.run_action(:run)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+ end
+
+ describe "#action_delete" do
+ it "deletes the task if it exists" do
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ expect(provider).to receive(:run_schtasks).with("DELETE", { "F" => "" })
+ provider.run_action(:delete)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "does nothing if the task doesn't exist" do
+ allow(provider).to receive(:load_task_hash)
+ provider.load_current_resource
+ provider.run_action(:delete)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+ end
+
+ describe "#action_end" do
+ it "does nothing if the task doesn't exist" do
+ allow(provider).to receive(:load_task_hash)
+ provider.load_current_resource
+ provider.run_action(:end)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ context "when the task exists" do
+ it "does nothing if the task is not running" do
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ provider.run_action(:end)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "ends the task if it's running" do
+ task_hash[:Status] = "Running"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ expect(provider).to receive(:run_schtasks).with("END")
+ provider.run_action(:end)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+ end
+
+ describe "#action_enable" do
+ it "raises error if the task doesn't exist" do
+ allow(provider).to receive(:load_task_hash)
+ provider.load_current_resource
+ expect { provider.run_action(:enable) }.to raise_error(Errno::ENOENT)
+ end
+
+ context "when the task exists" do
+ it "does nothing if the task is already enabled" do
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ provider.run_action(:enable)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "enables the task if it exists" do
+ task_hash[:ScheduledTaskState] = "Disabled"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ expect(provider).to receive(:run_schtasks).with("CHANGE", { "ENABLE" => "" })
+ provider.run_action(:enable)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+ end
+
+ describe "#action_disable" do
+ it "does nothing if the task doesn't exist" do
+ allow(provider).to receive(:load_task_hash)
+ provider.load_current_resource
+ provider.run_action(:disable)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ context "when the task exists" do
+ it "disables the task if it's enabled" do
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ expect(provider).to receive(:run_schtasks).with("CHANGE", { "DISABLE" => "" })
+ provider.run_action(:disable)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "does nothing if the task is already disabled" do
+ task_hash[:ScheduledTaskState] = "Disabled"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ provider.run_action(:disable)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+ end
+ end
+
+ describe "#run_schtasks" do
+ before do
+ @task_action = "CREATE"
+ @options = { "F" => "", "SC" => :minute, "MO" => 15, "TR" => "chef-client", "RU" => "SYSTEM", "RL" => "HIGHEST" }
+ @cmd = "schtasks /CREATE /TN \"sample_task\" /F /SC \"minute\" /MO \"15\" /TR \"chef-client\" /RU \"SYSTEM\" /RL \"HIGHEST\" "
+ end
+
+ it "forms the command properly from the given options" do
+ expect(provider).to receive(:shell_out!).with(@cmd, { :returns => [0] })
+ provider.send(:run_schtasks, @task_action, @options)
+ end
+ end
+
+ describe "#task_need_update?" do
+ context "when task doesn't exist" do
+ before do
+ allow(provider).to receive(:load_task_hash)
+ provider.load_current_resource
+ end
+
+ it "returns true" do
+ new_resource.command "chef-client"
+ expect(provider.send(:task_need_update?)).to be(true)
+ end
+ end
+
+ context "when the task exists" do
+ before do
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+
+ new_resource.command "chef-client"
+ new_resource.run_level :highest
+ new_resource.frequency :minute
+ new_resource.frequency_modifier 15
+ new_resource.user "SYSTEM"
+ new_resource.execution_time_limit "PT72H"
+ end
+
+ context "when no attributes are modified" do
+ it "returns false" do
+ expect(provider.send(:task_need_update?)).to be(false)
+ end
+ end
+
+ context "when frequency_modifier is updated" do
+ it "returns true" do
+ new_resource.frequency_modifier 25
+ expect(provider.send(:task_need_update?)).to be(true)
+ end
+ end
+
+ context "when months are updated" do
+ it "returns true" do
+ new_resource.months "JAN"
+ expect(provider.send(:task_need_update?)).to be(true)
+ end
+ end
+ end
+ end
+
+ describe "#update_task_xml" do
+ before do
+ new_resource.command "chef-client"
+ new_resource.run_level :highest
+ new_resource.frequency :minute
+ new_resource.frequency_modifier 15
+ new_resource.user "SYSTEM"
+ new_resource.random_delay "20"
+ end
+
+ it "does nothing if the task doesn't exist" do
+ task_xml = double("xml", :exitstatus => 1)
+ allow(provider).to receive(:powershell_out).and_return(task_xml)
+ output = provider.send(:update_task_xml, ["random_delay"])
+ expect(output).to be(nil)
+ end
+
+ it "updates the task XML if random_delay is passed" do
+ shell_out_obj = double("xml", :exitstatus => 0, :stdout => task_xml)
+ allow(provider).to receive(:powershell_out).and_return(shell_out_obj)
+ expect(::File).to receive(:join)
+ expect(::File).to receive(:open)
+ expect(::File).to receive(:delete)
+ expect(provider).to receive(:run_schtasks).twice
+ output = provider.send(:update_task_xml, ["random_delay"])
+ end
+ end
+
+ describe "#load_task_hash" do
+ it "returns false if the task doesn't exist" do
+ allow(provider).to receive_message_chain(:powershell_out, :stdout, :force_encoding).and_return("")
+ allow(provider).to receive(:load_task_xml)
+ expect(provider.send(:load_task_hash, "chef-client")).to be(false)
+ end
+
+ it "returns task hash if the task exists" do
+ powershell_output = "\r\nFolder: \\\r\nHostName: NIMISHA-PC\r\nTaskName: \\chef-client\r\n"
+ task_h = { :"" => "", :Folder => "\\", :HostName => "NIMISHA-PC", :TaskName => "\\chef-client" }
+ allow(provider).to receive_message_chain(:powershell_out, :stdout, :force_encoding).and_return(powershell_output)
+ allow(provider).to receive(:load_task_xml).with("chef-client")
+ expect(provider.send(:load_task_hash, "chef-client")).to eq(task_h)
+ end
+ end
+
+ describe "#frequency_modifier_allowed" do
+ it "returns true for frequency :hourly" do
+ new_resource.frequency :hourly
+ expect(provider.send(:frequency_modifier_allowed)).to be(true)
+ end
+
+ it "returns true for frequency :monthly if frequency_modifier is THIRD" do
+ new_resource.frequency :monthly
+ new_resource.frequency_modifier "THIRD"
+ expect(provider.send(:frequency_modifier_allowed)).to be(true)
+ end
+
+ it "returns false for frequency :once" do
+ new_resource.frequency :once
+ expect(provider.send(:frequency_modifier_allowed)).to be(false)
+ end
+ end
+end
diff --git a/spec/unit/provider_spec.rb b/spec/unit/provider_spec.rb
index f252d3177d..6eb2bb9303 100644
--- a/spec/unit/provider_spec.rb
+++ b/spec/unit/provider_spec.rb
@@ -195,4 +195,11 @@ describe Chef::Provider do
end
end
+ context "when using use_inline_resources" do
+ it "should log a deprecation warning" do
+ pending Chef::VERSION.start_with?("13.6")
+ expect(Chef).to receive(:deprecated).with(:use_inline_resources, kind_of(String))
+ Class.new(described_class) { use_inline_resources }
+ end
+ end
end
diff --git a/spec/unit/resource/conditional_spec.rb b/spec/unit/resource/conditional_spec.rb
index 135f798676..0219945936 100644
--- a/spec/unit/resource/conditional_spec.rb
+++ b/spec/unit/resource/conditional_spec.rb
@@ -92,7 +92,7 @@ describe Chef::Resource::Conditional do
describe "after running a command which timed out" do
before do
@conditional = Chef::Resource::Conditional.only_if(@parent_resource, "false")
- allow_any_instance_of(Chef::GuardInterpreter::DefaultGuardInterpreter).to receive(:shell_out).and_raise(Chef::Exceptions::CommandTimeout)
+ allow_any_instance_of(Chef::GuardInterpreter::DefaultGuardInterpreter).to receive(:shell_out_with_systems_locale).and_raise(Chef::Exceptions::CommandTimeout)
end
it "indicates that resource convergence should not continue" do
@@ -195,7 +195,7 @@ describe Chef::Resource::Conditional do
describe "after running a command which timed out" do
before do
@conditional = Chef::Resource::Conditional.not_if(@parent_resource, "false")
- allow_any_instance_of(Chef::GuardInterpreter::DefaultGuardInterpreter).to receive(:shell_out).and_raise(Chef::Exceptions::CommandTimeout)
+ allow_any_instance_of(Chef::GuardInterpreter::DefaultGuardInterpreter).to receive(:shell_out_with_systems_locale).and_raise(Chef::Exceptions::CommandTimeout)
end
it "indicates that resource convergence should continue" do
diff --git a/spec/unit/resource/package_spec.rb b/spec/unit/resource/package_spec.rb
index 8c00ea2bdd..84f92f26b5 100644
--- a/spec/unit/resource/package_spec.rb
+++ b/spec/unit/resource/package_spec.rb
@@ -61,7 +61,12 @@ describe Chef::Resource::Package do
it "should accept a string for the options" do
@resource.options "something"
- expect(@resource.options).to eql("something")
+ expect(@resource.options).to eql(["something"])
+ end
+
+ it "should split options" do
+ @resource.options "-a -b 'arg with spaces' -b \"and quotes\""
+ expect(@resource.options).to eql(["-a", "-b", "arg with spaces", "-b", "and quotes"])
end
describe "when it has a package_name and version" do
@@ -74,7 +79,7 @@ describe Chef::Resource::Package do
it "describes its state" do
state = @resource.state_for_resource_reporter
expect(state[:version]).to eq("10.9.8")
- expect(state[:options]).to eq("-al")
+ expect(state[:options]).to eq(["-al"])
end
it "returns the file path as its identity" do
diff --git a/spec/unit/resource/windows_task_spec.rb b/spec/unit/resource/windows_task_spec.rb
new file mode 100644
index 0000000000..fa2d458bbb
--- /dev/null
+++ b/spec/unit/resource/windows_task_spec.rb
@@ -0,0 +1,213 @@
+#
+# Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
+# Copyright:: Copyright 2008-2017, 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::WindowsTask do
+ let(:resource) { Chef::Resource::WindowsTask.new("sample_task") }
+
+ it "creates a new Chef::Resource::WindowsTask" do
+ expect(resource).to be_a_kind_of(Chef::Resource)
+ expect(resource).to be_a_instance_of(Chef::Resource::WindowsTask)
+ end
+
+ it "sets resource name as :windows_task" do
+ expect(resource.resource_name).to eql(:windows_task)
+ end
+
+ it "sets the task_name as it's name" do
+ expect(resource.task_name).to eql("sample_task")
+ end
+
+ it "sets the default action as :create" do
+ expect(resource.action).to eql(:create)
+ end
+
+ it "sets the default user as System" do
+ expect(resource.user).to eql("SYSTEM")
+ end
+
+ it "sets the default run_level as :limited" do
+ expect(resource.run_level).to eql(:limited)
+ end
+
+ it "sets the default force as false" do
+ expect(resource.force).to eql(false)
+ end
+
+ it "sets the default interactive_enabled as false" do
+ expect(resource.interactive_enabled).to eql(false)
+ end
+
+ it "sets the default frequency_modifier as 1" do
+ expect(resource.frequency_modifier).to eql(1)
+ end
+
+ it "sets the default frequency as :hourly" do
+ expect(resource.frequency).to eql(:hourly)
+ end
+
+ context "when random_delay is passed" do
+ it "raises error if frequency is `:once`" do
+ resource.frequency :once
+ resource.random_delay "20"
+ expect { resource.after_created }.to raise_error(Chef::Exceptions::ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly")
+ end
+
+ it "raises error for invalid random_delay" do
+ resource.frequency :monthly
+ resource.random_delay "xyz"
+ expect { resource.after_created }.to raise_error(Chef::Exceptions::ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as a String e.g. '60'.")
+ end
+
+ it "converts seconds into iso8601 format" do
+ resource.frequency :monthly
+ resource.random_delay "60"
+ resource.after_created
+ expect(resource.random_delay).to eq("PT60S")
+ end
+ end
+
+ context "when execution_time_limit is passed" do
+ it "sets the deafult value as PT72H" do
+ resource.after_created
+ expect(resource.execution_time_limit).to eq("PT72H")
+ end
+
+ it "raises error for invalid execution_time_limit" do
+ resource.execution_time_limit "abc"
+ expect { resource.after_created }.to raise_error(Chef::Exceptions::ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as a String e.g. '60'.")
+ end
+
+ it "converts seconds into iso8601 format" do
+ resource.execution_time_limit "60"
+ resource.after_created
+ expect(resource.execution_time_limit).to eq("PT60S")
+ end
+ end
+
+ context "#validate_start_time" do
+ it "raises error if start_time is nil" do
+ expect { resource.send(:validate_start_time, nil) }.to raise_error(Chef::Exceptions::ArgumentError, "`start_time` needs to be provided with `frequency :once`")
+ end
+ end
+
+ context "#validate_start_day" do
+ it "raise error if start_day is passed with frequency :on_logon" do
+ resource.frequency :on_logon
+ expect { resource.send(:validate_start_day, "Wed", :on_logon) }.to raise_error(Chef::Exceptions::ArgumentError, "`start_day` property is not supported with frequency: on_logon")
+ end
+ end
+
+ context "#validate_user_and_password" do
+ context "when password is not passed" do
+ it "raises error with non-system users" do
+ allow(resource).to receive(:use_password?).and_return(true)
+ expect { resource.send(:validate_user_and_password, "Testuser", nil) }.to raise_error("Can't specify a non-system user without a password!")
+ end
+ end
+ end
+
+ context "#validate_interactive_setting" do
+ it "raises error when interactive_enabled is passed without password" do
+ expect { resource.send(:validate_interactive_setting, true, nil) }.to raise_error("Please provide the password when attempting to set interactive/non-interactive.")
+ end
+ end
+
+ context "#validate_create_frequency_modifier" do
+ context "when frequency is :minute" do
+ it "raises error if frequency_modifier > 1439" do
+ expect { resource.send(:validate_create_frequency_modifier, :minute, 1500) }.to raise_error("frequency_modifier value 1500 is invalid. Valid values for :minute frequency are 1 - 1439.")
+ end
+ end
+
+ context "when frequency is :hourly" do
+ it "raises error if frequency_modifier > 23" do
+ expect { resource.send(:validate_create_frequency_modifier, :hourly, 24) }.to raise_error("frequency_modifier value 24 is invalid. Valid values for :hourly frequency are 1 - 23.")
+ end
+ end
+
+ context "when frequency is :daily" do
+ it "raises error if frequency_modifier > 365" do
+ expect { resource.send(:validate_create_frequency_modifier, :daily, 366) }.to raise_error("frequency_modifier value 366 is invalid. Valid values for :daily frequency are 1 - 365.")
+ end
+ end
+
+ context "when frequency is :weekly" do
+ it "raises error if frequency_modifier > 52" do
+ expect { resource.send(:validate_create_frequency_modifier, :weekly, 53) }.to raise_error("frequency_modifier value 53 is invalid. Valid values for :weekly frequency are 1 - 52.")
+ end
+ end
+
+ context "when frequency is :monthly" do
+ it "raises error if frequency_modifier > 12" do
+ expect { resource.send(:validate_create_frequency_modifier, :monthly, 14) }.to raise_error("frequency_modifier value 14 is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'.")
+ end
+
+ it "raises error if frequency_modifier is invalid" do
+ expect { resource.send(:validate_create_frequency_modifier, :monthly, "abc") }.to raise_error("frequency_modifier value abc is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'.")
+ end
+ end
+ end
+
+ context "#validate_create_day" do
+ it "raises error if frequency is not :weekly" do
+ expect { resource.send(:validate_create_day, "Mon", :monthly) }.to raise_error("day attribute is only valid for tasks that run weekly")
+ end
+
+ it "accepts a valid single day" do
+ expect { resource.send(:validate_create_day, "Mon", :weekly) }.not_to raise_error
+ end
+
+ it "accepts a comma separated list of valid days" do
+ expect { resource.send(:validate_create_day, "Mon, tue, THU", :weekly) }.not_to raise_error
+ end
+
+ it "raises error for invalid day value" do
+ expect { resource.send(:validate_create_day, "xyz", :weekly) }.to raise_error("day attribute invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma.")
+ end
+ end
+
+ context "#validate_create_months" do
+ it "raises error if frequency is not :monthly" do
+ expect { resource.send(:validate_create_months, "Jan", :once) }.to raise_error("months attribute is only valid for tasks that run monthly")
+ end
+
+ it "accepts a valid single month" do
+ expect { resource.send(:validate_create_months, "Feb", :monthly) }.not_to raise_error
+ end
+
+ it "accepts a comma separated list of valid months" do
+ expect { resource.send(:validate_create_months, "Jan, mar, AUG", :monthly) }.not_to raise_error
+ end
+
+ it "raises error for invalid month value" do
+ expect { resource.send(:validate_create_months, "xyz", :monthly) }.to raise_error("months attribute invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma.")
+ end
+ end
+
+ context "#validate_idle_time" do
+ it "raises error if frequency is not :on_idle" do
+ expect { resource.send(:validate_idle_time, 5, :hourly) }.to raise_error("idle_time attribute is only valid for tasks that run on_idle")
+ end
+
+ it "raises error if idle_time > 999" do
+ expect { resource.send(:validate_idle_time, 1000, :on_idle) }.to raise_error("idle_time value 1000 is invalid. Valid values for :on_idle frequency are 1 - 999.")
+ end
+ end
+end
diff --git a/spec/unit/resource_collection/resource_set_spec.rb b/spec/unit/resource_collection/resource_set_spec.rb
index ecf3e2707f..9955bc2bea 100644
--- a/spec/unit/resource_collection/resource_set_spec.rb
+++ b/spec/unit/resource_collection/resource_set_spec.rb
@@ -27,6 +27,7 @@ describe Chef::ResourceCollection::ResourceSet do
let(:zen_master) { Chef::Resource::ZenMaster.new(zen_master_name) }
let(:zen_master2) { Chef::Resource::ZenMaster.new(zen_master2_name) }
let(:zen_follower) { Chef::Resource::ZenFollower.new(zen_follower_name) }
+ let(:zen_array) { Chef::Resource::ZenMaster.new( [ zen_master_name, zen_master2_name ]) }
describe "initialize" do
it "should return a Chef::ResourceSet" do
@@ -113,13 +114,27 @@ describe Chef::ResourceCollection::ResourceSet do
end
it "should find resources by strings of zen_master[a,b]" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
collection.insert_as(zen_master)
collection.insert_as(zen_master2)
check_by_names(collection.find("zen_master[#{zen_master_name},#{zen_master2_name}]"),
zen_master_name, zen_master2_name)
end
+ it "should find array names" do
+ collection.insert_as(zen_array)
+ expect(collection.find("zen_master[#{zen_master_name}, #{zen_master2_name}]")).to eql(zen_array)
+ end
+
+ it "should favor array names over multi resource syntax" do
+ collection.insert_as(zen_master)
+ collection.insert_as(zen_master2)
+ collection.insert_as(zen_array)
+ expect(collection.find("zen_master[#{zen_master_name}, #{zen_master2_name}]")).to eql(zen_array)
+ end
+
it "should find resources by strings of zen_master[a,b] with custom names" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
collection.insert_as(zen_master, :zzz, "name1")
collection.insert_as(zen_master2, :zzz, "name2")
check_by_names(collection.find("zzz[name1,name2]"),
@@ -134,6 +149,7 @@ describe Chef::ResourceCollection::ResourceSet do
end
it "should find resources of multiple types by strings of zen_master[a] with custom names" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
collection.insert_as(zen_master, :zzz, "name1")
collection.insert_as(zen_master2, :zzz, "name2")
collection.insert_as(zen_follower, :yyy, "name3")
diff --git a/spec/unit/resource_collection_spec.rb b/spec/unit/resource_collection_spec.rb
index 76038e51b9..c696572b13 100644
--- a/spec/unit/resource_collection_spec.rb
+++ b/spec/unit/resource_collection_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -219,6 +219,7 @@ describe Chef::ResourceCollection do
end
it "should find resources by strings of zen_master[a,b]" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
load_up_resources
results = rc.resources("zen_master[monkey,dog]")
expect(results.length).to eql(2)
diff --git a/spec/unit/run_context/cookbook_compiler_spec.rb b/spec/unit/run_context/cookbook_compiler_spec.rb
index feb39615b6..e93088cd5f 100644
--- a/spec/unit/run_context/cookbook_compiler_spec.rb
+++ b/spec/unit/run_context/cookbook_compiler_spec.rb
@@ -163,9 +163,7 @@ describe Chef::RunContext::CookbookCompiler do
describe "event dispatch" do
let(:recipe) { "dependency1::default" }
let(:recipe_path) do
- File.expand_path("../../../data/run_context/cookbooks/dependency1/recipes/default.rb", __FILE__).tap do |path|
- path.gsub!(File::SEPARATOR, File::ALT_SEPARATOR) if File::ALT_SEPARATOR
- end
+ File.expand_path("../../../data/run_context/cookbooks/dependency1/recipes/default.rb", __FILE__)
end
before do
node.run_list(recipe)
diff --git a/spec/unit/search/query_spec.rb b/spec/unit/search/query_spec.rb
index 0837410b3c..95221870d5 100644
--- a/spec/unit/search/query_spec.rb
+++ b/spec/unit/search/query_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -237,6 +237,27 @@ describe Chef::Search::Query do
end
end
+ it "fuzzifies node searches when fuzz is set" do
+ expect(rest).to receive(:get).with(
+ "search/node?q=tags:*free.messi*%20OR%20roles:*free.messi*%20OR%20fqdn:*free.messi*%20OR%20addresses:*free.messi*%20OR%20policy_name:*free.messi*%20OR%20policy_group:*free.messi*&start=0"
+ ).and_return(response)
+ query.search(:node, "free.messi", fuzz: true)
+ end
+
+ it "does not fuzzify node searches when fuzz is not set" do
+ expect(rest).to receive(:get).with(
+ "search/node?q=free.messi&start=0"
+ ).and_return(response)
+ query.search(:node, "free.messi")
+ end
+
+ it "does not fuzzify client searches" do
+ expect(rest).to receive(:get).with(
+ "search/client?q=messi&start=0"
+ ).and_return(response)
+ query.search(:client, "messi", fuzz: true)
+ end
+
context "when :filter_result is provided as a result" do
include_context "filtered search" do
let(:filter_key) { :filter_result }
diff --git a/tasks/bin/bundle-platform b/tasks/bin/bundle-platform
deleted file mode 100755
index aaf433c98d..0000000000
--- a/tasks/bin/bundle-platform
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env ruby
-require_relative "bundler_patch"
-
-platforms = ARGV.shift
-platforms = platforms.split(" ").map { |p| Gem::Platform.new(p) }
-Gem::Platform.instance_eval { @local = platforms.last }
-old_platforms = Gem.platforms
-Gem.platforms = platforms
-puts "bundle-platform set Gem.platforms to #{Gem.platforms.map { |p| p.to_s }} (was #{old_platforms.map { |p| p.to_s }})"
-
-desired_version = ARGV.shift.delete("_")
-
-# The rest of this is a normal bundler binstub
-require "pathname"
-ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile",
- Pathname.new(__FILE__).realpath)
-
-require "rubygems"
-
-load Gem.bin_path("bundler", "bundle", desired_version)
diff --git a/tasks/bin/bundle-platform.bat b/tasks/bin/bundle-platform.bat
deleted file mode 100644
index d193eb0c05..0000000000
--- a/tasks/bin/bundle-platform.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@ECHO OFF
-ruby "%~dpn0" %*
diff --git a/tasks/bin/bundler_patch.rb b/tasks/bin/bundler_patch.rb
deleted file mode 100644
index 5665e44eca..0000000000
--- a/tasks/bin/bundler_patch.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# This is a temporary monkey patch to address https://github.com/bundler/bundler/issues/4896
-# the heart of the fix is line #18 with the addition of:
-# && (possibility.activated - existing_node.payload.activated).empty?
-# This ensures we do not mis linux platform gems in some scenarios like ffi in kitchen-test.
-# There is a permanent fix to bundler (See https://github.com/bundler/bundler/pull/4836) which
-# is due to ship in v1.14. Once we adopt that version, we can remove this file
-
-require "bundler"
-require "bundler/vendor/molinillo/lib/molinillo/resolution"
-
-module Bundler::Molinillo
- class Resolver
- # A specific resolution from a given {Resolver}
- class Resolution
- def attempt_to_activate
- debug(depth) { "Attempting to activate " + possibility.to_s }
- existing_node = activated.vertex_named(name)
- if existing_node.payload && (possibility.activated - existing_node.payload.activated).empty?
- debug(depth) { "Found existing spec (#{existing_node.payload})" }
- attempt_to_activate_existing_spec(existing_node)
- else
- attempt_to_activate_new_spec
- end
- end
- end
- end
-end
diff --git a/tasks/bin/gem-version-diff b/tasks/bin/gem-version-diff
deleted file mode 100755
index 617402d4e6..0000000000
--- a/tasks/bin/gem-version-diff
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env ruby
-
-require_relative "../../version_policy"
-
-old_version, new_version = ARGV[0..1]
-
-require "set"
-ENV["BUNDLE_WITHOUT"] = INSTALL_WITHOUT_GROUPS.join(":")
-relevant_gems = Set.new
-`bundle list`.each_line do |line|
- next unless line =~ /^ \* (\S+)/
- relevant_gems.add($1)
-end
-
-old_gems = {}
-old_file = `git show #{old_version}:Gemfile.lock`
-old_file.each_line do |line|
- next unless line =~ /^ (\S+) \(([^\)]+)\)$/
- next unless relevant_gems.include?($1)
- old_gems[$1] = $2
-end
-
-new_gems = {}
-new_file = `git show #{new_version}:Gemfile.lock`
-new_file.each_line do |line|
- next unless line =~ /^ (\S+) \(([^\)]+)\)$/
- next unless relevant_gems.include?($1)
- new_gems[$1] = $2
-end
-
-modified_gems = (old_gems.keys & new_gems.keys).sort.select { |name| new_gems[name] != old_gems[name] }.map { |name| "#{name} - #{new_gems[name]} (was #{old_gems[name]})" }
-removed_gems = (old_gems.keys - new_gems.keys).sort.map { |name| "#{name} - #{old_gems[name]}" }
-added_gems = (new_gems.keys - old_gems.keys).sort.map { |name| "#{name} - #{new_gems[name]}" }
-
-puts "MODIFIED:\n#{modified_gems.join("\n")}" if modified_gems.any?
-puts "\nADDED:\n#{added_gems.join("\n")}" if added_gems.any?
-puts "\nREMOVED:\n#{removed_gems.join("\n")}" if removed_gems.any?
diff --git a/tasks/bundle.rb b/tasks/bundle.rb
index f530515786..0e9b207932 100644
--- a/tasks/bundle.rb
+++ b/tasks/bundle.rb
@@ -15,7 +15,6 @@
# limitations under the License.
#
-require_relative "bundle_util"
require_relative "../version_policy"
require "fileutils"
@@ -23,33 +22,22 @@ desc "Tasks to work with the main Gemfile and Gemfile.<platform>"
namespace :bundle do
desc "Update Gemfile.lock and all Gemfile.<platform>.locks (or one or more gems via bundle:update gem1 gem2 ...)."
task :update, [:args] do |t, rake_args|
- extend BundleUtil
args = rake_args[:args] || ""
- with_bundle_unfrozen do
- puts ""
- puts "-------------------------------------------------------------------"
- puts "Updating Gemfile.lock ..."
- puts "-------------------------------------------------------------------"
- bundle "update #{args}"
- platforms.each do |platform|
- bundle "update #{args}", platform: platform
- end
+ Bundler.with_clean_env do
+ sh "bundle config --local frozen '0'"
+ sh "bundle update #{args}"
+ sh "bundle config --local frozen '1'"
end
end
desc "Conservatively update Gemfile.lock and all Gemfile.<platform>.locks"
task :install, [:args] do |t, rake_args|
- extend BundleUtil
args = rake_args[:args] || ""
- with_bundle_unfrozen do
- puts ""
- puts "-------------------------------------------------------------------"
- puts "Updating Gemfile.lock ..."
- puts "-------------------------------------------------------------------"
- bundle "install #{args}"
- platforms.each do |platform|
- bundle "lock", platform: platform
- end
+ args = rake_args[:args] || ""
+ Bundler.with_clean_env do
+ sh "bundle config --local frozen '0'"
+ sh "bundle install #{args}"
+ sh "bundle config --local frozen '1'"
end
end
@@ -82,20 +70,12 @@ namespace :bundle do
end
end
-desc "Run bundle with arbitrary args against the given platform; e.g. rake bundle[show]. No platform to run against the main bundle; bundle[show,windows] to run the windows one; bundle[show,*] to run against all non-default platforms."
-task :bundle, [:args, :platform] do |t, rake_args|
- extend BundleUtil
+desc "Run bundle with arbitrary args"
+task :bundle, [:args] do |t, rake_args|
args = rake_args[:args] || ""
- platform = rake_args[:platform]
- with_bundle_unfrozen do
- if platform == "*"
- platforms.each do |platform|
- bundle args, platform: platform
- end
- elsif platform
- bundle args, platform: platform
- else
- bundle args
- end
+ Bundler.with_clean_env do
+ sh "bundle config --local frozen '0'"
+ sh "bundle #{args}"
+ sh "bundle config --local frozen '1'"
end
end
diff --git a/tasks/bundle_util.rb b/tasks/bundle_util.rb
deleted file mode 100644
index 67647dd4f0..0000000000
--- a/tasks/bundle_util.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-require "bundler"
-require "shellwords"
-
-module BundleUtil
- PLATFORMS = { "windows" => %w{ruby x86-mingw32} }
-
- def project_root
- File.expand_path("../..", __FILE__)
- end
-
- def bundle_platform
- File.join(project_root, "tasks", "bin", "bundle-platform")
- end
-
- # Parse the output of "bundle outdated" and get the list of gems that
- # were outdated
- def parse_bundle_outdated(bundle_outdated_output)
- result = []
- bundle_outdated_output.each_line do |line|
- if line =~ /^\s*\* (.+) \(newest ([^,]+), installed ([^,)])*/
- gem_name, newest_version, installed_version = $1, $2, $3
- result << [ line, gem_name ]
- end
- end
- result
- end
-
- def with_bundle_unfrozen(cwd: nil, leave_frozen: false)
- bundle "config --delete frozen", cwd: cwd
- begin
- yield
- ensure
- bundle "config --local frozen 1", cwd: cwd unless leave_frozen
- end
- end
-
- # Run bundle-platform with the given ruby platform(s)
- def bundle(args, gemfile: nil, platform: nil, cwd: nil, extract_output: false, delete_gemfile_lock: false)
- args = args.split(/\s+/)
- if cwd
- prefix = "[#{cwd}] "
- end
- cwd = File.expand_path(cwd || ".", project_root)
- Bundler.with_clean_env do
- Dir.chdir(cwd) do
- gemfile ||= "Gemfile"
- gemfile = File.expand_path(gemfile, cwd)
- raise "No platform #{platform} (supported: #{PLATFORMS.keys.join(", ")})" if platform && !PLATFORMS[platform]
-
- # First delete the gemfile.lock
- if delete_gemfile_lock
- if File.exist?("#{gemfile}.lock")
- puts "Deleting #{gemfile}.lock ..."
- File.delete("#{gemfile}.lock")
- end
- end
-
- # Run the bundle command
- ruby_platforms = platform ? PLATFORMS[platform].join(" ") : "ruby"
- cmd = Shellwords.join([
- Gem.ruby,
- "-S",
- bundle_platform,
- ruby_platforms,
- "_#{desired_bundler_version}_",
- *args,
- ])
- puts "#{prefix}#{Shellwords.join(["bundle", *args])}#{platform ? " for #{platform} platform" : ""}:"
- with_gemfile(gemfile) do
- puts "#{prefix}BUNDLE_GEMFILE=#{gemfile}"
- puts "#{prefix}> #{cmd}"
- if extract_output
- `#{cmd}`
- else
- unless system(bundle_platform, ruby_platforms, "_#{desired_bundler_version}_", *args)
- raise "#{bundle_platform} failed: exit code #{$?}"
- end
- end
- end
- end
- end
- end
-
- def with_gemfile(gemfile)
- old_gemfile = ENV["BUNDLE_GEMFILE"]
- ENV["BUNDLE_GEMFILE"] = gemfile
- begin
- yield
- ensure
- if old_gemfile
- ENV["BUNDLE_GEMFILE"] = old_gemfile
- else
- ENV.delete("BUNDLE_GEMFILE")
- end
- end
- end
-
- def platforms
- PLATFORMS.keys
- end
-
- def desired_bundler_version
- @desired_bundler_version ||= begin
- omnibus_overrides = File.join(project_root, "omnibus_overrides.rb")
- File.readlines(omnibus_overrides).each do |line|
- return $1 if line =~ /^override :bundler, version: "(.+)"$/
- end
- end
- end
-end
diff --git a/tasks/dependencies.rb b/tasks/dependencies.rb
index 6b836b747e..2118644b12 100644
--- a/tasks/dependencies.rb
+++ b/tasks/dependencies.rb
@@ -15,7 +15,6 @@
# limitations under the License.
#
-require_relative "bundle_util"
require_relative "bundle"
require_relative "../version_policy"