summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Batye <gbatye@fb.com>2017-02-15 10:41:35 -0800
committerGregory Batye <gbatye@fb.com>2017-02-15 10:41:35 -0800
commitc0f2f0e22d6bd8c14e39dc8950a751fccaa30910 (patch)
tree82abcf214c0d9cb9e9aa22ca10279624a4ff09bf
parente8b452c2e9cdfadebe22e1ed2d6cb94b2d4f5a0a (diff)
parentac07b819652edb10b0421c12c16cce13e6e70f23 (diff)
downloadchef-c0f2f0e22d6bd8c14e39dc8950a751fccaa30910.tar.gz
Merge remote-tracking branch 'chef/master' into fix_osx_profile
-rw-r--r--.bundle/config2
-rw-r--r--.github/ISSUE_TEMPLATE.md3
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml116
-rw-r--r--CHANGELOG.md104
-rw-r--r--Dockerfile11
-rw-r--r--Gemfile11
-rw-r--r--Gemfile.lock252
-rw-r--r--HISTORY.md90
-rw-r--r--MAINTAINERS.md55
-rw-r--r--MAINTAINERS.toml65
-rw-r--r--README.md51
-rw-r--r--RELEASE_NOTES.md193
-rw-r--r--Rakefile26
-rw-r--r--VERSION2
-rw-r--r--acceptance/Gemfile8
-rw-r--r--acceptance/Gemfile.lock170
-rw-r--r--appveyor.yml9
-rw-r--r--chef-config/lib/chef-config/config.rb45
-rw-r--r--chef-config/lib/chef-config/mixin/fuzzy_hostname_matcher.rb8
-rw-r--r--chef-config/lib/chef-config/path_helper.rb2
-rw-r--r--chef-config/lib/chef-config/version.rb2
-rw-r--r--chef-config/spec/unit/config_spec.rb46
-rw-r--r--chef-universal-mingw32.gemspec5
-rw-r--r--chef.gemspec12
-rwxr-xr-xci/bundle_install.sh3
-rwxr-xr-xci/dependency_update.sh2
-rwxr-xr-xci/version_bump.sh4
-rw-r--r--distro/common/html/knife_environment.html12
-rw-r--r--distro/common/man/man1/knife-environment.120
-rw-r--r--distro/common/markdown/man1/knife-configure.mkd5
-rw-r--r--distro/powershell/chef/chef.psm1163
-rw-r--r--habitat/default.toml11
-rw-r--r--habitat/hooks/run8
-rw-r--r--habitat/plan.sh100
-rw-r--r--kitchen-tests/.kitchen.travis.yml20
-rw-r--r--kitchen-tests/Berksfile2
-rw-r--r--kitchen-tests/Berksfile.lock64
-rw-r--r--kitchen-tests/Gemfile3
-rw-r--r--kitchen-tests/Gemfile.lock118
-rw-r--r--kitchen-tests/cookbooks/audit_test/Berksfile2
-rw-r--r--kitchen-tests/cookbooks/base/Berksfile2
-rw-r--r--kitchen-tests/cookbooks/base/attributes/default.rb3
-rw-r--r--kitchen-tests/cookbooks/base/recipes/default.rb2
-rw-r--r--kitchen-tests/cookbooks/base/recipes/packages.rb5
-rw-r--r--kitchen-tests/cookbooks/webapp/Berksfile2
-rw-r--r--kitchen-tests/test/integration/webapp/default_spec.rb4
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/already_exists_error.rb2
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/cookbook_frozen_error.rb2
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/default_environment_cannot_be_modified_error.rb2
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/file_system_error.rb2
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/must_delete_recursively_error.rb2
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/not_found_error.rb2
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/operation_failed_error.rb2
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/operation_not_allowed_error.rb2
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb2
-rw-r--r--lib-backcompat/chef/chef_fs/file_system/repository/file_system_root_dir.rb2
-rw-r--r--lib/chef/api_client.rb20
-rw-r--r--lib/chef/api_client_v1.rb20
-rw-r--r--lib/chef/application.rb11
-rw-r--r--lib/chef/application/apply.rb18
-rw-r--r--lib/chef/application/client.rb2
-rw-r--r--lib/chef/application/exit_code.rb12
-rw-r--r--lib/chef/application/knife.rb4
-rw-r--r--lib/chef/application/windows_service.rb59
-rw-r--r--lib/chef/application/windows_service_manager.rb12
-rw-r--r--lib/chef/audit/audit_event_proxy.rb4
-rw-r--r--lib/chef/audit/control_group_data.rb2
-rw-r--r--lib/chef/chef_class.rb21
-rw-r--r--lib/chef/chef_fs/chef_fs_data_store.rb14
-rw-r--r--lib/chef/chef_fs/command_line.rb33
-rw-r--r--lib/chef/chef_fs/data_handler/client_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/container_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/cookbook_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/environment_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/group_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/node_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/organization_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/role_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/user_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/file_pattern.rb4
-rw-r--r--lib/chef/chef_fs/file_system.rb2
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb11
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb18
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/data_bags_dir.rb18
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/nodes_dir.rb22
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/policies_dir.rb58
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/policy_group_entry.rb2
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb56
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/rest_list_entry.rb51
-rw-r--r--lib/chef/chef_fs/file_system/memory/memory_file.rb2
-rw-r--r--lib/chef/chef_fs/file_system/multiplexed_dir.rb22
-rw-r--r--lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_dir.rb22
-rw-r--r--lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb22
-rw-r--r--lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb15
-rw-r--r--lib/chef/chef_fs/file_system/repository/cookbooks_dir.rb2
-rw-r--r--lib/chef/chef_fs/file_system/repository/nodes_dir.rb22
-rw-r--r--lib/chef/chef_fs/parallelizer.rb20
-rw-r--r--lib/chef/client.rb1
-rw-r--r--lib/chef/cookbook/chefignore.rb2
-rw-r--r--lib/chef/cookbook/cookbook_version_loader.rb58
-rw-r--r--lib/chef/cookbook/metadata.rb60
-rw-r--r--lib/chef/cookbook/syntax_check.rb2
-rw-r--r--lib/chef/cookbook_loader.rb2
-rw-r--r--lib/chef/cookbook_version.rb14
-rw-r--r--lib/chef/data_bag.rb4
-rw-r--r--lib/chef/data_bag_item.rb8
-rw-r--r--lib/chef/data_collector.rb75
-rw-r--r--lib/chef/data_collector/messages.rb15
-rw-r--r--lib/chef/data_collector/messages/helpers.rb6
-rw-r--r--lib/chef/decorator.rb2
-rw-r--r--lib/chef/decorator/unchain.rb4
-rw-r--r--lib/chef/deprecated.rb250
-rw-r--r--lib/chef/deprecation/provider/remote_directory.rb2
-rw-r--r--lib/chef/deprecation/warnings.rb7
-rw-r--r--lib/chef/dsl/audit.rb4
-rw-r--r--lib/chef/dsl/declare_resource.rb2
-rw-r--r--lib/chef/dsl/method_missing.rb4
-rw-r--r--lib/chef/dsl/platform_introspection.rb64
-rw-r--r--lib/chef/dsl/reboot_pending.rb2
-rw-r--r--lib/chef/dsl/resources.rb16
-rw-r--r--lib/chef/encrypted_data_bag_item.rb4
-rw-r--r--lib/chef/encrypted_data_bag_item/decryptor.rb4
-rw-r--r--lib/chef/environment.rb24
-rw-r--r--lib/chef/event_loggers/windows_eventlog.rb2
-rw-r--r--lib/chef/exceptions.rb17
-rw-r--r--lib/chef/file_access_control/unix.rb38
-rw-r--r--lib/chef/file_access_control/windows.rb2
-rw-r--r--lib/chef/formatters/base.rb12
-rw-r--r--lib/chef/formatters/doc.rb17
-rw-r--r--lib/chef/formatters/error_description.rb2
-rw-r--r--lib/chef/formatters/error_inspectors/api_error_formatting.rb9
-rw-r--r--lib/chef/formatters/error_mapper.rb12
-rw-r--r--lib/chef/http/api_versions.rb50
-rw-r--r--lib/chef/http/basic_client.rb2
-rw-r--r--lib/chef/http/json_input.rb4
-rw-r--r--lib/chef/http/validate_content_length.rb4
-rw-r--r--lib/chef/json_compat.rb16
-rw-r--r--lib/chef/key.rb12
-rw-r--r--lib/chef/knife.rb10
-rw-r--r--lib/chef/knife/client_delete.rb21
-rw-r--r--lib/chef/knife/configure.rb2
-rw-r--r--lib/chef/knife/cookbook_site_install.rb6
-rw-r--r--lib/chef/knife/core/bootstrap_context.rb26
-rw-r--r--lib/chef/knife/core/cookbook_scm_repo.rb6
-rw-r--r--lib/chef/knife/core/gem_glob_loader.rb2
-rw-r--r--lib/chef/knife/core/status_presenter.rb2
-rw-r--r--lib/chef/knife/core/subcommand_loader.rb6
-rw-r--r--lib/chef/knife/core/ui.rb48
-rw-r--r--lib/chef/knife/data_bag_secret_options.rb2
-rw-r--r--lib/chef/knife/deps.rb66
-rw-r--r--lib/chef/knife/help.rb2
-rw-r--r--lib/chef/knife/list.rb2
-rw-r--r--lib/chef/knife/node_delete.rb12
-rw-r--r--lib/chef/knife/search.rb4
-rw-r--r--lib/chef/knife/ssh.rb64
-rw-r--r--lib/chef/knife/ssl_check.rb2
-rw-r--r--lib/chef/knife/user_delete.rb2
-rw-r--r--lib/chef/log.rb2
-rw-r--r--lib/chef/mash.rb2
-rw-r--r--lib/chef/mixin/command.rb5
-rw-r--r--lib/chef/mixin/create_path.rb8
-rw-r--r--lib/chef/mixin/deep_merge.rb2
-rw-r--r--lib/chef/mixin/deprecation.rb14
-rw-r--r--lib/chef/mixin/from_file.rb4
-rw-r--r--lib/chef/mixin/get_source_from_package.rb4
-rw-r--r--lib/chef/mixin/notifying_block.rb16
-rw-r--r--lib/chef/mixin/params_validate.rb6
-rw-r--r--lib/chef/mixin/powershell_type_coercions.rb38
-rw-r--r--lib/chef/mixin/securable.rb2
-rw-r--r--lib/chef/mixin/shell_out.rb87
-rw-r--r--lib/chef/mixin/unformatter.rb4
-rw-r--r--lib/chef/mixin/uris.rb10
-rw-r--r--lib/chef/mixin/versioned_api.rb69
-rw-r--r--lib/chef/mixin/which.rb41
-rw-r--r--lib/chef/mixin/wide_string.rb2
-rw-r--r--lib/chef/mixin/windows_architecture_helper.rb4
-rw-r--r--lib/chef/mixin/xml_escape.rb8
-rw-r--r--lib/chef/monkey_patches/net-ssh-multi.rb141
-rw-r--r--lib/chef/monkey_patches/webrick-utils.rb2
-rw-r--r--lib/chef/node.rb22
-rw-r--r--lib/chef/node/attribute.rb24
-rw-r--r--lib/chef/node/common_api.rb12
-rw-r--r--lib/chef/node/mixin/state_tracking.rb7
-rw-r--r--lib/chef/node_map.rb24
-rw-r--r--lib/chef/org.rb24
-rw-r--r--lib/chef/platform/handler_map.rb40
-rw-r--r--lib/chef/platform/provider_handler_map.rb4
-rw-r--r--lib/chef/platform/provider_mapping.rb9
-rw-r--r--lib/chef/platform/query_helpers.rb2
-rw-r--r--lib/chef/platform/rebooter.rb4
-rw-r--r--lib/chef/platform/resource_handler_map.rb4
-rw-r--r--lib/chef/policy_builder/expand_node_object.rb2
-rw-r--r--lib/chef/policy_builder/policyfile.rb1
-rw-r--r--lib/chef/property.rb41
-rw-r--r--lib/chef/provider.rb8
-rw-r--r--lib/chef/provider/deploy/revision.rb8
-rw-r--r--lib/chef/provider/directory.rb2
-rw-r--r--lib/chef/provider/dsc_resource.rb18
-rw-r--r--lib/chef/provider/env/windows.rb4
-rw-r--r--lib/chef/provider/execute.rb7
-rw-r--r--lib/chef/provider/file.rb10
-rw-r--r--lib/chef/provider/git.rb2
-rw-r--r--lib/chef/provider/group.rb87
-rw-r--r--lib/chef/provider/group/aix.rb31
-rw-r--r--lib/chef/provider/group/dscl.rb89
-rw-r--r--lib/chef/provider/group/gpasswd.rb14
-rw-r--r--lib/chef/provider/group/groupadd.rb63
-rw-r--r--lib/chef/provider/group/groupmod.rb57
-rw-r--r--lib/chef/provider/group/pw.rb59
-rw-r--r--lib/chef/provider/group/suse.rb18
-rw-r--r--lib/chef/provider/group/usermod.rb21
-rw-r--r--lib/chef/provider/group/windows.rb38
-rw-r--r--lib/chef/provider/ifconfig.rb115
-rw-r--r--lib/chef/provider/ifconfig/aix.rb51
-rw-r--r--lib/chef/provider/ifconfig/debian.rb45
-rw-r--r--lib/chef/provider/ifconfig/redhat.rb24
-rw-r--r--lib/chef/provider/launchd.rb4
-rw-r--r--lib/chef/provider/link.rb6
-rw-r--r--lib/chef/provider/mount.rb2
-rw-r--r--lib/chef/provider/mount/aix.rb4
-rw-r--r--lib/chef/provider/mount/mount.rb8
-rw-r--r--lib/chef/provider/ohai.rb8
-rw-r--r--lib/chef/provider/osx_profile.rb14
-rw-r--r--lib/chef/provider/package.rb151
-rw-r--r--lib/chef/provider/package/aix.rb107
-rw-r--r--lib/chef/provider/package/apt.rb28
-rw-r--r--lib/chef/provider/package/cab.rb69
-rw-r--r--lib/chef/provider/package/chocolatey.rb25
-rw-r--r--lib/chef/provider/package/dnf.rb185
-rw-r--r--lib/chef/provider/package/dnf/dnf_helper.py91
-rw-r--r--lib/chef/provider/package/dnf/python_helper.rb157
-rw-r--r--lib/chef/provider/package/dnf/version.rb56
-rw-r--r--lib/chef/provider/package/dpkg.rb17
-rw-r--r--lib/chef/provider/package/easy_install.rb48
-rw-r--r--lib/chef/provider/package/freebsd/base.rb20
-rw-r--r--lib/chef/provider/package/freebsd/pkg.rb30
-rw-r--r--lib/chef/provider/package/freebsd/pkgng.rb30
-rw-r--r--lib/chef/provider/package/freebsd/port.rb14
-rw-r--r--lib/chef/provider/package/homebrew.rb21
-rw-r--r--lib/chef/provider/package/ips.rb41
-rw-r--r--lib/chef/provider/package/macports.rb46
-rw-r--r--lib/chef/provider/package/msu.rb162
-rw-r--r--lib/chef/provider/package/openbsd.rb47
-rw-r--r--lib/chef/provider/package/pacman.rb32
-rw-r--r--lib/chef/provider/package/paludis.rb53
-rw-r--r--lib/chef/provider/package/portage.rb44
-rw-r--r--lib/chef/provider/package/powershell.rb114
-rw-r--r--lib/chef/provider/package/rpm.rb50
-rw-r--r--lib/chef/provider/package/rubygems.rb120
-rw-r--r--lib/chef/provider/package/smartos.rb32
-rw-r--r--lib/chef/provider/package/solaris.rb88
-rw-r--r--lib/chef/provider/package/windows.rb8
-rw-r--r--lib/chef/provider/package/windows/exe.rb12
-rw-r--r--lib/chef/provider/package/windows/msi.rb12
-rw-r--r--lib/chef/provider/package/yum.rb586
-rw-r--r--lib/chef/provider/package/yum/rpm_utils.rb68
-rw-r--r--lib/chef/provider/package/yum/yum_cache.rb24
-rw-r--r--lib/chef/provider/package/zypper.rb24
-rw-r--r--lib/chef/provider/powershell_script.rb10
-rw-r--r--lib/chef/provider/route.rb370
-rw-r--r--lib/chef/provider/script.rb44
-rw-r--r--lib/chef/provider/service.rb2
-rw-r--r--lib/chef/provider/service/arch.rb4
-rw-r--r--lib/chef/provider/service/freebsd.rb2
-rw-r--r--lib/chef/provider/service/gentoo.rb4
-rw-r--r--lib/chef/provider/service/insserv.rb4
-rw-r--r--lib/chef/provider/service/macosx.rb4
-rw-r--r--lib/chef/provider/service/openbsd.rb2
-rw-r--r--lib/chef/provider/service/redhat.rb4
-rw-r--r--lib/chef/provider/service/solaris.rb2
-rw-r--r--lib/chef/provider/service/systemd.rb2
-rw-r--r--lib/chef/provider/support/yum_repo.erb13
-rw-r--r--lib/chef/provider/systemd_unit.rb2
-rw-r--r--lib/chef/provider/user.rb37
-rw-r--r--lib/chef/provider/user/aix.rb47
-rw-r--r--lib/chef/provider/user/dscl.rb109
-rw-r--r--lib/chef/provider/user/linux.rb29
-rw-r--r--lib/chef/provider/user/pw.rb56
-rw-r--r--lib/chef/provider/user/solaris.rb23
-rw-r--r--lib/chef/provider/user/useradd.rb42
-rw-r--r--lib/chef/provider/user/windows.rb41
-rw-r--r--lib/chef/provider_resolver.rb10
-rw-r--r--lib/chef/providers.rb3
-rw-r--r--lib/chef/resource.rb58
-rw-r--r--lib/chef/resource/apt_repository.rb1
-rw-r--r--lib/chef/resource/apt_update.rb2
-rw-r--r--lib/chef/resource/chef_gem.rb7
-rw-r--r--lib/chef/resource/chocolatey_package.rb1
-rw-r--r--lib/chef/resource/dnf_package.rb67
-rw-r--r--lib/chef/resource/dsc_resource.rb10
-rw-r--r--lib/chef/resource/execute.rb76
-rw-r--r--lib/chef/resource/file/verification.rb10
-rw-r--r--lib/chef/resource/file/verification/systemd_unit.rb67
-rw-r--r--lib/chef/resource/freebsd_package.rb2
-rw-r--r--lib/chef/resource/gem_package.rb2
-rw-r--r--lib/chef/resource/launchd.rb70
-rw-r--r--lib/chef/resource/mount.rb2
-rw-r--r--lib/chef/resource/msu_package.rb47
-rw-r--r--lib/chef/resource/ohai.rb30
-rw-r--r--lib/chef/resource/package.rb4
-rw-r--r--lib/chef/resource/powershell_package.rb41
-rw-r--r--lib/chef/resource/reboot.rb2
-rw-r--r--lib/chef/resource/registry_key.rb2
-rw-r--r--lib/chef/resource/user.rb4
-rw-r--r--lib/chef/resource/yum_package.rb47
-rw-r--r--lib/chef/resource/yum_repository.rb3
-rw-r--r--lib/chef/resource_builder.rb8
-rw-r--r--lib/chef/resource_collection/resource_collection_serialization.rb6
-rw-r--r--lib/chef/resource_collection/resource_set.rb4
-rw-r--r--lib/chef/resource_reporter.rb13
-rw-r--r--lib/chef/resource_resolver.rb5
-rw-r--r--lib/chef/resources.rb3
-rw-r--r--lib/chef/rest.rb2
-rw-r--r--lib/chef/role.rb2
-rw-r--r--lib/chef/run_context.rb12
-rw-r--r--lib/chef/run_list/run_list_item.rb2
-rw-r--r--lib/chef/run_list/versioned_recipe_list.rb12
-rw-r--r--lib/chef/scan_access_control.rb8
-rw-r--r--lib/chef/server_api.rb2
-rw-r--r--lib/chef/server_api_versions.rb40
-rw-r--r--lib/chef/shell.rb2
-rw-r--r--lib/chef/shell/ext.rb10
-rw-r--r--lib/chef/shell/shell_session.rb2
-rw-r--r--lib/chef/user.rb26
-rw-r--r--lib/chef/user_v1.rb22
-rw-r--r--lib/chef/util/diff.rb2
-rw-r--r--lib/chef/util/dsc/lcm_output_parser.rb2
-rw-r--r--lib/chef/util/dsc/resource_store.rb2
-rw-r--r--lib/chef/util/selinux.rb2
-rw-r--r--lib/chef/util/windows/net_group.rb48
-rw-r--r--lib/chef/util/windows/net_use.rb18
-rw-r--r--lib/chef/util/windows/net_user.rb28
-rw-r--r--lib/chef/util/windows/volume.rb24
-rw-r--r--lib/chef/version.rb2
-rw-r--r--lib/chef/version_class.rb2
-rw-r--r--lib/chef/win32/api.rb10
-rw-r--r--lib/chef/win32/api/file.rb56
-rw-r--r--lib/chef/win32/api/installer.rb4
-rw-r--r--lib/chef/win32/api/security.rb24
-rw-r--r--lib/chef/win32/file.rb10
-rw-r--r--lib/chef/win32/memory.rb2
-rw-r--r--lib/chef/win32/registry.rb18
-rw-r--r--lib/chef/win32/security.rb8
-rw-r--r--lib/chef/win32/security/acl.rb4
-rw-r--r--lib/chef/win32/security/sid.rb4
-rw-r--r--lib/chef/win32/unicode.rb4
-rw-r--r--lib/chef/win32/version.rb2
-rw-r--r--omnibus/Gemfile.lock78
-rw-r--r--omnibus/config/projects/angrychef.rb2
-rw-r--r--omnibus/config/projects/chef.rb5
-rw-r--r--omnibus/config/software/chef-gem-bcrypt_pbkdf-ruby.rb10
-rw-r--r--omnibus/config/software/chef-gem-rbnacl-libsodium.rb10
-rw-r--r--omnibus/config/software/chef.rb4
-rw-r--r--omnibus/files/chef/build-chef.rb2
-rw-r--r--omnibus/omnibus.rb1
-rw-r--r--omnibus/resources/chef/msi/localization-en-us.wxl.erb12
-rw-r--r--omnibus/resources/chef/msi/source.wxs.erb147
-rw-r--r--omnibus_overrides.rb2
-rw-r--r--spec/data/prefer_metadata_json/metadata.json51
-rw-r--r--spec/data/prefer_metadata_json/metadata.rb6
-rw-r--r--spec/data/prefer_metadata_json/recipes/default.rb0
-rw-r--r--spec/data/sample_msu1.xml10
-rw-r--r--spec/data/sample_msu2.xml14
-rw-r--r--spec/data/sample_msu3.xml16
-rw-r--r--spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.i686.rpmbin0 -> 6530 bytes
-rw-r--r--spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.src.rpmbin0 -> 6331 bytes
-rw-r--r--spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.x86_64.rpmbin0 -> 6498 bytes
-rw-r--r--spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.i686.rpmbin0 -> 6526 bytes
-rw-r--r--spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.src.rpmbin0 -> 6331 bytes
-rw-r--r--spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpmbin0 -> 6494 bytes
-rw-r--r--spec/functional/assets/yumrepo/repodata/313329137b55fd333b2dc66394a6661a2befa6cc535d8460d92a4a78a9c581f0-primary.sqlite.bz2bin0 -> 2460 bytes
-rw-r--r--spec/functional/assets/yumrepo/repodata/31ac4db5d5ac593728fcc26aef82b7b93c4cc4dbec843786b1845b939b658553-other.xml.gzbin0 -> 413 bytes
-rw-r--r--spec/functional/assets/yumrepo/repodata/4ac40fa3c6728c1401318e2e20a997436624e83dcf7a5f952b851ef422637773-filelists.sqlite.bz2bin0 -> 1131 bytes
-rw-r--r--spec/functional/assets/yumrepo/repodata/66391e53f0510b98b3f0b79f40ba1048026d9a1ef20905d9c40ba6f5411f3243-primary.xml.gzbin0 -> 859 bytes
-rw-r--r--spec/functional/assets/yumrepo/repodata/8b34697595fcc87928e12d24644dda9462c3857bd932861e28bc77ae1f31be16-filelists.xml.gzbin0 -> 419 bytes
-rw-r--r--spec/functional/assets/yumrepo/repodata/b97cca3fe14bcf06c52be4449b6108f7731239ff221111dcce8aada5467f60dc-other.sqlite.bz2bin0 -> 967 bytes
-rw-r--r--spec/functional/assets/yumrepo/repodata/repomd.xml55
-rw-r--r--spec/functional/knife/ssh_spec.rb10
-rw-r--r--spec/functional/rebooter_spec.rb6
-rw-r--r--spec/functional/resource/batch_spec.rb6
-rw-r--r--spec/functional/resource/dnf_package_spec.rb686
-rw-r--r--spec/functional/resource/dsc_script_spec.rb7
-rw-r--r--spec/functional/resource/execute_spec.rb17
-rw-r--r--spec/functional/resource/link_spec.rb63
-rw-r--r--spec/functional/resource/msu_package_spec.rb84
-rw-r--r--spec/functional/resource/registry_spec.rb6
-rw-r--r--spec/functional/resource/user/dscl_spec.rb6
-rw-r--r--spec/functional/resource/user/useradd_spec.rb11
-rw-r--r--spec/integration/client/client_spec.rb33
-rw-r--r--spec/integration/knife/chef_repo_path_spec.rb4
-rw-r--r--spec/integration/recipes/recipe_dsl_spec.rb119
-rw-r--r--spec/integration/recipes/resource_load_spec.rb6
-rw-r--r--spec/integration/solo/solo_spec.rb50
-rw-r--r--spec/spec_helper.rb15
-rw-r--r--spec/support/chef_helpers.rb12
-rw-r--r--spec/support/lib/chef/provider/snakeoil.rb1
-rw-r--r--spec/support/lib/chef/resource/cat.rb1
-rw-r--r--spec/support/lib/chef/resource/one_two_three_four.rb1
-rw-r--r--spec/support/lib/chef/resource/openldap_includer.rb2
-rw-r--r--spec/support/lib/chef/resource/with_state.rb2
-rw-r--r--spec/support/lib/chef/resource/zen_master.rb1
-rw-r--r--spec/support/platform_helpers.rb30
-rw-r--r--spec/support/platforms/prof/gc.rb10
-rw-r--r--spec/support/shared/context/client.rb2
-rw-r--r--spec/support/shared/functional/execute_resource.rb150
-rw-r--r--spec/support/shared/functional/windows_script.rb78
-rw-r--r--spec/support/shared/unit/execute_resource.rb37
-rw-r--r--spec/support/shared/unit/provider/file.rb10
-rw-r--r--spec/unit/application/exit_code_spec.rb18
-rw-r--r--spec/unit/cookbook/cookbook_version_loader_spec.rb9
-rw-r--r--spec/unit/cookbook/metadata_spec.rb6
-rw-r--r--spec/unit/cookbook/syntax_check_spec.rb10
-rw-r--r--spec/unit/data_collector/messages/helpers_spec.rb7
-rw-r--r--spec/unit/data_collector_spec.rb78
-rw-r--r--spec/unit/decorator/lazy_spec.rb2
-rw-r--r--spec/unit/deprecated_spec.rb59
-rw-r--r--spec/unit/deprecation_spec.rb9
-rw-r--r--spec/unit/environment_spec.rb2
-rw-r--r--spec/unit/handler_spec.rb4
-rw-r--r--spec/unit/http/api_versions_spec.rb69
-rw-r--r--spec/unit/knife/client_delete_spec.rb16
-rw-r--r--spec/unit/knife/configure_spec.rb2
-rw-r--r--spec/unit/knife/cookbook_metadata_spec.rb229
-rw-r--r--spec/unit/knife/core/bootstrap_context_spec.rb60
-rw-r--r--spec/unit/knife/node_delete_spec.rb29
-rw-r--r--spec/unit/knife/ssh_spec.rb70
-rw-r--r--spec/unit/lwrp_spec.rb7
-rw-r--r--spec/unit/mixin/shell_out_spec.rb1
-rw-r--r--spec/unit/mixin/versioned_api_spec.rb107
-rw-r--r--spec/unit/mixin/which.rb160
-rw-r--r--spec/unit/node/immutable_collections_spec.rb5
-rw-r--r--spec/unit/node/vivid_mash_spec.rb11
-rw-r--r--spec/unit/node_spec.rb29
-rw-r--r--spec/unit/platform_spec.rb28
-rw-r--r--spec/unit/provider/deploy_spec.rb2
-rw-r--r--spec/unit/provider/directory_spec.rb10
-rw-r--r--spec/unit/provider/dsc_resource_spec.rb175
-rw-r--r--spec/unit/provider/execute_spec.rb1
-rw-r--r--spec/unit/provider/group/dscl_spec.rb58
-rw-r--r--spec/unit/provider/group/gpasswd_spec.rb20
-rw-r--r--spec/unit/provider/group/groupadd_spec.rb61
-rw-r--r--spec/unit/provider/group/groupmod_spec.rb32
-rw-r--r--spec/unit/provider/group/pw_spec.rb22
-rw-r--r--spec/unit/provider/group/suse_spec.rb10
-rw-r--r--spec/unit/provider/group/usermod_spec.rb30
-rw-r--r--spec/unit/provider/ifconfig/aix_spec.rb28
-rw-r--r--spec/unit/provider/ifconfig/debian_spec.rb32
-rw-r--r--spec/unit/provider/ifconfig/redhat_spec.rb8
-rw-r--r--spec/unit/provider/ifconfig_spec.rb37
-rw-r--r--spec/unit/provider/launchd_spec.rb88
-rw-r--r--spec/unit/provider/mount/mount_spec.rb2
-rw-r--r--spec/unit/provider/mount_spec.rb7
-rw-r--r--spec/unit/provider/package/aix_spec.rb44
-rw-r--r--spec/unit/provider/package/apt_spec.rb54
-rw-r--r--spec/unit/provider/package/cab_spec.rb64
-rw-r--r--spec/unit/provider/package/chocolatey_spec.rb42
-rw-r--r--spec/unit/provider/package/dnf/python_helper_spec.rb29
-rw-r--r--spec/unit/provider/package/dpkg_spec.rb32
-rw-r--r--spec/unit/provider/package/easy_install_spec.rb48
-rw-r--r--spec/unit/provider/package/freebsd/pkg_spec.rb30
-rw-r--r--spec/unit/provider/package/freebsd/pkgng_spec.rb18
-rw-r--r--spec/unit/provider/package/freebsd/port_spec.rb18
-rw-r--r--spec/unit/provider/package/homebrew_spec.rb18
-rw-r--r--spec/unit/provider/package/ips_spec.rb68
-rw-r--r--spec/unit/provider/package/macports_spec.rb20
-rw-r--r--spec/unit/provider/package/msu_spec.rb283
-rw-r--r--spec/unit/provider/package/openbsd_spec.rb20
-rw-r--r--spec/unit/provider/package/pacman_spec.rb12
-rw-r--r--spec/unit/provider/package/paludis_spec.rb14
-rw-r--r--spec/unit/provider/package/portage_spec.rb13
-rw-r--r--spec/unit/provider/package/powershell_spec.rb337
-rw-r--r--spec/unit/provider/package/rpm_spec.rb46
-rw-r--r--spec/unit/provider/package/rubygems_spec.rb76
-rw-r--r--spec/unit/provider/package/solaris_spec.rb30
-rw-r--r--spec/unit/provider/package/windows_spec.rb3
-rw-r--r--spec/unit/provider/package/yum_spec.rb94
-rw-r--r--spec/unit/provider/package/zypper_spec.rb68
-rw-r--r--spec/unit/provider/package_spec.rb8
-rw-r--r--spec/unit/provider/remote_file/sftp_spec.rb6
-rw-r--r--spec/unit/provider/route_spec.rb50
-rw-r--r--spec/unit/provider/script_spec.rb55
-rw-r--r--spec/unit/provider/service/macosx_spec.rb2
-rw-r--r--spec/unit/provider/subversion_spec.rb9
-rw-r--r--spec/unit/provider/user/dscl_spec.rb111
-rw-r--r--spec/unit/provider/user/linux_spec.rb16
-rw-r--r--spec/unit/provider/user/pw_spec.rb48
-rw-r--r--spec/unit/provider/user/windows_spec.rb8
-rw-r--r--spec/unit/provider/user_spec.rb40
-rw-r--r--spec/unit/provider_resolver_spec.rb1
-rw-r--r--spec/unit/recipe_spec.rb54
-rw-r--r--spec/unit/resource/apt_update_spec.rb42
-rw-r--r--spec/unit/resource/chocolatey_package_spec.rb12
-rw-r--r--spec/unit/resource/dnf_package_spec.rb99
-rw-r--r--spec/unit/resource/dsc_resource_spec.rb6
-rw-r--r--spec/unit/resource/execute_spec.rb214
-rw-r--r--spec/unit/resource/file/verification/systemd_unit_spec.rb103
-rw-r--r--spec/unit/resource/file/verification_spec.rb2
-rw-r--r--spec/unit/resource/freebsd_package_spec.rb4
-rw-r--r--spec/unit/resource/mount_spec.rb3
-rw-r--r--spec/unit/resource/msu_package_spec.rb49
-rw-r--r--spec/unit/resource/ohai_spec.rb2
-rw-r--r--spec/unit/resource/package_spec.rb5
-rw-r--r--spec/unit/resource/powershell_package_spec.rb68
-rw-r--r--spec/unit/resource/remote_file_spec.rb4
-rw-r--r--spec/unit/resource/yum_package_spec.rb63
-rw-r--r--spec/unit/resource_reporter_spec.rb32
-rw-r--r--spec/unit/resource_spec.rb20
-rw-r--r--spec/unit/run_status_spec.rb2
-rw-r--r--spec/unit/runner_spec.rb1
-rw-r--r--spec/unit/server_api_versions_spec.rb44
-rw-r--r--spec/unit/util/selinux_spec.rb17
-rw-r--r--spec/unit/win32/error_spec.rb67
-rw-r--r--spec/unit/win32/security_spec.rb66
-rw-r--r--tasks/announce.rb58
-rwxr-xr-xtasks/bin/bundle-platform2
-rw-r--r--tasks/changelog.rb45
-rw-r--r--tasks/dependencies.rb24
-rw-r--r--tasks/gemfile_util.rb4
-rw-r--r--tasks/templates/prerelease.md.erb26
-rw-r--r--tasks/templates/release.md.erb26
-rw-r--r--version_policy.rb5
523 files changed, 11257 insertions, 4891 deletions
diff --git a/.bundle/config b/.bundle/config
index 7544be9dd7..e520135ebc 100644
--- a/.bundle/config
+++ b/.bundle/config
@@ -1,2 +1,2 @@
---
-BUNDLE_FROZEN: '1'
+BUNDLE_FROZEN: "1"
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 562e43e797..d6ca06036d 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -30,6 +30,7 @@ Please include the stacktrace.out output or link to a gist of it, if there is on
This issue tracker is for the code contained within this repo -- `chef-client`, base `knife` functionality (not
plugins), `chef-apply`, `chef-solo`, `chef-client -z`, etc.
-* [Server issues](https://github.com/chef/chef-server/issues/new)
+* Requests for new or alternative functionality should be made to [feedback.chef.io](https://feedback.chef.io/forums/301644-chef-product-feedback/category/110832-chef-client)
+* [Chef Server issues](https://github.com/chef/chef-server/issues/new)
* [ChefDK issues](https://github.com/chef/chef-dk/issues/new)
* Cookbook Issues (see the https://github.com/chef-cookbooks repos or search [Supermarket](https://supermarket.chef.io) or GitHub/Google)
diff --git a/.gitignore b/.gitignore
index 144369156c..03d53ceb10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@ tags
*/tags
*~
.chef
+results
# You should check in your Gemfile.lock in applications, and not in gems
external_tests/*.lock
diff --git a/.travis.yml b/.travis.yml
index 0c2ae0b153..ed7fffc22b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,11 @@ cache: bundler
# Early warning system to catch if Rubygems breaks something
before_install:
- gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2)
+ - gem --version
+ - gem uninstall bundler -a -x
+ - rvm @global do gem uninstall bundler -a -x
- gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
+ - bundle --version
- rm -f .bundle/config
bundler_args: --without changelog development docgen guard maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen
@@ -30,30 +34,30 @@ env:
matrix:
include:
- - rvm: 2.2.5
+ - rvm: 2.2.6
sudo: true
script: sudo -E $(which bundle) exec rake spec;
# also remove integration / external tests
bundler_args: --without changelog development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen
- - rvm: 2.3.1
+ - rvm: 2.3.3
sudo: true
script: sudo -E $(which bundle) exec rake spec;
# also remove integration / external tests
bundler_args: --without changelog development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen
- - rvm: rbx
+ - rvm: 2.4.0
sudo: true
script: sudo -E $(which bundle) exec rake spec;
# also remove integration / external tests
bundler_args: --without changelog development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen
- env:
CHEFSTYLE: 1
- rvm: 2.3.1
+ rvm: 2.3.3
script: bundle exec rake style
# also remove integration / external tests
bundler_args: --without changelog development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen
- env:
AUDIT_CHECK: 1
- rvm: 2.3.1
+ rvm: 2.3.3
script: bundle exec bundle-audit check --update
# also remove integration / external tests
bundler_args: --without changelog development docgen guard integration maintenance omnibus_package tools aix bsd mac_os_x solaris windows --frozen
@@ -63,51 +67,49 @@ matrix:
- env:
TEST_GEM: chef-provisioning
script: tasks/bin/run_external_test $TEST_GEM rake spec
- rvm: 2.3.1
- - env:
- TEST_GEM: chef-provisioning-aws
- script: tasks/bin/run_external_test $TEST_GEM rake spec
- rvm: 2.3.1
+ rvm: 2.3.3
- env:
TEST_GEM: chef-sugar
script: tasks/bin/run_external_test $TEST_GEM rake
- rvm: 2.3.1
+ rvm: 2.3.3
- env:
- TEST_GEM: chef-zero
script: tasks/bin/run_external_test $TEST_GEM rake spec cheffs
- rvm: 2.3.1
+ rvm: 2.3.3
- env:
TEST_GEM: cheffish
script: tasks/bin/run_external_test $TEST_GEM rake spec
- rvm: 2.3.1
+ rvm: 2.3.3
- env:
TEST_GEM: chefspec
# The chefspec tests + bundler cache + "gem update --system" interact badly :/
# (Cucumber doesn't start.)
before_install:
+ - gem uninstall bundler -a -x
+ - rvm @global do gem uninstall bundler -a -x
- gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
- bundle config --local without server:docgen:maintenance:omnibus_package:development:ruby_prof:pry
script: tasks/bin/run_external_test $TEST_GEM rake
- rvm: 2.3.1
+ rvm: 2.3.3
- env:
TEST_GEM: foodcritic
script: tasks/bin/run_external_test $TEST_GEM rake test
- rvm: 2.3.1
+ rvm: 2.3.3
- env:
TEST_GEM: halite
script: tasks/bin/run_external_test $TEST_GEM rake spec
- rvm: 2.3.1
+ rvm: 2.3.3
- env:
TEST_GEM: knife-windows
script: tasks/bin/run_external_test $TEST_GEM rake unit_spec
- rvm: 2.3.1
+ rvm: 2.3.3
- env:
TEST_GEM: poise
script: tasks/bin/run_external_test $TEST_GEM rake spec
- rvm: 2.3.1
+ rvm: 2.3.3
### START TEST KITCHEN ONLY ###
#
- - rvm: 2.3.1
+ - rvm: 2.3.3
services: docker
sudo: required
gemfile: kitchen-tests/Gemfile
@@ -125,7 +127,7 @@ matrix:
env:
- UBUNTU=12.04
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.3.1
+ - rvm: 2.3.3
services: docker
sudo: required
gemfile: kitchen-tests/Gemfile
@@ -143,7 +145,7 @@ matrix:
env:
- UBUNTU=14.04
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.3.1
+ - rvm: 2.3.3
services: docker
sudo: required
gemfile: kitchen-tests/Gemfile
@@ -161,7 +163,7 @@ matrix:
env:
- UBUNTU=16.04
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.3.1
+ - rvm: 2.3.3
services: docker
sudo: required
gemfile: kitchen-tests/Gemfile
@@ -179,7 +181,7 @@ matrix:
env:
- DEBIAN=7
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.3.1
+ - rvm: 2.3.3
services: docker
sudo: required
gemfile: kitchen-tests/Gemfile
@@ -198,7 +200,7 @@ matrix:
env:
- DEBIAN=8
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.3.1
+ - rvm: 2.3.3
services: docker
sudo: required
gemfile: kitchen-tests/Gemfile
@@ -216,7 +218,7 @@ matrix:
env:
- CENTOS=6
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.3.1
+ - rvm: 2.3.3
services: docker
sudo: required
gemfile: kitchen-tests/Gemfile
@@ -234,25 +236,44 @@ matrix:
env:
- CENTOS=7
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.3.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 changelog 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-fedora-23
- after_failure:
- - cat .kitchen/logs/kitchen.log
- env:
- - FEDORA=23
- - KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.3.1
+# - rvm: 2.3.3
+# 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 changelog 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-fedora-latest
+# after_failure:
+# - cat .kitchen/logs/kitchen.log
+# env:
+# - FEDORA=latest
+# - KITCHEN_YAML=.kitchen.travis.yml
+# can re-enable amazonlinux when we get a build in current that contains the crypto libs added in #5687
+# - rvm: 2.3.3
+# 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 changelog 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
+ - rvm: 2.3.3
services: docker
sudo: required
gemfile: kitchen-tests/Gemfile
@@ -270,7 +291,7 @@ matrix:
env:
- AWESOME_CUSTOMERS_UBUNTU=1
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.3.1
+ - rvm: 2.3.3
services: docker
sudo: required
gemfile: kitchen-tests/Gemfile
@@ -289,7 +310,7 @@ matrix:
- AWESOME_CUSTOMERS_RHEL=1
- KITCHEN_YAML=.kitchen.travis.yml
### END TEST KITCHEN ONLY ###
- - rvm: 2.3.1
+ - rvm: 2.3.3
sudo: required
dist: trusty
before_install:
@@ -310,9 +331,6 @@ matrix:
- sudo cat /var/log/squid3/cache.log
- sudo cat /var/log/squid3/access.log
- allow_failures:
- - rvm: rbx
-
notifications:
on_change: true
on_failure: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1679dad76a..4fdbf7627d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,102 @@
-# Change Log
+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).
+
+## [v12.19.30](https://github.com/chef/chef/tree/v12.19.30) (2017-02-14)
+[Full Changelog](https://github.com/chef/chef/compare/v12.18.31...v12.19.30)
+
+**Closed issues:**
+
+- Package resource fails chefspec on RHEL starting with Chef 12.18. [\#5769](https://github.com/chef/chef/issues/5769)
+
+**Merged pull requests:**
+
+- coerce immutable arrays to normal arrays in the yum\_package resource [\#5816](https://github.com/chef/chef/pull/5816) ([lamont-granquist](https://github.com/lamont-granquist))
+- Suppress sensitive properties from resource log and reporting output [\#5803](https://github.com/chef/chef/pull/5803) ([tduffield](https://github.com/tduffield))
+- Sanitize UTF-8 data sent to Data Collector [\#5793](https://github.com/chef/chef/pull/5793) ([lamont-granquist](https://github.com/lamont-granquist))
+- Add multipackage\_api support to yum\_package provider [\#5791](https://github.com/chef/chef/pull/5791) ([tduffield](https://github.com/tduffield))
+- rhel7 / dnf 2.0 fixes / improved errors [\#5782](https://github.com/chef/chef/pull/5782) ([lamont-granquist](https://github.com/lamont-granquist))
+- Grant Administrators group permissions to nodes directory under chef-solo [\#5781](https://github.com/chef/chef/pull/5781) ([tduffield](https://github.com/tduffield))
+- Fix --no-fips on chef-client [\#5778](https://github.com/chef/chef/pull/5778) ([btm](https://github.com/btm))
+- Raise error if ips\_package install returns non-zero [\#5773](https://github.com/chef/chef/pull/5773) ([tduffield](https://github.com/tduffield))
+- Use CIDR notation rather than netmask in route-eth0 file [\#5772](https://github.com/chef/chef/pull/5772) ([tduffield](https://github.com/tduffield))
+- Verify systemd\_unit file with custom verifier [\#5765](https://github.com/chef/chef/pull/5765) ([mal](https://github.com/mal))
+- Windows alternate user support for execute resources [\#5764](https://github.com/chef/chef/pull/5764) ([NimishaS](https://github.com/NimishaS))
+- favor metadata.json over metadata.rb [\#5750](https://github.com/chef/chef/pull/5750) ([lamont-granquist](https://github.com/lamont-granquist))
+- Ensure ssh search paginates correctly [\#5744](https://github.com/chef/chef/pull/5744) ([thommay](https://github.com/thommay))
+- Do not modify File's new\_resource during why-run [\#5742](https://github.com/chef/chef/pull/5742) ([scottopherson](https://github.com/scottopherson))
+- Add gems for ECC algorithm support to omnibus. [\#5736](https://github.com/chef/chef/pull/5736) ([rhass](https://github.com/rhass))
+- dh/url support cab [\#5732](https://github.com/chef/chef/pull/5732) ([dheerajd-msys](https://github.com/dheerajd-msys))
+- use git archive to speed up putting source in place [\#5730](https://github.com/chef/chef/pull/5730) ([robbkidd](https://github.com/robbkidd))
+- use pkg.path variable to reference path to self [\#5729](https://github.com/chef/chef/pull/5729) ([robbkidd](https://github.com/robbkidd))
+- Raise NamedSecurityInfo related exception using HR result. [\#5727](https://github.com/chef/chef/pull/5727) ([Aliasgar16](https://github.com/Aliasgar16))
+- Core: Ensure paths are correctly escaped when syntax checking [\#5704](https://github.com/chef/chef/pull/5704) ([ceneo](https://github.com/ceneo))
+- Added module\_version attribute for dsc\_resource for SxS support [\#5701](https://github.com/chef/chef/pull/5701) ([Aliasgar16](https://github.com/Aliasgar16))
+- Bump net-ssh to v4, add dependencies for ed25519 support [\#5687](https://github.com/chef/chef/pull/5687) ([onlyhavecans](https://github.com/onlyhavecans))
+- Initial habitat plan for chef-client [\#5677](https://github.com/chef/chef/pull/5677) ([adamhjk](https://github.com/adamhjk))
+
+## [v12.18.31](https://github.com/chef/chef/tree/v12.18.31) (2017-01-11)
+[Full Changelog](https://github.com/chef/chef/compare/v12.17.44...v12.18.31)
+
+**Implemented enhancements:**
+
+- yum\_repository: Allow baseurl to be an array & allow fastestmirror\_enabled false [\#5708](https://github.com/chef/chef/pull/5708) ([tas50](https://github.com/tas50))
+- Adding returns property to chocolatey\_package resource [\#5688](https://github.com/chef/chef/pull/5688) ([Vasu1105](https://github.com/Vasu1105))
+- Code cleanup in the user provider [\#5674](https://github.com/chef/chef/pull/5674) ([lamont-granquist](https://github.com/lamont-granquist))
+- Code cleanup in the group provider [\#5673](https://github.com/chef/chef/pull/5673) ([lamont-granquist](https://github.com/lamont-granquist))
+- Core: Formally deprecate run\_command [\#5666](https://github.com/chef/chef/pull/5666) ([lamont-granquist](https://github.com/lamont-granquist))
+- Set MSI Scheduled Task name to match chef-client cookbook managed name [\#5657](https://github.com/chef/chef/pull/5657) ([mwrock](https://github.com/mwrock))
+- remove Chef::Platform::HandlerMap [\#5636](https://github.com/chef/chef/pull/5636) ([lamont-granquist](https://github.com/lamont-granquist))
+- Core: Properly deprecate old Chef::Platform methods [\#5631](https://github.com/chef/chef/pull/5631) ([lamont-granquist](https://github.com/lamont-granquist))
+
+**Fixed bugs:**
+
+- Fix error thrown by solo when run on Windows as SYSTEM [\#5693](https://github.com/chef/chef/pull/5693) ([scottopherson](https://github.com/scottopherson))
+- Report a blank resource if sensitive is enabled [\#5668](https://github.com/chef/chef/pull/5668) ([afiune](https://github.com/afiune))
+- Ensure node.docker? returns boolean [\#5645](https://github.com/chef/chef/pull/5645) ([andrewjamesbrown](https://github.com/andrewjamesbrown))
+- Fix Data Collector organization parsing regex [\#5630](https://github.com/chef/chef/pull/5630) ([adamleff](https://github.com/adamleff))
+- Core: Use object ID when detected unprocessed Resources [\#5604](https://github.com/chef/chef/pull/5604) ([adamleff](https://github.com/adamleff))
+
+**Merged pull requests:**
+
+- Core: fix node attribute "unless" API methods [\#5717](https://github.com/chef/chef/pull/5717) ([lamont-granquist](https://github.com/lamont-granquist))
+
+## [v12.17.44](https://github.com/chef/chef/tree/v12.17.44) (2016-12-07)
+[Full Changelog](https://github.com/chef/chef/compare/v12.16.42...v12.17.44)
+
+**Implemented enhancements:**
+
+- Action :umount for mount resource is an obtuse anachronism [\#5595](https://github.com/chef/chef/issues/5595)
+- Core: Update ohai resource to new style, stop overwriting name property [\#5607](https://github.com/chef/chef/pull/5607) ([adamleff](https://github.com/adamleff))
+- Linux: mount provider - skip device detection for zfs [\#5603](https://github.com/chef/chef/pull/5603) ([ttr](https://github.com/ttr))
+- Core: Ensure chef-solo creates node files w/ correct permissions [\#5601](https://github.com/chef/chef/pull/5601) ([scottopherson](https://github.com/scottopherson))
+- Resources: Add unmount as an alias to umount in the mount resource [\#5599](https://github.com/chef/chef/pull/5599) ([shortdudey123](https://github.com/shortdudey123))
+- Core: Update Data Collector to use Chef::JSONCompat [\#5590](https://github.com/chef/chef/pull/5590) ([adamleff](https://github.com/adamleff))
+- Knife: Add ability to pass multiple nodes to knife node/client delete [\#5572](https://github.com/chef/chef/pull/5572) ([jeunito](https://github.com/jeunito))
+- Core: Data Collector debug log should output JSON [\#5570](https://github.com/chef/chef/pull/5570) ([adamleff](https://github.com/adamleff))
+- Yum: Purge yum cache before deleting repo config [\#5509](https://github.com/chef/chef/pull/5509) ([iancward](https://github.com/iancward))
+- Knife Bootstrap: Passing config\_log\_level and config\_log\_location from config.rb [\#5502](https://github.com/chef/chef/pull/5502) ([dheerajd-msys](https://github.com/dheerajd-msys))
+
+**Fixed bugs:**
+
+- Custom Resources: Undefined method up\_to\_date thrown by Chef 12.16.42 [\#5593](https://github.com/chef/chef/issues/5593)
+- Core: Ensure deprecation messages are always included [\#5618](https://github.com/chef/chef/pull/5618) ([thommay](https://github.com/thommay))
+- Core: Fix bug where Access Controls on existing symlink resources would be ignored on first chef-client run [\#5616](https://github.com/chef/chef/pull/5616) ([tduffield](https://github.com/tduffield))
+- The suggested fix for the manage\_home deprecation is incorrect [\#5615](https://github.com/chef/chef/pull/5615) ([tas50](https://github.com/tas50))
+- change choco -version to choco --version [\#5613](https://github.com/chef/chef/pull/5613) ([spuder](https://github.com/spuder))
+- Knife: Correct example `chef\_server\_url` in `knife configure` [\#5602](https://github.com/chef/chef/pull/5602) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
+- Windows: Ensure correct version of shutdown is called when using the reboot resource [\#5596](https://github.com/chef/chef/pull/5596) ([Xoph](https://github.com/Xoph))
+- Windows: Support for running cab\_package on non-English system locales [\#5591](https://github.com/chef/chef/pull/5591) ([jugatsu](https://github.com/jugatsu))
+- Core: Ensure Data Collector resource report exists before updating [\#5571](https://github.com/chef/chef/pull/5571) ([adamleff](https://github.com/adamleff))
+- Windows: Use the full path to expand.exe for msu\_package [\#5564](https://github.com/chef/chef/pull/5564) ([NimishaS](https://github.com/NimishaS))
+- Unset http\[s\]\_proxy in the subversion spec [\#5562](https://github.com/chef/chef/pull/5562) ([stefanor](https://github.com/stefanor))
+- Core: fix Lint/UnifiedInteger cop [\#5547](https://github.com/chef/chef/pull/5547) ([lamont-granquist](https://github.com/lamont-granquist))
+- Core: fix ImmutableArray slices [\#5541](https://github.com/chef/chef/pull/5541) ([lamont-granquist](https://github.com/lamont-granquist))
+- Prevent apt\_update failures on non-Linux platforms [\#5524](https://github.com/chef/chef/pull/5524) ([tas50](https://github.com/tas50))
+- Core: Ensure that the sensitive property is correctly accessed [\#5508](https://github.com/chef/chef/pull/5508) ([axos88](https://github.com/axos88))
+
+**Closed issues:**
+
+- cab\_package doesn't support running on non-English system locales [\#5592](https://github.com/chef/chef/issues/5592)
+- Support restarting/stopping/ the service from state paused on windows [\#5586](https://github.com/chef/chef/issues/5586)
## [v12.16.42](https://github.com/chef/chef/tree/v12.16.42) (2016-11-04)
[Full Changelog](https://github.com/chef/chef/compare/v12.15.19...v12.16.42)
@@ -12,6 +110,7 @@
- Knife: Add the `--field-separator` flag to knife show commands [\#5489](https://github.com/chef/chef/pull/5489) ([tduffield](https://github.com/tduffield))
- Core: Enable Signed Header Auth for Data Collector, and Configure the Data Collector Automatically [\#5487](https://github.com/chef/chef/pull/5487) ([danielsdeleo](https://github.com/danielsdeleo))
- Core: set use\_inline\_resources in package superclass [\#5483](https://github.com/chef/chef/pull/5483) ([lamont-granquist](https://github.com/lamont-granquist))
+- Package: Add new "lock" action for apt, yum and zypper packages [\#5395](https://github.com/chef/chef/pull/5395) ([yeoldegrove](https://github.com/yeoldegrove))
**Fixed bugs:**
@@ -1266,5 +1365,4 @@ of partial templates.
* Allow specifying a guard_interpreter after a conditional on a resource (Fixes #1943)
* Windows package type should be a symbol (Fixes #1997)
-
-\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
+\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000..ea79037581
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,11 @@
+FROM busybox
+MAINTAINER Chef Software, Inc. <docker@chef.io>
+
+ARG CHANNEL=stable
+ARG VERSION=12.18.31
+
+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 && \
+ rm -rf /tmp/chef-client.rpm
+
+VOLUME [ "/opt/chef" ]
diff --git a/Gemfile b/Gemfile
index 782a85357d..b3fa6b01a3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -12,10 +12,9 @@ source "https://rubygems.org"
gem "chef", path: "."
gem "chef-config", path: File.expand_path("../chef-config", __FILE__) if File.exist?(File.expand_path("../chef-config", __FILE__))
-# Ensure that we can always install rake, regardless of gem groups
-gem "rake", group: [ :default, :omnibus_package, :development ]
+gem "rake"
gem "bundler"
-gem "cheffish"
+gem "cheffish" # required for rspec tests
group(:omnibus_package) do
gem "appbundler"
@@ -29,10 +28,10 @@ group(:omnibus_package, :pry) do
gem "pry-remote"
gem "pry-stack_explorer"
end
+
# These are used for external tests
group(:integration) do
gem "chef-provisioning"
- gem "chef-provisioning-aws"
gem "chef-sugar"
gem "chefspec"
gem "halite"
@@ -64,6 +63,7 @@ group(:linux, :bsd, :mac_os_x, :solaris, :windows) do
# may need to disable this in insolation on fussy builds like AIX, RHEL4, etc
gem "ruby-prof"
end
+
# Everything except AIX and Windows
group(:linux, :bsd, :mac_os_x, :solaris) do
gem "ruby-shadow", platforms: :ruby
@@ -78,7 +78,8 @@ group(:development, :test) do
end
group(:changelog) do
- gem "github_changelog_generator"
+ gem "github_changelog_generator", git: "https://github.com/chef/github-changelog-generator"
+ gem "mixlib-install"
end
group(:travis) do
diff --git a/Gemfile.lock b/Gemfile.lock
index a3a22e0a5f..00b17a1f57 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,6 +1,6 @@
GIT
remote: https://github.com/chef/chef-server
- revision: f4a124354730cbd61c14635dca955d385cfa382d
+ revision: 53b28425d56005a92b0e3bb153f95b505168354a
specs:
oc-chef-pedant (2.2.0)
activesupport (>= 4.2.7.1, < 6.0)
@@ -16,15 +16,28 @@ GIT
GIT
remote: https://github.com/chef/chefstyle.git
- revision: 71b73a0f481d595bf222e1804c7152d2415f69a4
+ revision: 7e47afd6141d3c44a11322916e3fc85c89aa9b59
branch: master
specs:
- chefstyle (0.4.0)
- rubocop (= 0.44.1)
+ chefstyle (0.5.0)
+ rubocop (= 0.47.1)
+
+GIT
+ remote: https://github.com/chef/github-changelog-generator
+ revision: 7ab4953b47598dccf10e106058673c1592b8f9bf
+ specs:
+ github_changelog_generator (1.14.2)
+ activesupport
+ faraday-http-cache
+ multi_json
+ octokit (~> 4.6)
+ rainbow (>= 2.1)
+ rake (>= 10.0)
+ retriable (>= 1.4)
GIT
remote: https://github.com/rubysec/bundler-audit.git
- revision: b7123d7b294f244165d9469f22b37a559e235fc2
+ revision: 6eb5a81e9b184fbb8db03f3e57dc758c65dd7383
specs:
bundler-audit (0.5.0)
bundler (~> 1.2)
@@ -33,25 +46,25 @@ GIT
PATH
remote: .
specs:
- chef (12.16.49)
+ chef (12.19.30)
addressable
bundler (>= 1.10)
- chef-config (= 12.16.49)
+ chef-config (= 12.19.30)
chef-zero (>= 4.8)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
ffi-yajl (~> 2.2)
highline (~> 1.6, >= 1.6.9)
iniparse (~> 1.4)
- mixlib-archive (>= 0.2.0)
+ mixlib-archive (~> 0.4)
mixlib-authentication (~> 1.4)
mixlib-cli (~> 1.7)
mixlib-log (~> 1.3)
mixlib-shellout (~> 2.0)
net-sftp (~> 2.1, >= 2.1.2)
- net-ssh (>= 2.9, < 4.0)
- net-ssh-multi (~> 1.1)
- ohai (>= 8.6.0.alpha.1, < 9)
+ net-ssh (>= 2.9, < 5.0)
+ net-ssh-multi (~> 1.2, >= 1.2.1)
+ ohai (>= 8.6.0.alpha.1, < 13)
plist (~> 3.2)
proxifier (~> 1.0)
rspec-core (~> 3.5)
@@ -62,10 +75,10 @@ PATH
specinfra (~> 2.10)
syslog-logger (~> 1.6)
uuidtools (~> 2.1.5)
- chef (12.16.49-universal-mingw32)
+ chef (12.19.30-universal-mingw32)
addressable
bundler (>= 1.10)
- chef-config (= 12.16.49)
+ chef-config (= 12.19.30)
chef-zero (>= 4.8)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
@@ -73,15 +86,15 @@ PATH
ffi-yajl (~> 2.2)
highline (~> 1.6, >= 1.6.9)
iniparse (~> 1.4)
- mixlib-archive (>= 0.2.0)
+ mixlib-archive (~> 0.4)
mixlib-authentication (~> 1.4)
mixlib-cli (~> 1.7)
mixlib-log (~> 1.3)
mixlib-shellout (~> 2.0)
net-sftp (~> 2.1, >= 2.1.2)
- net-ssh (>= 2.9, < 4.0)
- net-ssh-multi (~> 1.1)
- ohai (>= 8.6.0.alpha.1, < 9)
+ net-ssh (>= 2.9, < 5.0)
+ net-ssh-multi (~> 1.2, >= 1.2.1)
+ ohai (>= 8.6.0.alpha.1, < 13)
plist (~> 3.2)
proxifier (~> 1.0)
rspec-core (~> 3.5)
@@ -106,7 +119,7 @@ PATH
PATH
remote: chef-config
specs:
- chef-config (12.16.49)
+ chef-config (12.19.30)
addressable
fuzzyurl
mixlib-config (~> 2.0)
@@ -115,70 +128,62 @@ PATH
GEM
remote: https://rubygems.org/
specs:
- activesupport (5.0.0.1)
+ activesupport (5.0.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.4.0)
- appbundler (0.9.0)
+ appbundler (0.10.0)
mixlib-cli (~> 1.4)
- artifactory (2.5.0)
+ artifactory (2.6.0)
ast (2.3.0)
- aws-sdk (2.6.14)
- aws-sdk-resources (= 2.6.14)
- aws-sdk-core (2.6.14)
+ aws-sdk (2.7.7)
+ aws-sdk-resources (= 2.7.7)
+ aws-sdk-core (2.7.7)
+ aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-resources (2.6.14)
- aws-sdk-core (= 2.6.14)
- aws-sdk-v1 (1.66.0)
- json (~> 1.4)
- nokogiri (>= 1.4.4)
+ aws-sdk-resources (2.7.7)
+ aws-sdk-core (= 2.7.7)
+ aws-sigv4 (1.0.0)
backports (3.6.8)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
- builder (3.2.2)
+ builder (3.2.3)
byebug (9.0.6)
chef-api (0.7.0)
logify (~> 0.1)
mime-types
- chef-provisioning (2.0.2)
+ chef-provisioning (2.1.0)
cheffish (~> 4.0)
inifile (>= 2.0.2)
mixlib-install (>= 1.0, < 3.0)
net-scp (~> 1.0)
- net-ssh (>= 2.9, < 4.0)
- net-ssh-gateway (~> 1.2.0)
+ net-ssh (>= 2.9, < 5.0)
+ net-ssh-gateway (~> 1.2)
winrm-fs (~> 1.0)
- chef-provisioning-aws (2.0.0)
- aws-sdk (>= 2.1.26, < 3.0)
- aws-sdk-v1 (>= 1.59.0)
- chef-provisioning (~> 2.0)
- retryable (~> 2.0, >= 2.0.1)
- ubuntu_ami (~> 0.4, >= 0.4.1)
chef-sugar (3.4.0)
- chef-zero (5.1.0)
+ chef-zero (5.3.0)
ffi-yajl (~> 2.2)
hashie (>= 2.0, < 4.0)
mixlib-log (~> 1.3)
rack (~> 2.0)
uuidtools (~> 2.1)
- cheffish (4.0.0)
+ cheffish (4.1.1)
chef-zero (~> 5.0)
net-ssh
- chefspec (5.3.0)
+ chefspec (5.4.0)
chef (>= 12.0)
fauxhai (~> 3.6)
rspec (~> 3.0)
codeclimate-test-reporter (0.6.0)
simplecov (>= 0.7.1, < 1.0.0)
- codecov (0.1.6)
+ codecov (0.1.9)
json
simplecov
url
coderay (1.1.1)
- concurrent-ruby (1.0.2)
- connection_pool (2.2.0)
+ concurrent-ruby (1.0.4)
cucumber (2.4.0)
builder (>= 2.1.2)
cucumber-core (~> 1.5.0)
@@ -191,29 +196,29 @@ GEM
gherkin (~> 4.0)
cucumber-wire (0.0.1)
debug_inspector (0.0.2)
- descendants_tracker (0.0.4)
- thread_safe (~> 0.3, >= 0.3.1)
- diff-lcs (1.2.5)
+ diff-lcs (1.3)
docile (1.1.5)
- domain_name (0.5.20161021)
+ domain_name (0.5.20161129)
unf (>= 0.0.5, < 1.0.0)
erubis (2.7.0)
- ethon (0.9.1)
+ ethon (0.10.1)
ffi (>= 1.3.0)
- excon (0.54.0)
- faraday (0.9.2)
+ excon (0.55.0)
+ faraday (0.11.0)
multipart-post (>= 1.2, < 3)
- faraday_middleware (0.10.0)
- faraday (>= 0.7.4, < 0.10)
+ faraday-http-cache (2.0.0)
+ faraday (~> 0.8)
+ faraday_middleware (0.11.0.1)
+ faraday (>= 0.7.4, < 1.0)
fauxhai (3.10.0)
net-ssh
- ffi (1.9.14)
- ffi (1.9.14-x86-mingw32)
+ ffi (1.9.17)
+ ffi (1.9.17-x86-mingw32)
ffi-win32-extensions (1.0.3)
ffi
ffi-yajl (2.3.0)
libyajl2 (~> 1.2)
- foodcritic (8.1.0)
+ foodcritic (8.2.0)
cucumber-core (>= 1.3)
erubis
nokogiri (>= 1.5, < 2.0)
@@ -225,60 +230,49 @@ GEM
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
fuzzyurl (0.9.0)
- gh (0.14.0)
- addressable
+ gh (0.15.0)
+ addressable (~> 2.4.0)
backports
faraday (~> 0.8)
multi_json (~> 1.0)
- net-http-persistent (>= 2.7)
+ net-http-persistent (~> 2.9)
net-http-pipeline
gherkin (4.0.0)
git (1.3.0)
- github_api (0.14.5)
- addressable (~> 2.4.0)
- descendants_tracker (~> 0.0.4)
- faraday (~> 0.8, < 0.10)
- hashie (>= 3.4)
- oauth2 (~> 1.0)
- github_changelog_generator (1.13.2)
- github_api (>= 0.14)
- rainbow (>= 2.1)
- rake (>= 10.0)
gssapi (1.2.0)
ffi (>= 1.0.1)
gyoku (1.3.1)
builder (>= 2.1.2)
- halite (1.3.0)
+ halite (1.4.0)
bundler
chef (~> 12.0)
stove (~> 4.0)
thor
- hashie (3.4.6)
+ hashie (3.5.3)
highline (1.7.8)
http-cookie (1.0.3)
domain_name (~> 0.5)
- httpclient (2.8.2.4)
- i18n (0.7.0)
+ httpclient (2.8.3)
+ i18n (0.8.0)
inifile (3.0.0)
iniparse (1.4.2)
ipaddress (0.8.3)
jmespath (1.3.1)
- json (1.8.3)
- jwt (1.5.6)
+ json (2.0.3)
kitchen-docker (2.6.0)
test-kitchen (>= 1.0.0)
- kitchen-ec2 (1.2.0)
+ kitchen-ec2 (1.3.0)
aws-sdk (~> 2)
excon
multi_json
retryable (~> 2.0)
test-kitchen (~> 1.4, >= 1.4.1)
- kitchen-sync (2.1.1)
+ kitchen-sync (2.1.2)
net-sftp
test-kitchen (>= 1.0.0)
- kitchen-vagrant (0.20.0)
+ kitchen-vagrant (1.0.1)
test-kitchen (~> 1.4)
- knife-windows (1.7.0)
+ knife-windows (1.9.0)
winrm (~> 2.1)
winrm-elevated (~> 1.0)
launchy (2.4.3)
@@ -294,14 +288,14 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_portile2 (2.1.0)
- minitest (5.9.1)
- mixlib-archive (0.2.0)
+ minitest (5.10.1)
+ mixlib-archive (0.4.1)
mixlib-log
mixlib-authentication (1.4.1)
mixlib-log
mixlib-cli (1.7.0)
mixlib-config (2.2.4)
- mixlib-install (2.1.5)
+ mixlib-install (2.1.12)
artifactory
mixlib-shellout
mixlib-versioning
@@ -314,38 +308,30 @@ GEM
mixlib-versioning (1.1.0)
multi_json (1.12.1)
multi_test (0.1.2)
- multi_xml (0.5.5)
multipart-post (2.0.0)
- net-http-persistent (3.0.0)
- connection_pool (~> 2.2)
+ net-http-persistent (2.9.4)
net-http-pipeline (1.0.1)
net-http-spy (0.2.1)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-sftp (2.1.2)
net-ssh (>= 2.6.5)
- net-ssh (3.2.0)
- net-ssh-gateway (1.2.0)
+ net-ssh (4.0.1)
+ net-ssh-gateway (1.3.0)
net-ssh (>= 2.6.5)
net-ssh-multi (1.2.1)
net-ssh (>= 2.6.5)
net-ssh-gateway (>= 1.2.0)
net-telnet (0.1.1)
netrc (0.11.0)
- nokogiri (1.6.8.1)
+ nokogiri (1.7.0.1)
mini_portile2 (~> 2.1.0)
- nokogiri (1.6.8.1-x86-mingw32)
+ nokogiri (1.7.0.1-x86-mingw32)
mini_portile2 (~> 2.1.0)
nori (2.6.0)
- oauth2 (1.2.0)
- faraday (>= 0.8, < 0.10)
- jwt (~> 1.0)
- multi_json (~> 1.3)
- multi_xml (~> 0.5)
- rack (>= 1.2, < 3)
- octokit (4.4.1)
- sawyer (~> 0.7.0, >= 0.5.3)
- ohai (8.21.0)
+ octokit (4.6.2)
+ sawyer (~> 0.8.0, >= 0.5.3)
+ ohai (8.23.0)
chef-config (>= 12.5.0.alpha.1, < 13)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
@@ -357,12 +343,12 @@ GEM
plist (~> 3.1)
systemu (~> 2.6.4)
wmi-lite (~> 1.0)
- parser (2.3.1.4)
+ parser (2.4.0.0)
ast (~> 2.2)
plist (3.2.0)
- poise (2.7.1)
+ poise (2.7.2)
halite (~> 1.0)
- poise-boiler (1.13.1)
+ poise-boiler (1.13.2)
bundler
chefspec (~> 5.0)
codeclimate-test-reporter (~> 0.4)
@@ -386,8 +372,8 @@ GEM
test-kitchen (~> 1.7, >= 1.7.1)
travis (~> 1.8, >= 1.8.1)
vagrant-wrapper
- winrm (~> 2.0)
- winrm-fs (~> 1.0)
+ winrm (>= 1.6, < 3)
+ winrm-fs (>= 0.4, < 2)
yard (~> 0.8)
yard-classmethods (~> 1.0)
poise-profiler (1.0.1)
@@ -399,7 +385,7 @@ GEM
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
- pry-byebug (3.4.0)
+ pry-byebug (3.4.2)
byebug (~> 9.0)
pry (~> 0.10)
pry-remote (0.1.8)
@@ -412,9 +398,9 @@ GEM
json
websocket (~> 1.0)
rack (2.0.1)
- rainbow (2.1.0)
+ rainbow (2.2.1)
rake (11.3.0)
- rb-readline (0.5.3)
+ rb-readline (0.5.4)
rest-client (2.0.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
@@ -424,6 +410,7 @@ GEM
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
+ retriable (3.0.0)
retryable (2.0.4)
rspec (3.5.0)
rspec-core (~> 3.5.0)
@@ -446,8 +433,8 @@ GEM
rspec_junit_formatter (0.2.3)
builder (< 4)
rspec-core (>= 2, < 4, != 2.12.0)
- rubocop (0.44.1)
- parser (>= 2.3.1.1, < 3.0)
+ rubocop (0.47.1)
+ parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
@@ -456,27 +443,27 @@ GEM
ruby-progressbar (1.8.1)
ruby-shadow (2.5.0)
rubyntlm (0.6.1)
- rubyzip (1.2.0)
+ rubyzip (1.2.1)
rufus-lru (1.1.0)
safe_yaml (1.0.4)
- sawyer (0.7.0)
- addressable (>= 2.3.5, < 2.5)
- faraday (~> 0.8, < 0.10)
- serverspec (2.37.2)
+ sawyer (0.8.1)
+ addressable (>= 2.3.5, < 2.6)
+ faraday (~> 0.8, < 1.0)
+ serverspec (2.38.0)
multi_json
rspec (~> 3.0)
rspec-its
specinfra (~> 2.53)
sfl (2.3)
- simplecov (0.12.0)
+ simplecov (0.13.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
slop (3.6.0)
- specinfra (2.64.0)
+ specinfra (2.66.9)
net-scp
- net-ssh (>= 2.7, < 4.0)
+ net-ssh (>= 2.7, < 5.0)
net-telnet
sfl
stove (4.1.1)
@@ -484,18 +471,18 @@ GEM
logify (~> 0.2)
syslog-logger (1.6.8)
systemu (2.6.5)
- test-kitchen (1.13.2)
+ test-kitchen (1.15.0)
mixlib-install (>= 1.2, < 3.0)
mixlib-shellout (>= 1.2, < 3.0)
net-scp (~> 1.1)
- net-ssh (>= 2.9, < 4.0)
- net-ssh-gateway (~> 1.2.0)
+ net-ssh (>= 2.9, < 5.0)
+ net-ssh-gateway (~> 1.2)
safe_yaml (~> 1.0)
thor (~> 0.18)
- thor (0.19.1)
+ thor (0.19.4)
thread_safe (0.3.5)
tomlrb (1.2.3)
- travis (1.8.2)
+ travis (1.8.6)
backports
faraday (~> 0.9)
faraday_middleware (~> 0.9, >= 0.9.1)
@@ -510,16 +497,15 @@ GEM
ethon (>= 0.8.0)
tzinfo (1.2.2)
thread_safe (~> 0.1)
- ubuntu_ami (0.4.1)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.2)
unf_ext (0.0.7.2-x86-mingw32)
- unicode-display_width (1.1.1)
+ unicode-display_width (1.1.3)
url (0.3.2)
uuidtools (2.1.5)
vagrant-wrapper (2.0.3)
- websocket (1.2.3)
+ websocket (1.2.4)
win32-api (1.5.3-universal-mingw32)
win32-dir (0.5.1)
ffi (>= 1.0.0)
@@ -535,12 +521,12 @@ GEM
win32-ipc (>= 0.6.0)
win32-process (0.8.3)
ffi (>= 1.0.0)
- win32-service (0.8.9)
+ win32-service (0.8.10)
ffi
ffi-win32-extensions
windows-api (0.4.4)
win32-api (>= 1.4.5)
- winrm (2.1.0)
+ winrm (2.1.2)
builder (>= 2.1.2)
erubis (~> 2.7)
gssapi (~> 1.2)
@@ -549,17 +535,17 @@ GEM
logging (>= 1.6.1, < 3.0)
nori (~> 2.0)
rubyntlm (~> 0.6.0, >= 0.6.1)
- winrm-elevated (1.0.1)
+ winrm-elevated (1.1.0)
winrm (~> 2.0)
winrm-fs (~> 1.0)
- winrm-fs (1.0.0)
+ winrm-fs (1.0.1)
erubis (~> 2.7)
logging (>= 1.6.1, < 3.0)
rubyzip (~> 1.1)
winrm (~> 2.0)
wmi-lite (1.0.0)
- yajl-ruby (1.2.1)
- yard (0.9.5)
+ yajl-ruby (1.3.0)
+ yard (0.9.8)
yard-classmethods (1.0.0)
yard
@@ -574,16 +560,16 @@ DEPENDENCIES
chef!
chef-config!
chef-provisioning
- chef-provisioning-aws
chef-sugar
cheffish
chefspec
chefstyle!
cucumber (>= 2.4.0)
foodcritic
- github_changelog_generator
+ github_changelog_generator!
halite
knife-windows
+ mixlib-install
netrc
nokogiri
oc-chef-pedant!
diff --git a/HISTORY.md b/HISTORY.md
index 487a28d105..acce953a47 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,3 +1,91 @@
+## [v12.18.31](https://github.com/chef/chef/tree/v12.18.31) (2017-01-11)
+[Full Changelog](https://github.com/chef/chef/compare/v12.17.44...v12.18.31)
+
+**Implemented enhancements:**
+
+- yum\_repository: Allow baseurl to be an array & allow fastestmirror\_enabled false [\#5708](https://github.com/chef/chef/pull/5708) ([tas50](https://github.com/tas50))
+- Adding returns property to chocolatey\_package resource [\#5688](https://github.com/chef/chef/pull/5688) ([Vasu1105](https://github.com/Vasu1105))
+- Code cleanup in the user provider [\#5674](https://github.com/chef/chef/pull/5674) ([lamont-granquist](https://github.com/lamont-granquist))
+- Code cleanup in the group provider [\#5673](https://github.com/chef/chef/pull/5673) ([lamont-granquist](https://github.com/lamont-granquist))
+- Core: Formally deprecate run\_command [\#5666](https://github.com/chef/chef/pull/5666) ([lamont-granquist](https://github.com/lamont-granquist))
+- Set MSI Scheduled Task name to match chef-client cookbook managed name [\#5657](https://github.com/chef/chef/pull/5657) ([mwrock](https://github.com/mwrock))
+- remove Chef::Platform::HandlerMap [\#5636](https://github.com/chef/chef/pull/5636) ([lamont-granquist](https://github.com/lamont-granquist))
+- Core: Properly deprecate old Chef::Platform methods [\#5631](https://github.com/chef/chef/pull/5631) ([lamont-granquist](https://github.com/lamont-granquist))
+
+**Fixed bugs:**
+
+- Fix error thrown by solo when run on Windows as SYSTEM [\#5693](https://github.com/chef/chef/pull/5693) ([scottopherson](https://github.com/scottopherson))
+- Report a blank resource if sensitive is enabled [\#5668](https://github.com/chef/chef/pull/5668) ([afiune](https://github.com/afiune))
+- Ensure node.docker? returns boolean [\#5645](https://github.com/chef/chef/pull/5645) ([andrewjamesbrown](https://github.com/andrewjamesbrown))
+- Fix Data Collector organization parsing regex [\#5630](https://github.com/chef/chef/pull/5630) ([adamleff](https://github.com/adamleff))
+- Core: Use object ID when detected unprocessed Resources [\#5604](https://github.com/chef/chef/pull/5604) ([adamleff](https://github.com/adamleff))
+
+**Merged pull requests:**
+
+- Core: fix node attribute "unless" API methods [\#5717](https://github.com/chef/chef/pull/5717) ([lamont-granquist](https://github.com/lamont-granquist))
+
+## [v12.17.44](https://github.com/chef/chef/tree/v12.17.44) (2016-12-07)
+[Full Changelog](https://github.com/chef/chef/compare/v12.16.42...v12.17.44)
+
+**Implemented enhancements:**
+
+- Action :umount for mount resource is an obtuse anachronism [\#5595](https://github.com/chef/chef/issues/5595)
+- Core: Update ohai resource to new style, stop overwriting name property [\#5607](https://github.com/chef/chef/pull/5607) ([adamleff](https://github.com/adamleff))
+- Linux: mount provider - skip device detection for zfs [\#5603](https://github.com/chef/chef/pull/5603) ([ttr](https://github.com/ttr))
+- Core: Ensure chef-solo creates node files w/ correct permissions [\#5601](https://github.com/chef/chef/pull/5601) ([scottopherson](https://github.com/scottopherson))
+- Resources: Add unmount as an alias to umount in the mount resource [\#5599](https://github.com/chef/chef/pull/5599) ([shortdudey123](https://github.com/shortdudey123))
+- Core: Update Data Collector to use Chef::JSONCompat [\#5590](https://github.com/chef/chef/pull/5590) ([adamleff](https://github.com/adamleff))
+- Knife: Add ability to pass multiple nodes to knife node/client delete [\#5572](https://github.com/chef/chef/pull/5572) ([jeunito](https://github.com/jeunito))
+- Core: Data Collector debug log should output JSON [\#5570](https://github.com/chef/chef/pull/5570) ([adamleff](https://github.com/adamleff))
+- Yum: Purge yum cache before deleting repo config [\#5509](https://github.com/chef/chef/pull/5509) ([iancward](https://github.com/iancward))
+- Knife Bootstrap: Passing config\_log\_level and config\_log\_location from config.rb [\#5502](https://github.com/chef/chef/pull/5502) ([dheerajd-msys](https://github.com/dheerajd-msys))
+
+**Fixed bugs:**
+
+- Custom Resources: Undefined method up\_to\_date thrown by Chef 12.16.42 [\#5593](https://github.com/chef/chef/issues/5593)
+- Core: Ensure deprecation messages are always included [\#5618](https://github.com/chef/chef/pull/5618) ([thommay](https://github.com/thommay))
+- Core: Fix bug where Access Controls on existing symlink resources would be ignored on first chef-client run [\#5616](https://github.com/chef/chef/pull/5616) ([tduffield](https://github.com/tduffield))
+- The suggested fix for the manage\_home deprecation is incorrect [\#5615](https://github.com/chef/chef/pull/5615) ([tas50](https://github.com/tas50))
+- change choco -version to choco --version [\#5613](https://github.com/chef/chef/pull/5613) ([spuder](https://github.com/spuder))
+- Knife: Correct example `chef\_server\_url` in `knife configure` [\#5602](https://github.com/chef/chef/pull/5602) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
+- Windows: Ensure correct version of shutdown is called when using the reboot resource [\#5596](https://github.com/chef/chef/pull/5596) ([Xoph](https://github.com/Xoph))
+- Windows: Support for running cab\_package on non-English system locales [\#5591](https://github.com/chef/chef/pull/5591) ([jugatsu](https://github.com/jugatsu))
+- Core: Ensure Data Collector resource report exists before updating [\#5571](https://github.com/chef/chef/pull/5571) ([adamleff](https://github.com/adamleff))
+- Windows: Use the full path to expand.exe for msu\_package [\#5564](https://github.com/chef/chef/pull/5564) ([NimishaS](https://github.com/NimishaS))
+- Unset http\[s\]\_proxy in the subversion spec [\#5562](https://github.com/chef/chef/pull/5562) ([stefanor](https://github.com/stefanor))
+- Core: fix Lint/UnifiedInteger cop [\#5547](https://github.com/chef/chef/pull/5547) ([lamont-granquist](https://github.com/lamont-granquist))
+- Core: fix ImmutableArray slices [\#5541](https://github.com/chef/chef/pull/5541) ([lamont-granquist](https://github.com/lamont-granquist))
+- Prevent apt\_update failures on non-Linux platforms [\#5524](https://github.com/chef/chef/pull/5524) ([tas50](https://github.com/tas50))
+- Core: Ensure that the sensitive property is correctly accessed [\#5508](https://github.com/chef/chef/pull/5508) ([axos88](https://github.com/axos88))
+
+**Closed issues:**
+
+- cab\_package doesn't support running on non-English system locales [\#5592](https://github.com/chef/chef/issues/5592)
+- Support restarting/stopping/ the service from state paused on windows [\#5586](https://github.com/chef/chef/issues/5586)
+
+## [v12.16.42](https://github.com/chef/chef/tree/v12.16.42) (2016-11-04)
+[Full Changelog](https://github.com/chef/chef/compare/v12.15.19...v12.16.42)
+
+**Implemented enhancements:**
+
+- Core: improve readability of property-resource namespace collision exception message [\#5500](https://github.com/chef/chef/pull/5500) ([lamont-granquist](https://github.com/lamont-granquist))
+- Omnibus: Pull in Ohai 8.21.0 and other new deps [\#5499](https://github.com/chef/chef/pull/5499) ([tas50](https://github.com/tas50))
+- Core: Add deprecations to Data Collector run completion messages [\#5496](https://github.com/chef/chef/pull/5496) ([adamleff](https://github.com/adamleff))
+- Core: add attribute\_changed hook to event handlers [\#5495](https://github.com/chef/chef/pull/5495) ([lamont-granquist](https://github.com/lamont-granquist))
+- Knife: Add the `--field-separator` flag to knife show commands [\#5489](https://github.com/chef/chef/pull/5489) ([tduffield](https://github.com/tduffield))
+- Core: Enable Signed Header Auth for Data Collector, and Configure the Data Collector Automatically [\#5487](https://github.com/chef/chef/pull/5487) ([danielsdeleo](https://github.com/danielsdeleo))
+- Core: set use\_inline\_resources in package superclass [\#5483](https://github.com/chef/chef/pull/5483) ([lamont-granquist](https://github.com/lamont-granquist))
+- Package: Add new "lock" action for apt, yum and zypper packages [\#5395](https://github.com/chef/chef/pull/5395) ([yeoldegrove](https://github.com/yeoldegrove))
+
+**Fixed bugs:**
+
+- Enable data collector w/o token for solo, but require explicit URL [\#5511](https://github.com/chef/chef/pull/5511) ([danielsdeleo](https://github.com/danielsdeleo))
+- Core: Include chef/chef\_class in Chef::REST for method log\_deprecation [\#5504](https://github.com/chef/chef/pull/5504) ([smalltown](https://github.com/smalltown))
+- Knife: Updating knife ssl fetch to correctly store certificate when it does not have a CN [\#5498](https://github.com/chef/chef/pull/5498) ([tyler-ball](https://github.com/tyler-ball))
+- Knife: Fixed knife download cookbooks issue which used to corrupt the certificate files each time the command was fired. [\#5494](https://github.com/chef/chef/pull/5494) ([Aliasgar16](https://github.com/Aliasgar16))
+- Solaris: Properly check lock status of users on solaris2 [\#5486](https://github.com/chef/chef/pull/5486) ([tduffield](https://github.com/tduffield))
+- Solaris: Fix IPS package must create symlinks to package commands [\#5485](https://github.com/chef/chef/pull/5485) ([jaymalasinha](https://github.com/jaymalasinha))
+
## [v12.15.19](https://github.com/chef/chef/tree/v12.15.19) (2016-10-07)
[Full Changelog](https://github.com/chef/chef/compare/v12.14.89...v12.15.19)
@@ -1240,4 +1328,4 @@ of partial templates.
would not share the same actions/default_action as their parent
* Raise error if a guard_interpreter is specified and a block is passed to a guard (conditional)
* Allow specifying a guard_interpreter after a conditional on a resource (Fixes #1943)
-* Windows package type should be a symbol (Fixes #1997)
+* Windows package type should be a symbol (Fixes #1997) \ No newline at end of file
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 6e4ec2fc3f..0034f46adc 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -18,9 +18,7 @@ a maintainer, lieutenant, or the project lead.
## Chef Core
-Handles the core parts of the Chef DSL, base resource and provider
-infrastructure, the Chef applications and [omnibus-chef](https://github.com/chef/omnibus-chef). Includes anything not covered by
-another component.
+Maintainers for the Chef client, Ohai, mixlibs, ChefDK, ChefSpec, Foodcritic, chefstyle, and sundry others.
To mention the team, use @chef/client-core
@@ -38,55 +36,16 @@ To mention the team, use @chef/client-core
* [Jay Mundrawala](https://github.com/jaym)
* [John Keiser](https://github.com/jkeiser)
* [Jon Cowie](https://github.com/jonlives)
+* [Joshua Timberman](https://github.com/jtimberman)
* [Lamont Granquist](https://github.com/lamont-granquist)
* [Claire McQuin](https://github.com/mcquin)
-* [Steven Murawski](https://github.com/smurawski)
-* [Tim Smith](https://github.com/tas50)
-* [Tyler Ball](https://github.com/tyler-ball)
-* [Ranjib Dey](https://github.com/ranjib)
* [Matt Wrock](https://github.com/mwrock)
-
-## Ohai
-
-To mention the team, use @chef/ohai
-
-### Lieutenant
-
-* [Claire McQuin](https://github.com/mcquin)
-
-### Maintainers
-
-* [Bryan McLellan](https://github.com/btm)
-* [Tim Smith](https://github.com/tas50)
-
-## Dev Tools
-
-ChefDK, Chef Zero, Knife, Chef Apply and Chef Shell.
-To mention the team, use @chef/client-dev-tools
-
-### Maintainers
-
-* [Daniel DeLeo](https://github.com/danielsdeleo)
-* [John Keiser](https://github.com/jkeiser)
-* [Joshua Timberman](https://github.com/jtimberman)
-* [Lamont Granquist](https://github.com/lamont-granquist)
+* [Ranjib Dey](https://github.com/ranjib)
+* [Steven Murawski](https://github.com/smurawski)
* [Steven Danna](https://github.com/stevendanna)
-
-## Test Tools
-
-ChefSpec
-To mention the team, use @chef/client-test-tools
-
-### Lieutenant
-
-* [Seth Vargo](https://github.com/sethvargo)
-
-### Maintainers
-
-* [Joshua Timberman](https://github.com/jtimberman)
-* [Lamont Granquist](https://github.com/lamont-granquist)
* [Tim Smith](https://github.com/tas50)
-* [Ranjib Dey](https://github.com/ranjib)
+* [Tom Duffield](https://github.com/tduffield)
+* [Tyler Ball](https://github.com/tyler-ball)
## Chef Provisioning
@@ -101,9 +60,9 @@ To mention the team, use @chef/provisioning
### Maintainers
* [John Keiser](https://github.com/jkeiser)
-* [Stuart Preston](https://github.com/stuartpreston)
* [JJ Asghar](https://github.com/jjasghar)
* [João Cravo](https://github.com/joaogbcravo)
+* [Stuart Preston](https://github.com/stuartpreston)
* [Harley Alaniz](https://github.com/thehar)
## Platform Specific Components
diff --git a/MAINTAINERS.toml b/MAINTAINERS.toml
index e78316e144..a46953aac1 100644
--- a/MAINTAINERS.toml
+++ b/MAINTAINERS.toml
@@ -28,9 +28,7 @@ a maintainer, lieutenant, or the project lead.
title = "Chef Core"
team = "client-core"
text = """
-Handles the core parts of the Chef DSL, base resource and provider
-infrastructure, the Chef applications and [omnibus-chef](https://github.com/chef/omnibus-chef). Includes anything not covered by
-another component.
+Maintainers for the Chef client, Ohai, mixlibs, ChefDK, ChefSpec, Foodcritic, chefstyle, and sundry others.
"""
lieutenant = "thommay"
@@ -44,59 +42,16 @@ another component.
"jaym",
"jkeiser",
"jonlives",
+ "jtimberman",
"lamont-granquist",
"mcquin",
- "smurawski",
- "tas50",
- "tyler-ball",
+ "mwrock",
"ranjib",
- "mwrock"
- ]
-
- [Org.Components.Ohai]
- title = "Ohai"
- team = "ohai"
-
- lieutenant = "mcquin"
-
- maintainers = [
- "btm",
- "tas50"
- ]
-
- [Org.Components.DevTools]
- title = "Dev Tools"
- team = "client-dev-tools"
- text = "ChefDK, Chef Zero, Knife, Chef Apply and Chef Shell."
-
- paths = [
- "lib/chef/knife.rb",
- "lib/chef/knife/",
- "spec/functional/knife/",
- "spec/integration/knife/",
- "spec/unit/knife/"
- ]
-
- maintainers = [
- "danielsdeleo",
- "jkeiser",
- "jtimberman",
- "lamont-granquist",
- "stevendanna"
- ]
-
- [Org.Components.TestTools]
- title = "Test Tools"
- team = "client-test-tools"
- text = "ChefSpec"
-
- lieutenant = "sethvargo"
-
- maintainers = [
- "jtimberman",
- "lamont-granquist",
+ "smurawski",
+ "stevendanna",
"tas50",
- "ranjib"
+ "tduffield",
+ "tyler-ball"
]
[Org.Components.Provisioning]
@@ -110,9 +65,9 @@ Chef Provisioning and Drivers. Supported Drivers are listed in the [README](htt
maintainers = [
"jkeiser",
- "stuartpreston",
"jjasghar",
"joaogbcravo",
+ "stuartpreston",
"thehar"
]
@@ -424,3 +379,7 @@ The specific components of Chef related to a given platform - including (but not
[people.thehar]
Name = "Harley Alaniz"
GitHub = "thehar"
+
+ [people.tduffield]
+ Name = "Tom Duffield"
+ GitHub = "tduffield"
diff --git a/README.md b/README.md
index 99f2ba4063..cc61509fde 100644
--- a/README.md
+++ b/README.md
@@ -2,14 +2,15 @@
[![Code Climate](https://codeclimate.com/github/chef/chef.svg)](https://codeclimate.com/github/chef/chef)
[![Build Status Master](https://travis-ci.org/chef/chef.svg?branch=master)](https://travis-ci.org/chef/chef)
[![Build Status Master](https://ci.appveyor.com/api/projects/status/github/chef/chef?branch=master&svg=true&passingText=master%20-%20Ok&pendingText=master%20-%20Pending&failingText=master%20-%20Failing)](https://ci.appveyor.com/project/Chef/chef/branch/master)
+[![Gem Version](https://badge.fury.io/rb/chef.svg)](https://badge.fury.io/rb/chef)
Want to try Chef? Get started with [learnchef](https://learn.chef.io)
-* Documentation: [https://docs.chef.io](https://docs.chef.io)
-* Source: [https://github.com/chef/chef/tree/master](https://github.com/chef/chef/tree/master)
-* Tickets/Issues: [https://github.com/chef/chef/issues](https://github.com/chef/chef/issues)
-* Slack: [Chef Community Slack](https://community-slack.chef.io/)
-* Mailing list: [https://discourse.chef.io](https://discourse.chef.io)
+- Documentation: <https://docs.chef.io>
+- Source: <https://github.com/chef/chef/tree/master>
+- Tickets/Issues: <https://github.com/chef/chef/issues>
+- Slack: [Chef Community Slack](https://community-slack.chef.io/)
+- Mailing list: <https://discourse.chef.io>
Chef is a configuration management tool designed to bring automation to your
entire infrastructure.
@@ -17,15 +18,16 @@ entire infrastructure.
This README focuses on developers who want to modify Chef source code.
If you just want to use Chef, check out these resources:
-* [learnchef](https://learn.chef.io): Getting started guide
-* [docs.chef.io](https://docs.chef.io): Comprehensive User Docs
-* [Installer Downloads](https://downloads.chef.io/chef-client/): Install Chef as a complete package
+- [learnchef](https://learn.chef.io): Getting started guide
+- [docs.chef.io](https://docs.chef.io): Comprehensive User Docs
+- [Installer Downloads](https://downloads.chef.io/chef/): Install Chef as a complete package
+- [chef/chef](https://hub.docker.com/r/chef/chef): Docker image for use with [kitchen-dokken](https://github.com/someara/kitchen-dokken)
## Installing From Git
**NOTE:** Unless you have a specific reason to install from source (to
try a new feature, contribute a patch, or run chef on an OS for which no
-package is available), you should head to the [downloads page](https://downloads.chef.io/chef-client/)
+package is available), you should head to the [downloads page](https://downloads.chef.io/chef/)
to get a prebuilt package.
### Prerequisites
@@ -72,11 +74,10 @@ The general development process is:
1. Fork this repo and clone it to your workstation.
2. Create a feature branch for your change.
3. Write code and tests.
-4. Push your feature branch to github and open a pull request against
- master.
+4. Push your feature branch to github and open a pull request against master.
Once your repository is set up, you can start working on the code. We do utilize
-RSpec for test driven development, so you'll need to get a development
+RSpec for test driven development, so you'll need to get a development
environment running. Follow the above procedure ("Installing from Git") to get
your local copy of the source running.
@@ -90,7 +91,7 @@ Note that this repository is primarily for reporting chef-client issues.
For reporting issues against other Chef projects, please look up the appropriate repository
to report issues against in the Chef docs in the
[community contributions section](https://docs.chef.io/community_contributions.html#issues-and-bug-reports).
-If you can't detemine the appropriate place to report an issue, then please open it
+If you can't determine the appropriate place to report an issue, then please open it
against the repository you think best fits and it will be directed to the appropriate project.
## Testing
@@ -156,18 +157,32 @@ Whenever a change is checked in to `master`, the patch version of `chef` is bump
1. Bumps the patch version in `lib/chef/version.rb` (e.g. 0.9.14 -> 0.9.15).
2. Runs `rake bundle:install` to update the `Gemfile.lock` to include the new version.
-3. Pushes to `master` and submits a new build to Chef's Jenkins cluster.
+3. Runs `rake changelog:update` to update the `CHANGELOG.md`.
+4. Pushes to `master` and submits a new build to Chef's Jenkins cluster.
## Bumping the minor version of Chef
After each "official" stable release we need to bump the minor version. To do this:
-1. Manually increment the minor version in the VERSION file that is in the root of this repo. and reset the patch version to 0. Assuming the current version is `12.10.57` you would edit `VERSION` to be `12.11.0`.
-2. Run `bundle exec rake version` which will copy the version to the respective `version.rb` files in chef and chef-config.
-3. Run `bundle exec rake bundle:install` to update the base Gemfile.lock
+1. Run `bundle exec rake version:bump_minor`
Submit a PR with the changes made by the above.
+## Addressing a Regression
+
+Sometimes, regressions split through the cracks. Since new functionality is always being added and the minor version is bumped immediately after release, we can't simply roll forward. In this scenario, we'll need to perform a special regression release process. In the example that follows, the stable release with a regression is `1.10.60` while master is currently sitting at `1.11.30`. *Note:* To perform this process, you must be a Chef employee.
+
+1. If the regression has not already been addressed, open a Pull Request against master with the fix.
+2. Wait until that Pull Request has been merged and `1.11.31` has passed all the necessary tests and is available in the current channel.
+3. Inspect the Git history and find the `SHA` associated with the Merge Commit for the Pull Request above.
+4. Apply the fix for the regression via a cherry-pick:
+ 1. Check out the stable release tag: `git checkout v1.10.60`
+ 2. Cherry Pick the SHA with the fix: `git cherry-pick SHA`
+ 3. Address any conflicts (if necessary)
+ 4. Tag the sha with the appropriate version: `git tag -a v1.10.61 -m "Release v1.10.61"`
+ 5. Push the new tag to origin: `git push origin --tags`
+5. Log in to Jenkins and trigger a `chef-trigger-release` job specifying the new tag as the `GIT_REF`.
+
## Component Versions
Chef has two sorts of component: ruby components like `berkshelf` and `test-kitchen`, and binary components like `openssl` and even `ruby` itself.
@@ -228,7 +243,7 @@ bundle install
bundle exec omnibus build chef
```
-This causes the [chef project definition](omnibus/config/projects/chef.rb) to load, which runs the [chef-complete](omnibus/config/software/chef-complete.rb) software definition, the primary software definition driving the whole build process. The reason we embed it all in a software definiton instead of the project is to take advantage of omnibus caching: omnibus will invalidate the entire project (and recompile ruby, openssl, and everything else) if you change anything at all in the project file. Not so with a software definition.
+This causes the [chef project definition](omnibus/config/projects/chef.rb) to load, which runs the [chef-complete](omnibus/config/software/chef-complete.rb) software definition, the primary software definition driving the whole build process. The reason we embed it all in a software definition instead of the project is to take advantage of omnibus caching: omnibus will invalidate the entire project (and recompile ruby, openssl, and everything else) if you change anything at all in the project file. Not so with a software definition.
### Installing the Gems
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 986519fa4a..7f68425e8b 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,89 +1,146 @@
-*This file holds "in progress" release notes for the current release under development and is intended for consumption by the Chef Documentation team.
-Please see [https://docs.chef.io/release_notes.html](https://docs.chef.io/release_notes.html) for the official Chef release notes.*
+_This file holds "in progress" release notes for the current release under development and is intended for consumption by the Chef Documentation team. Please see <https://docs.chef.io/release_notes.html> for the official Chef release notes._
-# Chef Client Release Notes 12.16:
+# Chef Client Release Notes 12.19:
## Highlighted enhancements for this release:
-### `attribute_changed` event hook
+- Systemd unit files are now verified before being installed.
+- Added support for windows alternate user identity in execute resources.
+- Added ed25519 key support for for ssh connections.
-In a cookbook library file, you can add this in order to print out all attribute changes in cookbooks:
+### Windows alternate user identity execute support
+
+The `execute` resource and similar resources such as `script`, `batch`, and `powershell_script` now support the specification of credentials on Windows so that the resulting process is created with the security identity that corresponds to those credentials.
+
+**Note**: When Chef is running as a service, this feature requires that the user that Chef runs as has 'SeAssignPrimaryTokenPrivilege' (aka 'SE_ASSIGNPRIMARYTOKEN_NAME') user right. By default only LocalSystem and NetworkService have this right when running as a service. This is necessary even if the user is an Administrator.
+
+This right bacn be added and checked in a recipe using this example:
```ruby
-Chef.event_handler do
- on :attribute_changed do |precedence, key, value|
- puts "setting attribute #{precedence}#{key.map {|n| "[\"#{n}\"]" }.join} = #{value}"
- end
-end
+# Add 'SeAssignPrimaryTokenPrivilege' for the user
+Chef::ReservedNames::Win32::Security.add_account_right('<user>', 'SeAssignPrimaryTokenPrivilege')
+
+# Check if the user has 'SeAssignPrimaryTokenPrivilege' rights
+Chef::ReservedNames::Win32::Security.get_account_right('<user>').include?('SeAssignPrimaryTokenPrivilege')
```
-If you want to setup a policy that override attributes should never be used:
+#### Properties
+
+The following properties are new or updated for the `execute`, `script`, `batch`, and `powershell_script` resources and any resources derived from them:
+
+- `user`<br>
+ **Ruby types:** String<br>
+ The user name of the user identity with which to launch the new process. Default value: `nil`. The user name may optionally be specified with a domain, i.e. `domain\user` or `user@my.dns.domain.com` via Universal Principal Name (UPN) format. It can also be specified without a domain simply as `user` if the domain is instead specified using the `domain` attribute. On Windows only, if this property is specified, the `password` property **must** be specified.
+
+- `password`<br>
+ **Ruby types** String<br>
+ _Windows only:_ The password of the user specified by the `user` property. Default value: `nil`. This property is mandatory if `user` is specified on Windows and may only be specified if `user` is specified. The `sensitive` property for this resource will automatically be set to `true` if `password` is specified.
+
+- `domain`<br>
+ **Ruby types** String<br>
+ _Windows only:_ The domain of the user user specified by the `user` property. Default value: `nil`. If not specified, the user name and password specified by the `user` and `password` properties will be used to resolve that user against the domain in which the system running Chef client is joined, or if that system is not joined to a domain it will resolve the user as a local account on that system. An alternative way to specify the domain is to leave this property unspecified and specify the domain as part of the `user` property.
+
+#### Usage
+
+The following examples explain how alternate user identity properties can be used in the execute resources:
```ruby
-Chef.event_handler do
- on :attribute_changed do |precedence, key, value|
- raise "override policy violation" if precedence == :override
- end
+powershell_script 'create powershell-test file' do
+ code <<-EOH
+ $stream = [System.IO.StreamWriter] "#{Chef::Config[:file_cache_path]}/powershell-test.txt"
+ $stream.WriteLine("In #{Chef::Config[:file_cache_path]}...word.")
+ $stream.close()
+ EOH
+ user 'username'
+ password 'password'
+end
+
+execute 'mkdir test_dir' do
+ cwd Chef::Config[:file_cache_path]
+ domain "domain-name"
+ user "user"
+ password "password"
+end
+
+script 'create test_dir' do
+ interpreter "bash"
+ code "mkdir test_dir"
+ cwd Chef::Config[:file_cache_path]
+ user "domain-name\\username"
+ password "password"
end
-```
-There will likely be some missed attribute changes and some bugs that need fixing (hint: PRs accepted), there could be
-added command line options to print out all attribute changes or filter them (hint: PRs accepted), or to add source
-file and line numbers to the event (hint: PRs accepted).
-
-### Automatic connection to Chef Automate's Data Collector with supported Chef Server
-
-Chef Client will automatically attempt to connect to the Chef Server
-authenticated data collector proxy. If you have a supported version of
-Chef Server and have enabled this feature on the Chef Server, Chef
-Client run data will automatically be forwarded to Automate without
-additional Chef Client configuration. If you do not have Automate or the
-feature is disabled on the Chef Server, Chef Client will detect this and
-disable data collection.
-
-Note that Chef Server 12.11.0+ (not yet released as of the time this was
-written) is required for this feature.
-
-### RFC018 Partially Implemented: Specify `--field-separator` for attribute filtering
-
-If you have periods (`.`) in your Chef Node attribute keys, you can now pass
-the `--field-separator` (or `-S`) flag along with your `--attribute` (or `-a`)
-flag to specify a custom nesting character other than `.`.
-
-In a situation where the *webapp* node has the following node data:
-```json
-{
- "foo.bar": "baz",
- "alpha": {
- "beta": "omega"
- }
-}
+batch 'create test_dir' do
+ code "mkdir test_dir"
+ cwd Chef::Config[:file_cache_path]
+ user "username@domain-name"
+ password "password"
+end
```
-Running `knife node show` with the default field separator (`.`) won't show
-us the data we're expecting for some attributes:
+## Highlighted bug fixes for this release:
-```shell
-$ knife node show webapp -a foo.bar
-webapp:
- foo.bar:
+- Ensure that the Windows Administrator group can access the chef-solo nodes directory
+- When loading a cookbook in Chef Solo, use `metadata.json` in preference to `metadata.rb`
-$ knife node show webapp -a alpha.beta
-webapp:
- alpha.beta: omega
-```
+# Ohai Release Notes 8.23:
-However, by specifying a field separator other than `.` we're now able to show
-the data.
+## Cumulus Linux Platform
-```shell
-$ knife node show webapp -S: -a foo.bar
-webapp:
- foo.bar: baz
+Cumulus Linux will now be detected as platform `cumulus` instead of `debian` and the `platform_version` will be properly set to the Cumulus Linux release.
-$ knife node show webapp -S: -a alpha:beta
-webapp:
- alpha:beta: omega
-```
+## Virtualization Detection
-## Highlighted bug fixes for this release:
+Windows / Linux / BSD guests running on the Veertu hypervisors will now be detected
+
+Windows guests running on Xen and Hyper-V hypervisors will now be detected
+
+## New Sysconf Plugin
+
+A new plugin parses the output of the sysconf command to provide information on the underlying system.
+
+## AWS Account ID
+
+The EC2 plugin now fetches the AWS Account ID in addition to previous instance metadata
+
+## GCC Detection
+
+GCC detection has been improved to collect additional information, and to not prompt for the installation of Xcode on macOS systems
+
+## New deprecations introduced in this release:
+
+### Ohai::Config removed
+
+- **Deprecation ID**: OHAI-1
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_legacy_config.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### sigar gem based plugins removed
+
+- **Deprecation ID**: OHAI-2
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_sigar_plugins.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### run_command and popen4 helper methods removed
+
+- **Deprecation ID**: OHAI-3
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_run_command_helpers.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### libvirt plugin attributes moved
+
+- **Deprecation ID**: OHAI-4
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_libvirt_plugin.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### Windows CPU plugin attribute changes
+
+- **Deprecation ID**: OHAI-5
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_windows_cpu.html>
+- **Expected Removal**: Ohai 13 (April 2017)
+
+### DigitalOcean plugin attribute changes
+
+- **Deprecation ID**: OHAI-6
+- **Remediation Docs**: <https://docs.chef.io/deprecations_ohai_digitalocean.html>
+- **Expected Removal**: Ohai 13 (April 2017)
diff --git a/Rakefile b/Rakefile
index 98216cf5fd..311639230b 100644
--- a/Rakefile
+++ b/Rakefile
@@ -28,6 +28,7 @@ require_relative "tasks/maintainers"
require_relative "tasks/cbgb"
require_relative "tasks/dependencies"
require_relative "tasks/changelog"
+require_relative "tasks/announce"
ChefConfig::PackageTask.new(File.expand_path("..", __FILE__), "Chef", "chef") do |package|
package.component_paths = ["chef-config"]
@@ -37,6 +38,22 @@ end
task "version:bump" => %w{version:bump_patch version:update}
task "version:bump" => %w{version:bump_patch version:update}
+task "version:bump_minor" do
+ Rake::Task["changelog:archive"].invoke
+ maj, min, _build = Chef::VERSION.split(".")
+ File.open("VERSION", "w+") { |f| f.write("#{maj}.#{min.to_i + 1}.0") }
+ Rake::Task["version"].invoke
+ Rake::Task["bundle:install"].invoke
+end
+
+task "version:bump_major" do
+ Rake::Task["changelog:archive"].invoke
+ maj, _min, _build = Chef::VERSION.split(".")
+ File.open("VERSION", "w+") { |f| f.write("#{maj.to_i + 1}.0.0") }
+ Rake::Task["version"].invoke
+ Rake::Task["bundle:install"].invoke
+end
+
task :pedant, :chef_zero_spec
task :build_eventlog do
@@ -51,6 +68,15 @@ task :register_eventlog do
end
end
+desc "Keep the Dockerfile up-to-date"
+task :update_dockerfile do
+ require "mixlib/install"
+ latest_stable_version = Mixlib::Install.available_versions("chef", "stable").last
+ text = File.read("Dockerfile")
+ new_text = text.gsub(/^ARG VERSION=[\d\.]+$/, "ARG VERSION=#{latest_stable_version}")
+ File.open("Dockerfile", "w+") { |f| f.write(new_text) }
+end
+
begin
require "chefstyle"
require "rubocop/rake_task"
diff --git a/VERSION b/VERSION
index 2e8cb7a110..40d1f067de 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-12.16.49 \ No newline at end of file
+12.19.30 \ No newline at end of file
diff --git a/acceptance/Gemfile b/acceptance/Gemfile
index 59f232fcd3..41a18c9914 100644
--- a/acceptance/Gemfile
+++ b/acceptance/Gemfile
@@ -1,16 +1,16 @@
source "https://rubygems.org"
+gem "rake" # required to build some native extensions
gem "chef-acceptance", github: "chef/chef-acceptance"
gem "kitchen-ec2"
gem "inspec"
-# Pinning to github for kitchen-vagrant because 0.19.0 incorrectly
-# puts in a box_url for bento when a vagrant box in atlas is specified
gem "kitchen-vagrant"
gem "windows_chef_zero"
gem "kitchen-inspec"
gem "test-kitchen"
gem "winrm-elevated"
-gem "berkshelf", "4.3.5"
+gem "berkshelf"
-# until 2.0.0 is fixed for unstable packages
+# Pin to 1.2.3 because current mixlib-install has a problem where unstable
+# packages are not always immediately available via the omnitruck API.
gem "mixlib-install", "1.2.3"
diff --git a/acceptance/Gemfile.lock b/acceptance/Gemfile.lock
index 4299609f91..8dfb2ec217 100644
--- a/acceptance/Gemfile.lock
+++ b/acceptance/Gemfile.lock
@@ -9,75 +9,77 @@ GIT
GEM
remote: https://rubygems.org/
specs:
- addressable (2.4.0)
- artifactory (2.5.0)
- aws-sdk (2.6.14)
- aws-sdk-resources (= 2.6.14)
- aws-sdk-core (2.6.14)
+ addressable (2.5.0)
+ public_suffix (~> 2.0, >= 2.0.2)
+ artifactory (2.6.0)
+ aws-sdk (2.7.5)
+ aws-sdk-resources (= 2.7.5)
+ aws-sdk-core (2.7.5)
+ aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-resources (2.6.14)
- aws-sdk-core (= 2.6.14)
- berkshelf (4.3.5)
+ aws-sdk-resources (2.7.5)
+ aws-sdk-core (= 2.7.5)
+ aws-sigv4 (1.0.0)
+ berkshelf (5.6.2)
addressable (~> 2.3, >= 2.3.4)
- berkshelf-api-client (~> 2.0, >= 2.0.2)
- buff-config (~> 1.0)
- buff-extensions (~> 1.0)
- buff-shell_out (~> 0.1)
- celluloid (= 0.16.0)
- celluloid-io (~> 0.16.1)
+ berkshelf-api-client (>= 2.0.2, < 4.0)
+ buff-config (~> 2.0)
+ buff-extensions (~> 2.0)
+ buff-shell_out (~> 1.0)
cleanroom (~> 1.0)
faraday (~> 0.9)
httpclient (~> 2.7)
minitar (~> 0.5, >= 0.5.4)
- mixlib-archive (~> 0.1)
+ mixlib-archive (~> 0.4)
octokit (~> 4.0)
retryable (~> 2.0)
- ridley (~> 4.5)
- solve (~> 2.0)
- thor (~> 0.19)
- berkshelf-api-client (2.0.2)
- faraday (~> 0.9.1)
- httpclient (~> 2.7.0)
- ridley (~> 4.5)
- buff-config (1.0.1)
- buff-extensions (~> 1.0)
- varia_model (~> 0.4)
- buff-extensions (1.0.0)
- buff-ignore (1.1.1)
- buff-ruby_engine (0.1.0)
- buff-shell_out (0.2.0)
- buff-ruby_engine (~> 0.1.0)
- builder (3.2.2)
+ ridley (~> 5.0)
+ solve (> 2.0, < 4.0)
+ thor (~> 0.19, < 0.19.2)
+ berkshelf-api-client (3.0.0)
+ faraday (~> 0.9)
+ httpclient (~> 2.7)
+ ridley (>= 4.5, < 6.0)
+ buff-config (2.0.0)
+ buff-extensions (~> 2.0)
+ varia_model (~> 0.6)
+ buff-extensions (2.0.0)
+ buff-ignore (1.2.0)
+ buff-ruby_engine (1.0.0)
+ buff-shell_out (1.1.0)
+ buff-ruby_engine (~> 1.0)
+ builder (3.2.3)
celluloid (0.16.0)
timers (~> 4.0.0)
celluloid-io (0.16.2)
celluloid (>= 0.16.0)
nio4r (>= 1.1.0)
- chef-config (12.15.19)
+ chef-config (12.18.31)
addressable
fuzzyurl
mixlib-config (~> 2.0)
mixlib-shellout (~> 2.0)
cleanroom (1.0.0)
coderay (1.1.1)
- diff-lcs (1.2.5)
- docker-api (1.32.1)
+ diff-lcs (1.3)
+ docker-api (1.33.2)
excon (>= 0.38.0)
json
erubis (2.7.0)
- excon (0.54.0)
+ excon (0.55.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
- ffi (1.9.14)
+ ffi (1.9.17)
fuzzyurl (0.9.0)
gssapi (1.2.0)
ffi (>= 1.0.1)
gyoku (1.3.1)
builder (>= 2.1.2)
- hashie (3.4.6)
+ hashie (3.5.1)
hitimes (1.2.4)
- httpclient (2.7.2)
- inspec (1.3.0)
+ httpclient (2.8.3)
+ inspec (1.14.1)
+ faraday (>= 0.9.0)
hashie (~> 3.4)
json (>= 1.8, < 3.0)
method_source (~> 0.8)
@@ -87,30 +89,32 @@ GEM
rainbow (~> 2)
rspec (~> 3)
rspec-its (~> 1.2)
+ rspec_junit_formatter (~> 0.2.3)
rubyzip (~> 1.1)
sslshake (~> 1)
thor (~> 0.19)
- train (>= 0.20.1, < 1.0)
+ train (>= 0.22.0, < 1.0)
jmespath (1.3.1)
- json (2.0.2)
+ json (2.0.3)
kitchen-ec2 (1.2.0)
aws-sdk (~> 2)
excon
multi_json
retryable (~> 2.0)
test-kitchen (~> 1.4, >= 1.4.1)
- kitchen-inspec (0.15.2)
- inspec (>= 0.22.0, < 2.0.0)
+ kitchen-inspec (0.17.0)
+ hashie (~> 3.4)
+ inspec (>= 0.34.0, < 2.0.0)
test-kitchen (~> 1.6)
- kitchen-vagrant (0.20.0)
+ kitchen-vagrant (1.0.0)
test-kitchen (~> 1.4)
little-plugger (1.1.4)
logging (2.1.0)
little-plugger (~> 1.1)
multi_json (~> 1.10)
method_source (0.8.2)
- minitar (0.5.4)
- mixlib-archive (0.2.0)
+ minitar (0.6.1)
+ mixlib-archive (0.4.1)
mixlib-log
mixlib-authentication (1.4.1)
mixlib-log
@@ -122,31 +126,33 @@ GEM
mixlib-log (1.7.1)
mixlib-shellout (2.2.7)
mixlib-versioning (1.1.0)
- molinillo (0.4.5)
+ molinillo (0.5.6)
multi_json (1.12.1)
multipart-post (2.0.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
- net-ssh (3.2.0)
- net-ssh-gateway (1.2.0)
+ net-ssh (4.0.1)
+ net-ssh-gateway (1.3.0)
net-ssh (>= 2.6.5)
- nio4r (1.2.1)
+ nio4r (2.0.0)
nori (2.6.0)
- octokit (4.4.1)
- sawyer (~> 0.7.0, >= 0.5.3)
- parallel (1.9.0)
+ octokit (4.6.2)
+ sawyer (~> 0.8.0, >= 0.5.3)
+ parallel (1.10.0)
pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
- rainbow (2.1.0)
+ public_suffix (2.0.5)
+ rainbow (2.2.1)
+ rake (12.0.0)
retryable (2.0.4)
- ridley (4.6.1)
+ ridley (5.1.0)
addressable
- buff-config (~> 1.0)
- buff-extensions (~> 1.0)
- buff-ignore (~> 1.1.1)
- buff-shell_out (~> 0.1)
+ buff-config (~> 2.0)
+ buff-extensions (~> 2.0)
+ buff-ignore (~> 1.2)
+ buff-shell_out (~> 1.0)
celluloid (~> 0.16.0)
celluloid-io (~> 0.16.1)
chef-config (>= 12.5.0)
@@ -157,8 +163,8 @@ GEM
json (>= 1.7.7)
mixlib-authentication (>= 1.3.0)
retryable (~> 2.0)
- semverse (~> 1.1)
- varia_model (~> 0.4.0)
+ semverse (~> 2.0)
+ varia_model (~> 0.6)
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
@@ -175,43 +181,46 @@ GEM
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
+ rspec_junit_formatter (0.2.3)
+ builder (< 4)
+ rspec-core (>= 2, < 4, != 2.12.0)
rubyntlm (0.6.1)
- rubyzip (1.2.0)
+ rubyzip (1.2.1)
safe_yaml (1.0.4)
- sawyer (0.7.0)
- addressable (>= 2.3.5, < 2.5)
- faraday (~> 0.8, < 0.10)
- semverse (1.2.1)
+ sawyer (0.8.1)
+ addressable (>= 2.3.5, < 2.6)
+ faraday (~> 0.8, < 1.0)
+ semverse (2.0.0)
slop (3.6.0)
- solve (2.0.3)
- molinillo (~> 0.4.2)
- semverse (~> 1.1)
+ solve (3.1.0)
+ molinillo (>= 0.5)
+ semverse (>= 1.1, < 3.0)
sslshake (1.0.13)
- test-kitchen (1.13.2)
+ test-kitchen (1.15.0)
mixlib-install (>= 1.2, < 3.0)
mixlib-shellout (>= 1.2, < 3.0)
net-scp (~> 1.1)
- net-ssh (>= 2.9, < 4.0)
- net-ssh-gateway (~> 1.2.0)
+ net-ssh (>= 2.9, < 5.0)
+ net-ssh-gateway (~> 1.2)
safe_yaml (~> 1.0)
thor (~> 0.18)
thor (0.19.1)
timers (4.0.4)
hitimes
- train (0.20.1)
+ train (0.22.1)
docker-api (~> 1.26)
json (>= 1.8, < 3.0)
mixlib-shellout (~> 2.0)
net-scp (~> 1.2)
- net-ssh (>= 2.9, < 4.0)
+ net-ssh (>= 2.9, < 5.0)
winrm (~> 2.0)
winrm-fs (~> 1.0)
- varia_model (0.4.1)
- buff-extensions (~> 1.0)
+ varia_model (0.6.0)
+ buff-extensions (~> 2.0)
hashie (>= 2.0.2, < 4.0.0)
windows_chef_zero (2.0.0)
test-kitchen (>= 1.2.1)
- winrm (2.1.0)
+ winrm (2.1.2)
builder (>= 2.1.2)
erubis (~> 2.7)
gssapi (~> 1.2)
@@ -220,10 +229,10 @@ GEM
logging (>= 1.6.1, < 3.0)
nori (~> 2.0)
rubyntlm (~> 0.6.0, >= 0.6.1)
- winrm-elevated (1.0.1)
+ winrm-elevated (1.1.0)
winrm (~> 2.0)
winrm-fs (~> 1.0)
- winrm-fs (1.0.0)
+ winrm-fs (1.0.1)
erubis (~> 2.7)
logging (>= 1.6.1, < 3.0)
rubyzip (~> 1.1)
@@ -233,13 +242,14 @@ PLATFORMS
ruby
DEPENDENCIES
- berkshelf (= 4.3.5)
+ berkshelf
chef-acceptance!
inspec
kitchen-ec2
kitchen-inspec
kitchen-vagrant
mixlib-install (= 1.2.3)
+ rake
test-kitchen
windows_chef_zero
winrm-elevated
diff --git a/appveyor.yml b/appveyor.yml
index 831ecf67e5..e3bf174e01 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -20,16 +20,19 @@ install:
- systeminfo
- winrm quickconfig -q
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
+ - ps: $env:RUBYGEMS_VERSION=$(findstr rubygems omnibus_overrides.rb | %{ $_.split(" ")[3] })
+ - ps: $env:BUNDLER_VERSION=$(findstr bundler omnibus_overrides.rb | %{ $_.split(" ")[3] })
- echo %PATH%
- ruby --version
- - gem update --system || gem update --system || gem update --system
- - gem install bundler --quiet --no-ri --no-rdoc || gem install bundler --quiet --no-ri --no-rdoc || gem install bundler --quiet --no-ri --no-rdoc
- - update_rubygems
+ - gem update --system %RUBYGEMS_VERSION% || gem update --system %RUBYGEMS_VERSION% || gem update --system %RUBYGEMS_VERSION%
+ - gem install bundler -v %BUNDLER_VERSION% --quiet --no-ri --no-rdoc || gem install bundler -v %BUNDLER_VERSION% --quiet --no-ri --no-rdoc || gem install bundler -v %BUNDLER_VERSION% --quiet --no-ri --no-rdoc
- gem --version
- bundler --version
- SET BUNDLE_IGNORE_CONFIG=true
- SET BUNDLE_FROZEN=1
- SET BUNDLE_WITHOUT=development:guard:maintenance:tools:integration:changelog:docgen:travis:style:omnibus_package:aix:bsd:linux:mac_os_x:solaris
+ - appveyor DownloadFile http://curl.haxx.se/ca/cacert.pem -FileName C:\cacert.pem
+ - set SSL_CERT_FILE=C:\cacert.pem
build_script:
- bundle install || bundle install || bundle install
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb
index fb8e19518f..4f2516331d 100644
--- a/chef-config/lib/chef-config/config.rb
+++ b/chef-config/lib/chef-config/config.rb
@@ -45,7 +45,7 @@ module ChefConfig
#
# +filename+ is used for context in stacktraces, but doesn't need to be the name of an actual file.
def self.from_string(string, filename)
- self.instance_eval(string, filename, 1)
+ instance_eval(string, filename, 1)
end
def self.inspect
@@ -56,13 +56,24 @@ module ChefConfig
path = PathHelper.cleanpath(path)
if ChefConfig.windows?
# turns \etc\chef\client.rb and \var\chef\client.rb into C:/chef/client.rb
- if env["SYSTEMDRIVE"] && path[0] == '\\' && path.split('\\')[2] == "chef"
- path = PathHelper.join(env["SYSTEMDRIVE"], path.split('\\', 3)[2])
+ # Some installations will be on different drives so use the drive that
+ # the expanded path to __FILE__ is found.
+ drive = windows_installation_drive
+ if drive && path[0] == '\\' && path.split('\\')[2] == "chef"
+ path = PathHelper.join(drive, path.split('\\', 3)[2])
end
end
path
end
+ def self.windows_installation_drive
+ if ChefConfig.windows?
+ drive = File.expand_path(__FILE__).split("/", 2)[0]
+ drive = ENV["SYSTEMDRIVE"] if drive.to_s == ""
+ drive
+ end
+ end
+
def self.add_formatter(name, file_path = nil)
formatters << [name, file_path]
end
@@ -131,16 +142,16 @@ module ChefConfig
# that upload or download files (such as knife upload, knife role from file,
# etc.) work.
default :chef_repo_path do
- if self.configuration[:cookbook_path]
- if self.configuration[:cookbook_path].kind_of?(String)
- File.expand_path("..", self.configuration[:cookbook_path])
+ if configuration[:cookbook_path]
+ if configuration[:cookbook_path].kind_of?(String)
+ File.expand_path("..", configuration[:cookbook_path])
else
- self.configuration[:cookbook_path].map do |path|
+ configuration[:cookbook_path].map do |path|
File.expand_path("..", path)
end
end
elsif configuration[:cookbook_artifact_path]
- File.expand_path("..", self.configuration[:cookbook_artifact_path])
+ File.expand_path("..", configuration[:cookbook_artifact_path])
else
cache_path
end
@@ -194,7 +205,7 @@ module ChefConfig
# Defaults to <chef_repo_path>/cookbooks. If chef_repo_path
# is not specified, this is set to [/var/chef/cookbooks, /var/chef/site-cookbooks]).
default(:cookbook_path) do
- if self.configuration[:chef_repo_path]
+ if configuration[:chef_repo_path]
derive_path_from_chef_repo_path("cookbooks")
else
Array(derive_path_from_chef_repo_path("cookbooks")).flatten +
@@ -401,10 +412,10 @@ module ChefConfig
default(:chef_server_root) do
# if the chef_server_url is a path to an organization, aka
# 'some_url.../organizations/*' then remove the '/organization/*' by default
- if self.configuration[:chef_server_url] =~ /\/organizations\/\S*$/
- self.configuration[:chef_server_url].split("/")[0..-3].join("/")
- elsif self.configuration[:chef_server_url] # default to whatever chef_server_url is
- self.configuration[:chef_server_url]
+ if configuration[:chef_server_url] =~ /\/organizations\/\S*$/
+ configuration[:chef_server_url].split("/")[0..-3].join("/")
+ elsif configuration[:chef_server_url] # default to whatever chef_server_url is
+ configuration[:chef_server_url]
else
"https://localhost:443"
end
@@ -555,7 +566,7 @@ module ChefConfig
# Initialize openssl
def self.init_openssl
if fips
- self.enable_fips_mode
+ enable_fips_mode
end
end
@@ -1042,6 +1053,12 @@ module ChefConfig
default :rubygems_url, "https://rubygems.org"
+ # This controls the behavior of resource cloning (and CHEF-3694 warnings). For Chef < 12 the behavior
+ # has been that this is 'true', in Chef 13 this will change to false. Setting this to 'true' in Chef
+ # 13 is not a viable or supported migration strategy since Chef 13 community cookbooks will be expected
+ # to break with this setting set to 'true'.
+ default :resource_cloning, true
+
# If installed via an omnibus installer, this gives the path to the
# "embedded" directory which contains all of the software packaged with
# omnibus. This is used to locate the cacert.pem file on windows.
diff --git a/chef-config/lib/chef-config/mixin/fuzzy_hostname_matcher.rb b/chef-config/lib/chef-config/mixin/fuzzy_hostname_matcher.rb
index 6dd678840a..ca1bdb4c0b 100644
--- a/chef-config/lib/chef-config/mixin/fuzzy_hostname_matcher.rb
+++ b/chef-config/lib/chef-config/mixin/fuzzy_hostname_matcher.rb
@@ -21,9 +21,11 @@ module ChefConfig
module FuzzyHostnameMatcher
def fuzzy_hostname_match_any?(hostname, matches)
- return matches.to_s.split(/\s*,\s*/).compact.any? do |m|
- fuzzy_hostname_match?(hostname, m)
- end if (hostname != nil) && (matches != nil)
+ if (!hostname.nil?) && (!matches.nil?)
+ return matches.to_s.split(/\s*,\s*/).compact.any? do |m|
+ fuzzy_hostname_match?(hostname, m)
+ end
+ end
false
end
diff --git a/chef-config/lib/chef-config/path_helper.rb b/chef-config/lib/chef-config/path_helper.rb
index 0304694516..e8a576c84f 100644
--- a/chef-config/lib/chef-config/path_helper.rb
+++ b/chef-config/lib/chef-config/path_helper.rb
@@ -187,7 +187,7 @@ module ChefConfig
#
# See self.all_homes.
def self.home(*args)
- @@home_dir ||= self.all_homes { |p| break p }
+ @@home_dir ||= all_homes { |p| break p }
if @@home_dir
path = File.join(@@home_dir, *args)
block_given? ? (yield path) : path
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index 3adffc3320..ca6c51b3fb 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 = "12.16.49"
+ VERSION = "12.19.30"
end
#
diff --git a/chef-config/spec/unit/config_spec.rb b/chef-config/spec/unit/config_spec.rb
index 806ab7d4fa..f5e9a914c9 100644
--- a/chef-config/spec/unit/config_spec.rb
+++ b/chef-config/spec/unit/config_spec.rb
@@ -203,16 +203,41 @@ RSpec.describe ChefConfig::Config do
before :each do
allow(ChefConfig).to receive(:windows?).and_return(is_windows)
end
-
+ describe "class method: windows_installation_drive" do
+ before do
+ allow(File).to receive(:expand_path).and_return("D:/Path/To/Executable")
+ end
+ if is_windows
+ it "should return D: on a windows system" do
+ expect(ChefConfig::Config.windows_installation_drive).to eq("D:")
+ end
+ else
+ it "should return nil on a non-windows system" do
+ expect(ChefConfig::Config.windows_installation_drive).to eq(nil)
+ end
+ end
+ end
describe "class method: platform_specific_path" do
+ before do
+ allow(ChefConfig::Config).to receive(:env).and_return({ "SYSTEMDRIVE" => "C:" })
+ end
if is_windows
- it "should return a windows path on windows systems" do
- path = "/etc/chef/cookbooks"
- allow(ChefConfig::Config).to receive(:env).and_return({ "SYSTEMDRIVE" => "C:" })
- # match on a regex that looks for the base path with an optional
- # system drive at the beginning (c:)
- # system drive is not hardcoded b/c it can change and b/c it is not present on linux systems
- expect(ChefConfig::Config.platform_specific_path(path)).to eq("C:\\chef\\cookbooks")
+ path = "/etc/chef/cookbooks"
+ context "a windows system with chef installed on C: drive" do
+ before do
+ allow(ChefConfig::Config).to receive(:windows_installation_drive).and_return("C:")
+ end
+ it "should return a windows path rooted in C:" do
+ expect(ChefConfig::Config.platform_specific_path(path)).to eq("C:\\chef\\cookbooks")
+ end
+ end
+ context "a windows system with chef installed on D: drive" do
+ before do
+ allow(ChefConfig::Config).to receive(:windows_installation_drive).and_return("D:")
+ end
+ it "should return a windows path rooted in D:" do
+ expect(ChefConfig::Config.platform_specific_path(path)).to eq("D:\\chef\\cookbooks")
+ end
end
else
it "should return given path on non-windows systems" do
@@ -345,6 +370,11 @@ RSpec.describe ChefConfig::Config do
end
describe "ChefConfig::Config[:cache_path]" do
+ before do
+ if is_windows
+ allow(File).to receive(:expand_path).and_return("#{ChefConfig::Config.env["SYSTEMDRIVE"]}/Path/To/Executable")
+ end
+ end
context "when /var/chef exists and is accessible" do
it "defaults to /var/chef" do
allow(ChefConfig::Config).to receive(:path_accessible?).with(to_platform("/var/chef")).and_return(true)
diff --git a/chef-universal-mingw32.gemspec b/chef-universal-mingw32.gemspec
index a4f086cfaf..449f909bb2 100644
--- a/chef-universal-mingw32.gemspec
+++ b/chef-universal-mingw32.gemspec
@@ -6,9 +6,8 @@ gemspec.add_dependency "ffi", "~> 1.9"
gemspec.add_dependency "win32-api", "~> 1.5.3"
gemspec.add_dependency "win32-dir", "~> 0.5.0"
gemspec.add_dependency "win32-event", "~> 0.6.1"
-# Hard pin on win32-eventlog until djberg96/win32-eventlog#20 is resolved.
-# win32-eventlog was stomping over the CreateEvent FFI bindings that
-# win32-service needed, causing the chef service to not run.
+# TODO: Relax this pin and make the necessary updaets. The issue originally
+# leading to this pin has been fixed in 0.6.5.
gemspec.add_dependency "win32-eventlog", "0.6.3"
gemspec.add_dependency "win32-mmap", "~> 0.4.1"
gemspec.add_dependency "win32-mutex", "~> 0.4.2"
diff --git a/chef.gemspec b/chef.gemspec
index 367761fbcc..2b80d817b8 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -11,9 +11,9 @@ Gem::Specification.new do |s|
s.license = "Apache-2.0"
s.author = "Adam Jacob"
s.email = "adam@chef.io"
- s.homepage = "http://www.chef.io"
+ s.homepage = "https://www.chef.io"
- s.required_ruby_version = ">= 2.2.0"
+ s.required_ruby_version = ">= 2.2.2"
s.add_dependency "chef-config", "= #{Chef::VERSION}"
@@ -21,12 +21,12 @@ Gem::Specification.new do |s|
s.add_dependency "mixlib-log", "~> 1.3"
s.add_dependency "mixlib-authentication", "~> 1.4"
s.add_dependency "mixlib-shellout", "~> 2.0"
- s.add_dependency "mixlib-archive", ">= 0.2.0"
- s.add_dependency "ohai", ">= 8.6.0.alpha.1", "< 9"
+ s.add_dependency "mixlib-archive", "~> 0.4"
+ s.add_dependency "ohai", ">= 8.6.0.alpha.1", "< 13"
s.add_dependency "ffi-yajl", "~> 2.2"
- s.add_dependency "net-ssh", ">= 2.9", "< 4.0"
- s.add_dependency "net-ssh-multi", "~> 1.1"
+ s.add_dependency "net-ssh", ">= 2.9", "< 5.0"
+ s.add_dependency "net-ssh-multi", "~> 1.2", ">= 1.2.1"
s.add_dependency "net-sftp", "~> 2.1", ">= 2.1.2"
s.add_dependency "highline", "~> 1.6", ">= 1.6.9"
s.add_dependency "erubis", "~> 2.7"
diff --git a/ci/bundle_install.sh b/ci/bundle_install.sh
index 6c6d76dc5d..4eecec9f18 100755
--- a/ci/bundle_install.sh
+++ b/ci/bundle_install.sh
@@ -5,5 +5,6 @@ set -evx
gem environment
bundler_version=$(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
gem install bundler -v $bundler_version --user-install --conservative
-export BUNDLE_WITHOUT=default:omnibus_package:test:pry:integration:docgen:maintenance:changelog:travis:aix:bsd:linux:mac_os_x:solaris:windows
+# WITH: changelog (for version bumping and changelog creation)
+export BUNDLE_WITHOUT=omnibus_package:test:pry:integration:docgen:maintenance:travis:aix:bsd:linux:mac_os_x:solaris:windows:development:travis
bundle _${bundler_version}_ install
diff --git a/ci/dependency_update.sh b/ci/dependency_update.sh
index 9588652143..65b67be526 100755
--- a/ci/dependency_update.sh
+++ b/ci/dependency_update.sh
@@ -4,6 +4,6 @@ set -evx
. ci/bundle_install.sh
-bundle exec rake dependencies
+bundle exec rake dependencies_ci
git checkout .bundle/config
diff --git a/ci/version_bump.sh b/ci/version_bump.sh
index dd53cebfd5..ed2229ecc3 100755
--- a/ci/version_bump.sh
+++ b/ci/version_bump.sh
@@ -2,8 +2,12 @@
set -evx
+export LANG=en_US.UTF-8
+
. ci/bundle_install.sh
bundle exec rake version:bump
+bundle exec rake changelog || true
+bundle exec rake update_dockerfile
git checkout .bundle/config
diff --git a/distro/common/html/knife_environment.html b/distro/common/html/knife_environment.html
index 75ef69f8a0..ee4810c133 100644
--- a/distro/common/html/knife_environment.html
+++ b/distro/common/html/knife_environment.html
@@ -200,11 +200,11 @@ windows 1.0.0 4.1.2
</div>
<div class="section" id="from-file">
<h2>from file<a class="headerlink" href="#from-file" title="Permalink to this headline">¶</a></h2>
-<p>The <tt class="docutils literal"><span class="pre">from</span> <span class="pre">file</span></tt> argument is used to add or update an environment using a JSON or Ruby DSL description. It must be run with the <tt class="docutils literal"><span class="pre">create</span></tt> or <tt class="docutils literal"><span class="pre">edit</span></tt> arguments.</p>
+<p>The <tt class="docutils literal"><span class="pre">from</span> <span class="pre">file</span></tt> argument is used to add or update an environment using a JSON or Ruby DSL description.</p>
<div class="section" id="id7">
<h3>Syntax<a class="headerlink" href="#id7" title="Permalink to this headline">¶</a></h3>
<p>This argument has the following syntax:</p>
-<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife environment <span class="o">[</span>create | edit<span class="o">]</span> from file FILE <span class="o">(</span>options<span class="o">)</span>
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife environment from file FILE <span class="o">(</span>options<span class="o">)</span>
</pre></div>
</div>
</div>
@@ -221,11 +221,7 @@ windows 1.0.0 4.1.2
<p>The following examples show how to use this knife subcommand:</p>
<p><strong>Create an environment from a JSON file</strong></p>
<p>To add an environment using data contained in a JSON file:</p>
-<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife environment create devops from file <span class="s2">&quot;path to JSON file&quot;</span>
-</pre></div>
-</div>
-<p>or:</p>
-<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife environment edit devops from file <span class="s2">&quot;path to JSON file&quot;</span>
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife environment from file <span class="s2">&quot;path to JSON file&quot;</span>
</pre></div>
</div>
</div>
@@ -323,4 +319,4 @@ override_attributes:
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/distro/common/man/man1/knife-environment.1 b/distro/common/man/man1/knife-environment.1
index d583abe7fa..7b8542170f 100644
--- a/distro/common/man/man1/knife-environment.1
+++ b/distro/common/man/man1/knife-environment.1
@@ -339,7 +339,7 @@ $ knife environment edit devops
.UNINDENT
.SH FROM FILE
.sp
-The \fBfrom file\fP argument is used to add or update an environment using a JSON or Ruby DSL description. It must be run with the \fBcreate\fP or \fBedit\fP arguments.
+The \fBfrom file\fP argument is used to add or update an environment using a JSON or Ruby DSL description.
.sp
\fBSyntax\fP
.sp
@@ -349,7 +349,7 @@ This argument has the following syntax:
.sp
.nf
.ft C
-$ knife environment [create | edit] from file FILE (options)
+$ knife environment from file FILE (options)
.ft P
.fi
.UNINDENT
@@ -366,25 +366,13 @@ Use to upload all environments found at the specified path.
.sp
\fBExamples\fP
.sp
-To add an environment using data contained in a JSON file:
+To add or update an environment using data contained in a JSON file:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
-$ knife environment create devops from file "path to JSON file"
-.ft P
-.fi
-.UNINDENT
-.UNINDENT
-.sp
-or:
-.INDENT 0.0
-.INDENT 3.5
-.sp
-.nf
-.ft C
-$ knife environment edit devops from file "path to JSON file"
+$ knife environment from file "path to JSON file"
.ft P
.fi
.UNINDENT
diff --git a/distro/common/markdown/man1/knife-configure.mkd b/distro/common/markdown/man1/knife-configure.mkd
index f3a4ef02bb..b441dc5d8b 100644
--- a/distro/common/markdown/man1/knife-configure.mkd
+++ b/distro/common/markdown/man1/knife-configure.mkd
@@ -33,10 +33,11 @@ the specified _directory_.
* On a freshly installed Chef Server, use _knife configure -i_ to
create an administrator and knife configuration file. Leave the
field blank to accept the default value. On most systems, the
- default values are acceptable.
+ default values are acceptable (except for the chef server URL,
+ there you must add your organization name)
user@host$ knife configure -i
- Please enter the chef server URL: [http://localhost:4000]
+ Please enter the chef server URL: [http://localhost/organizations/myorg]
Please enter a clientname for the new client: [username]
Please enter the existing admin clientname: [chef-webui]
Please enter the location of the existing admin client's private key: [/etc/chef/webui.pem]
diff --git a/distro/powershell/chef/chef.psm1 b/distro/powershell/chef/chef.psm1
index 6646226795..9196d62e6c 100644
--- a/distro/powershell/chef/chef.psm1
+++ b/distro/powershell/chef/chef.psm1
@@ -109,6 +109,12 @@ public enum StandardHandle : int
Error = -12
}
+public enum HandleFlags : int
+{
+ HANDLE_FLAG_INHERIT = 0x00000001,
+ HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002
+}
+
public static class Kernel32
{
[DllImport("kernel32.dll", SetLastError=true)]
@@ -128,11 +134,12 @@ public static class Kernel32
[DllImport("kernel32.dll", SetLastError=true)]
public static extern IntPtr GetStdHandle(
StandardHandle nStdHandle);
-
- [DllImport("kernel32", SetLastError=true)]
- public static extern int WaitForSingleObject(
- IntPtr hHandle,
- int dwMilliseconds);
+
+ [DllImport("kernel32.dll")]
+ public static extern bool SetHandleInformation(
+ IntPtr hObject,
+ int dwMask,
+ uint dwFlags);
[DllImport("kernel32", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
@@ -144,6 +151,32 @@ public static class Kernel32
public static extern bool GetExitCodeProcess(
IntPtr hProcess,
out int lpExitCode);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool CreatePipe(
+ out IntPtr phReadPipe,
+ out IntPtr phWritePipe,
+ IntPtr lpPipeAttributes,
+ uint nSize);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool ReadFile(
+ IntPtr hFile,
+ [Out] byte[] lpBuffer,
+ uint nNumberOfBytesToRead,
+ ref int lpNumberOfBytesRead,
+ IntPtr lpOverlapped);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool PeekNamedPipe(
+ IntPtr handle,
+ byte[] buffer,
+ uint nBufferSize,
+ ref uint bytesRead,
+ ref uint bytesAvail,
+ ref uint BytesLeftThisMessage);
+
+ public const int STILL_ACTIVE = 259;
}
}
"@
@@ -156,13 +189,6 @@ function Run-ExecutableAndWait($AppPath, $ArgumentString) {
$si = New-Object Chef.STARTUPINFO
$pi = New-Object Chef.PROCESS_INFORMATION
- $si.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($si)
- $si.wShowWindow = [Chef.ShowWindow]::SW_SHOW
- $si.dwFlags = [Chef.STARTF]::STARTF_USESTDHANDLES
- $si.hStdError = [Chef.Kernel32]::GetStdHandle([Chef.StandardHandle]::Error)
- $si.hStdOutput = [Chef.Kernel32]::GetStdHandle([Chef.StandardHandle]::Output)
- $si.hStdInput = [Chef.Kernel32]::GetStdHandle([Chef.StandardHandle]::Input)
-
$pSec = New-Object Chef.SECURITY_ATTRIBUTES
$pSec.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($pSec)
$pSec.bInheritHandle = $true
@@ -170,25 +196,103 @@ function Run-ExecutableAndWait($AppPath, $ArgumentString) {
$tSec.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($tSec)
$tSec.bInheritHandle = $true
- $success = [Chef.Kernel32]::CreateProcess($AppPath, $ArgumentString, [ref] $pSec, [ref] $tSec, $true, [Chef.CreationFlags]::NONE, [IntPtr]::Zero, $pwd, [ref] $si, [ref] $pi)
+ # Create pipe for process stdout
+ $ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf($si))
+ [System.Runtime.InteropServices.Marshal]::StructureToPtr($pSec, $ptr, $true)
+ $hReadOut = [IntPtr]::Zero
+ $hWriteOut = [IntPtr]::Zero
+ $success = [Chef.Kernel32]::CreatePipe([ref] $hReadOut, [ref] $hWriteOut, $ptr, 0)
if (-Not $success) {
$reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- throw "Unable to create process [$ArgumentString]. Error code $reason."
+ throw "Unable to create output pipe. Error code $reason."
}
- $waitReason = [Chef.Kernel32]::WaitForSingleObject($pi.hProcess, -1)
- if ($waitReason -ne 0) {
- if ($waitReason -eq -1) {
- $reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- throw "Could not wait for process to terminate. Error code $reason."
- } else {
- throw "WaitForSingleObject failed with return code $waitReason - it's impossible!"
- }
+ $success = [Chef.Kernel32]::SetHandleInformation($hReadOut, [Chef.HandleFlags]::HANDLE_FLAG_INHERIT, 0)
+ if (-Not $success) {
+ $reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ throw "Unable to set output pipe handle information. Error code $reason."
}
- $success = [Chef.Kernel32]::GetExitCodeProcess($pi.hProcess, [ref] $global:LASTEXITCODE)
+
+ $si.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($si)
+ $si.wShowWindow = [Chef.ShowWindow]::SW_SHOW
+ $si.dwFlags = [Chef.STARTF]::STARTF_USESTDHANDLES
+ $si.hStdOutput = $hWriteOut
+ $si.hStdError = $hWriteOut
+ $si.hStdInput = [Chef.Kernel32]::GetStdHandle([Chef.StandardHandle]::Input)
+
+ $success = [Chef.Kernel32]::CreateProcess(
+ $AppPath,
+ $ArgumentString,
+ [ref] $pSec,
+ [ref] $tSec,
+ $true,
+ [Chef.CreationFlags]::NONE,
+ [IntPtr]::Zero,
+ $pwd,
+ [ref] $si,
+ [ref] $pi
+ )
if (-Not $success) {
$reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- throw "Process exit code unavailable. Error code $reason."
+ throw "Unable to create process [$ArgumentString]. Error code $reason."
}
+
+ $sb = New-Object System.Text.StringBuilder
+ $buffer = New-Object byte[] 1024
+
+ # Initialize reference variables
+ $bytesRead = 0
+ $bytesAvailable = 0
+ $bytesLeftThisMsg = 0
+ $global:LASTEXITCODE = [Chef.Kernel32]::STILL_ACTIVE
+
+ $isActive = $true
+ while ($isActive) {
+ $success = [Chef.Kernel32]::GetExitCodeProcess($pi.hProcess, [ref] $global:LASTEXITCODE)
+ if (-Not $success) {
+ $reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ throw "Process exit code unavailable. Error code $reason."
+ }
+
+ $success = [Chef.Kernel32]::PeekNamedPipe(
+ $hReadOut,
+ $null,
+ $buffer.Length,
+ [ref] $bytesRead,
+ [ref] $bytesAvailable,
+ [ref] $bytesLeftThisMsg
+ )
+ if (-Not $success) {
+ $reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ throw "Output pipe unavailable for peeking. Error code $reason."
+ }
+
+ if ($bytesRead -gt 0) {
+ while ([Chef.Kernel32]::ReadFile($hReadOut, $buffer, $buffer.Length, [ref] $bytesRead, 0)) {
+ $output = [Text.Encoding]::UTF8.GetString($buffer, 0, $bytesRead)
+ if ($output) {
+ [void]$sb.Append($output)
+ }
+ if ($bytesRead -lt $buffer.Length) {
+ # Partial buffer indicating the end of stream, break out of ReadFile loop
+ # ReadFile will block until:
+ # The number of bytes requested is read.
+ # A write operation completes on the write end of the pipe.
+ # An asynchronous handle is being used and the read is occurring asynchronously.
+ # An error occurs.
+ break
+ }
+ }
+ }
+
+ if ($global:LASTEXITCODE -ne [Chef.Kernel32]::STILL_ACTIVE) {
+ $isActive = $false
+ }
+ }
+
+ # Return output obtained from child process stdout/stderr
+ $sb.ToString()
+
+ # Cleanup handles
$success = [Chef.Kernel32]::CloseHandle($pi.hProcess)
if (-Not $success) {
$reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
@@ -199,6 +303,17 @@ function Run-ExecutableAndWait($AppPath, $ArgumentString) {
$reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
throw "Unable to release thread handle. Error code $reason."
}
+ $success = [Chef.Kernel32]::CloseHandle($hWriteOut)
+ if (-Not $success) {
+ $reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ throw "Unable to release output write handle. Error code $reason."
+ }
+ $success = [Chef.Kernel32]::CloseHandle($hReadOut)
+ if (-Not $success) {
+ $reason = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ throw "Unable to release output read handle. Error code $reason."
+ }
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)
}
function Get-ScriptDirectory {
diff --git a/habitat/default.toml b/habitat/default.toml
new file mode 100644
index 0000000000..04385fc371
--- /dev/null
+++ b/habitat/default.toml
@@ -0,0 +1,11 @@
+# The Chef run interval in seconds
+interval = 10
+
+# The splay
+splay = 10
+
+# The default log level
+log_level = "info"
+
+# The default run list
+run_list = ""
diff --git a/habitat/hooks/run b/habitat/hooks/run
new file mode 100644
index 0000000000..0f3844dd5f
--- /dev/null
+++ b/habitat/hooks/run
@@ -0,0 +1,8 @@
+#!/bin/sh
+export GEM_HOME="{{pkg.path}}/ruby/2.3.0"
+export GEM_PATH="$(hab pkg path core/ruby)/lib/ruby/gems/2.3.0:$(hab pkg path core/bundler):$GEM_HOME"
+export APPBUNDLER_ALLOW_RVM=true
+
+exec 2>&1
+exec chef-solo --fork -i {{cfg.interval}} -s {{cfg.splay}} -l {{cfg.log_level}} -o {{cfg.run_list}}
+
diff --git a/habitat/plan.sh b/habitat/plan.sh
new file mode 100644
index 0000000000..7a797842e2
--- /dev/null
+++ b/habitat/plan.sh
@@ -0,0 +1,100 @@
+pkg_name=chef-client
+pkg_origin=chef
+pkg_maintainer="The Chef Maintainers <humans@chef.io>"
+pkg_description="The Chef Client"
+pkg_version=$(cat ../VERSION)
+pkg_source=nosuchfile.tar.gz
+pkg_filename=${pkg_dirname}.tar.gz
+pkg_license=('Apache-2.0')
+pkg_bin_dirs=(bin)
+pkg_build_deps=(core/make core/gcc core/coreutils core/git)
+pkg_deps=(core/glibc core/ruby core/libxml2 core/libxslt core/libiconv core/xz core/zlib core/bundler core/openssl core/cacerts core/libffi)
+pkg_svc_user=root
+
+do_download() {
+ build_line "Fake download! Creating archive of latest repository commit."
+ # source is in this repo, so we're going to create an archive from the
+ # appropriate path within the repo and place the generated tarball in the
+ # location expected by do_unpack
+ cd $PLAN_CONTEXT/../
+ git archive --prefix=${pkg_name}-${pkg_version}/ --output=$HAB_CACHE_SRC_PATH/${pkg_filename} HEAD
+}
+
+do_verify() {
+ build_line "Skipping checksum verification on the archive we just created."
+ return 0
+}
+
+do_prepare() {
+ export OPENSSL_LIB_DIR=$(pkg_path_for openssl)/lib
+ export OPENSSL_INCLUDE_DIR=$(pkg_path_for openssl)/include
+ export SSL_CERT_FILE=$(pkg_path_for cacerts)/ssl/cert.pem
+
+ build_line "Setting link for /usr/bin/env to 'coreutils'"
+ [[ ! -f /usr/bin/env ]] && ln -s $(pkg_path_for coreutils)/bin/env /usr/bin/env
+
+ return 0
+}
+
+do_build() {
+ export CPPFLAGS="${CPPFLAGS} ${CFLAGS}"
+
+ local _bundler_dir=$(pkg_path_for bundler)
+ local _libxml2_dir=$(pkg_path_for libxml2)
+ local _libxslt_dir=$(pkg_path_for libxslt)
+ local _zlib_dir=$(pkg_path_for zlib)
+
+ export GEM_HOME=${pkg_prefix}
+ export GEM_PATH=${_bundler_dir}:${GEM_HOME}
+
+ export NOKOGIRI_CONFIG="--use-system-libraries --with-zlib-dir=${_zlib_dir} --with-xslt-dir=${_libxslt_dir} --with-xml2-include=${_libxml2_dir}/include/libxml2 --with-xml2-lib=${_libxml2_dir}/lib"
+ bundle config --local build.nokogiri '${NOKOGIRI_CONFIG}'
+
+ bundle config --local silence_root_warning 1
+
+ # We need to add tzinfo-data to the Gemfile since we're not in an
+ # environment that has this from the OS
+ if [[ -z "`grep 'gem .*tzinfo-data.*' Gemfile`" ]]; then
+ echo 'gem "tzinfo-data"' >> Gemfile
+ fi
+
+ bundle install --no-deployment --jobs 2 --retry 5 --path $pkg_prefix
+
+ bundle exec 'cd ./chef-config && rake package'
+ bundle exec 'rake package'
+ mkdir -p gems-suck/gems
+ cp pkg/chef-$pkg_version.gem gems-suck/gems
+ cp chef-config/pkg/chef-config-$pkg_version.gem gems-suck/gems
+ bundle exec gem generate_index -d gems-suck
+
+ sed -e "s#gem \"chef\".*#gem \"chef\", source: \"file://$HAB_CACHE_SRC_PATH/$pkg_dirname/gems-suck\"#" -i Gemfile
+ sed -e "s#gem \"chef-config\".*#gem \"chef-config\", source: \"file://$HAB_CACHE_SRC_PATH/$pkg_dirname/gems-suck\"#" -i Gemfile
+ #bundle config --local local.chef $HAB_CACHE_SRC_PATH/$pkg_dirname/gems-suck
+ #bundle config --local local.chef-config $HAB_CACHE_SRC_PATH/$pkg_dirname/gems-suck
+
+ bundle install --no-deployment --jobs 2 --retry 5 --path $pkg_prefix
+
+}
+
+do_install() {
+
+ mkdir -p $pkg_prefix/bin
+
+ bundle exec appbundler $HAB_CACHE_SRC_PATH/$pkg_dirname $pkg_prefix/bin chef
+ bundle exec appbundler $HAB_CACHE_SRC_PATH/$pkg_dirname $pkg_prefix/bin ohai
+
+ for binstub in ${pkg_prefix}/bin/*; do
+ build_line "Setting shebang for ${binstub} to 'ruby'"
+ [[ -f $binstub ]] && sed -e "s#/usr/bin/env ruby#$(pkg_path_for ruby)/bin/ruby#" -i $binstub
+ done
+
+ if [[ `readlink /usr/bin/env` = "$(pkg_path_for coreutils)/bin/env" ]]; then
+ build_line "Removing the symlink we created for '/usr/bin/env'"
+ rm /usr/bin/env
+ fi
+}
+
+# Stubs
+do_strip() {
+ return 0
+}
diff --git a/kitchen-tests/.kitchen.travis.yml b/kitchen-tests/.kitchen.travis.yml
index 312764e9e4..aae5202457 100644
--- a/kitchen-tests/.kitchen.travis.yml
+++ b/kitchen-tests/.kitchen.travis.yml
@@ -2,7 +2,8 @@
driver:
name: dokken
privileged: true
- chef_version: latest
+ chef_image: chef/chef
+ chef_version: current
transport:
name: dokken
@@ -10,9 +11,6 @@ transport:
provisioner:
name: chef_github
root_path: /opt/kitchen
- require_chef_omnibus: latest
- chef_omnibus_url: "https://omnitruck.chef.io/install.sh"
- chef_omnibus_install_options: "-c current"
github_owner: "chef"
github_repo: "chef"
refname: <%= ENV['TRAVIS_COMMIT'] %>
@@ -75,12 +73,13 @@ platforms:
- RUN yum -y install which initscripts net-tools sudo wget
- RUN sed -i -e "s/Defaults.*requiretty.*/Defaults !requiretty/g" /etc/sudoers
-- name: fedora-23
+- name: fedora-latest
driver:
- image: fedora:23
+ image: fedora:latest
pid_one_command: /usr/lib/systemd/systemd
intermediate_instructions:
- RUN dnf -y install yum which initscripts rpm-build zlib-devel net-tools sudo wget
+ - RUN yum makecache
- RUN sed -i -e "s/Defaults.*requiretty.*/Defaults !requiretty/g" /etc/sudoers
- name: ubuntu-12.04
@@ -114,6 +113,15 @@ platforms:
intermediate_instructions:
- RUN zypper refresh
+- name: amazonlinux
+ driver:
+ image: amazonlinux:latest
+ pid_one_command: /sbin/init
+ intermediate_instructions:
+ - RUN yum clean all
+ - RUN yum -y install which initscripts net-tools sudo wget
+ - RUN sed -i -e "s/Defaults.*requiretty.*/Defaults !requiretty/g" /etc/sudoers
+
suites:
- name: webapp
run_list:
diff --git a/kitchen-tests/Berksfile b/kitchen-tests/Berksfile
index 45695ca5a3..5319e45a19 100644
--- a/kitchen-tests/Berksfile
+++ b/kitchen-tests/Berksfile
@@ -1,4 +1,4 @@
-source "https://supermarket.getchef.com"
+source "https://supermarket.chef.io"
#cookbook "webapp", path: "cookbooks/webapp"
cookbook "base", path: "cookbooks/base"
diff --git a/kitchen-tests/Berksfile.lock b/kitchen-tests/Berksfile.lock
index 9261f6f481..6d8f40436a 100644
--- a/kitchen-tests/Berksfile.lock
+++ b/kitchen-tests/Berksfile.lock
@@ -1,12 +1,12 @@
DEPENDENCIES
awesome_customers_rhel
git: https://github.com/learn-chef/awesome_customers_rhel.git
- revision: 1ac86593829610c0eab7a45d9c63c09a9cea1754
+ revision: b576fcf2988e2cdf156e7ba6ff59a94d556e16f1
awesome_customers_rhel_wrapper
path: cookbooks/awesome_customers_rhel_wrapper
awesome_customers_ubuntu
git: https://github.com/learn-chef/awesome_customers_ubuntu.git
- revision: 71927c094d570e6fd0f8bfbcc02ebe3556af2a16
+ revision: fea174c5855266f28218f76f00f6eff69e850244
awesome_customers_ubuntu_wrapper
path: cookbooks/awesome_customers_ubuntu_wrapper
base
@@ -52,39 +52,39 @@ GRAPH
sudo (>= 0.0.0)
ubuntu (>= 0.0.0)
users (>= 0.0.0)
- build-essential (7.0.1)
- compat_resource (>= 12.14)
+ build-essential (7.0.3)
+ compat_resource (>= 12.16.3)
mingw (>= 1.1)
seven_zip (>= 0.0.0)
- chef-client (6.0.0)
+ chef-client (7.1.0)
cron (>= 1.7.0)
logrotate (>= 1.9.0)
windows (>= 1.42.0)
chef-sugar (3.4.0)
chef_hostname (0.4.2)
compat_resource (>= 0.0.0)
- compat_resource (12.14.7)
+ compat_resource (12.16.3)
cron (3.0.0)
- database (6.0.0)
+ database (6.1.1)
postgresql (>= 1.0.0)
- firewall (2.5.2)
+ firewall (2.5.3)
chef-sugar (>= 0.0.0)
httpd (0.4.4)
compat_resource (>= 12.14.6)
- iis (5.0.4)
+ iis (5.0.5)
windows (>= 1.34.6)
- iptables (3.0.1)
+ iptables (3.1.0)
compat_resource (>= 12.14.3)
logrotate (2.1.0)
compat_resource (>= 0.0.0)
- mariadb (0.3.1)
+ mariadb (1.0.1)
apt (>= 0.0.0)
yum (>= 0.0.0)
yum-epel (>= 0.0.0)
- mingw (1.2.4)
- compat_resource (>= 0.0.0)
+ mingw (1.2.5)
+ compat_resource (>= 12.16.3)
seven_zip (>= 0.0.0)
- multipackage (3.0.28)
+ multipackage (4.0.0)
compat_resource (>= 0.0.0)
mysql (7.2.0)
smf (>= 0.0.0)
@@ -95,11 +95,12 @@ GRAPH
mysql (>= 6.0)
nscd (4.1.0)
compat_resource (>= 0.0.0)
- ntp (3.2.0)
- openssh (2.1.0)
+ ntp (3.3.1)
+ ohai (4.2.3)
+ compat_resource (>= 12.14.7)
+ openssh (2.1.1)
iptables (>= 1.0)
- openssl (4.4.0)
- chef-sugar (>= 3.1.1)
+ openssl (6.1.1)
php (1.5.0)
build-essential (>= 0.0.0)
iis (>= 0.0.0)
@@ -107,10 +108,10 @@ GRAPH
windows (>= 0.0.0)
xml (>= 0.0.0)
yum-epel (>= 0.0.0)
- postgresql (4.0.6)
- apt (>= 1.9.0)
- build-essential (>= 0.0.0)
- openssl (~> 4.0)
+ postgresql (6.0.1)
+ build-essential (>= 2.0.0)
+ compat_resource (>= 12.16.3)
+ openssl (>= 4.0)
rbac (1.0.3)
resolver (1.3.1)
selinux (0.9.0)
@@ -118,15 +119,16 @@ GRAPH
windows (>= 1.2.2)
smf (2.2.8)
rbac (>= 1.0.1)
- sudo (3.0.0)
+ sudo (3.3.1)
ubuntu (2.0.0)
apt (>= 0.0.0)
- users (4.0.1)
- windows (2.0.2)
- xml (3.0.0)
+ users (4.0.3)
+ windows (2.1.1)
+ ohai (>= 4.0.0)
+ xml (3.1.1)
build-essential (>= 0.0.0)
- yum (4.0.0)
- yum-epel (1.0.1)
- yum (>= 3.6)
- yum-mysql-community (1.0.0)
- yum (>= 3.2)
+ yum (4.1.0)
+ yum-epel (2.1.1)
+ compat_resource (>= 12.16.3)
+ yum-mysql-community (2.0.3)
+ compat_resource (>= 12.16.3)
diff --git a/kitchen-tests/Gemfile b/kitchen-tests/Gemfile
index ad89269a75..707a38a7f6 100644
--- a/kitchen-tests/Gemfile
+++ b/kitchen-tests/Gemfile
@@ -1,8 +1,9 @@
source "https://rubygems.org"
+gem "rake" # required to build some native extensions
gem "berkshelf"
gem "kitchen-appbundle-updater"
-gem "kitchen-dokken"
+gem "kitchen-dokken", "< 2.0" # 2.x fails atm: https://travis-ci.org/chef/chef/jobs/199125787
gem "kitchen-ec2"
gem "kitchen-inspec"
gem "kitchen-vagrant"
diff --git a/kitchen-tests/Gemfile.lock b/kitchen-tests/Gemfile.lock
index 48231fb189..b9d14397f1 100644
--- a/kitchen-tests/Gemfile.lock
+++ b/kitchen-tests/Gemfile.lock
@@ -1,15 +1,18 @@
GEM
remote: https://rubygems.org/
specs:
- addressable (2.4.0)
- artifactory (2.5.0)
- aws-sdk (2.6.14)
- aws-sdk-resources (= 2.6.14)
- aws-sdk-core (2.6.14)
+ addressable (2.5.0)
+ public_suffix (~> 2.0, >= 2.0.2)
+ artifactory (2.6.0)
+ aws-sdk (2.7.5)
+ aws-sdk-resources (= 2.7.5)
+ aws-sdk-core (2.7.5)
+ aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-resources (2.6.14)
- aws-sdk-core (= 2.6.14)
- berkshelf (5.1.0)
+ aws-sdk-resources (2.7.5)
+ aws-sdk-core (= 2.7.5)
+ aws-sigv4 (1.0.0)
+ berkshelf (5.6.2)
addressable (~> 2.3, >= 2.3.4)
berkshelf-api-client (>= 2.0.2, < 4.0)
buff-config (~> 2.0)
@@ -19,12 +22,12 @@ GEM
faraday (~> 0.9)
httpclient (~> 2.7)
minitar (~> 0.5, >= 0.5.4)
- mixlib-archive (~> 0.1)
+ mixlib-archive (~> 0.4)
octokit (~> 4.0)
retryable (~> 2.0)
ridley (~> 5.0)
solve (> 2.0, < 4.0)
- thor (~> 0.19)
+ thor (~> 0.19, < 0.19.2)
berkshelf-api-client (3.0.0)
faraday (~> 0.9)
httpclient (~> 2.7)
@@ -37,39 +40,40 @@ GEM
buff-ruby_engine (1.0.0)
buff-shell_out (1.1.0)
buff-ruby_engine (~> 1.0)
- builder (3.2.2)
+ builder (3.2.3)
celluloid (0.16.0)
timers (~> 4.0.0)
celluloid-io (0.16.2)
celluloid (>= 0.16.0)
nio4r (>= 1.1.0)
- chef-config (12.15.19)
+ chef-config (12.18.31)
addressable
fuzzyurl
mixlib-config (~> 2.0)
mixlib-shellout (~> 2.0)
cleanroom (1.0.0)
coderay (1.1.1)
- diff-lcs (1.2.5)
- docker-api (1.32.1)
+ diff-lcs (1.3)
+ docker-api (1.33.2)
excon (>= 0.38.0)
json
erubis (2.7.0)
- excon (0.54.0)
+ excon (0.55.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
- ffi (1.9.14)
- ffi (1.9.14-x86-mingw32)
+ ffi (1.9.17)
+ ffi (1.9.17-x86-mingw32)
fuzzyurl (0.9.0)
gssapi (1.2.0)
ffi (>= 1.0.1)
gyoku (1.3.1)
builder (>= 2.1.2)
- hashie (3.4.6)
+ hashie (3.5.1)
hitimes (1.2.4)
hitimes (1.2.4-x86-mingw32)
- httpclient (2.8.2.4)
- inspec (1.3.0)
+ httpclient (2.8.3)
+ inspec (1.14.1)
+ faraday (>= 0.9.0)
hashie (~> 3.4)
json (>= 1.8, < 3.0)
method_source (~> 0.8)
@@ -79,39 +83,41 @@ GEM
rainbow (~> 2)
rspec (~> 3)
rspec-its (~> 1.2)
+ rspec_junit_formatter (~> 0.2.3)
rubyzip (~> 1.1)
sslshake (~> 1)
thor (~> 0.19)
- train (>= 0.20.1, < 1.0)
+ train (>= 0.22.0, < 1.0)
jmespath (1.3.1)
- json (2.0.2)
+ json (2.0.3)
kitchen-appbundle-updater (0.1.2)
- kitchen-dokken (1.0.3)
- docker-api (~> 1.29)
- test-kitchen (~> 1.5)
+ kitchen-dokken (1.1.0)
+ docker-api (~> 1.33)
+ test-kitchen (~> 1.13)
kitchen-ec2 (1.2.0)
aws-sdk (~> 2)
excon
multi_json
retryable (~> 2.0)
test-kitchen (~> 1.4, >= 1.4.1)
- kitchen-inspec (0.15.2)
- inspec (>= 0.22.0, < 2.0.0)
+ kitchen-inspec (0.17.0)
+ hashie (~> 3.4)
+ inspec (>= 0.34.0, < 2.0.0)
test-kitchen (~> 1.6)
- kitchen-vagrant (0.20.0)
+ kitchen-vagrant (1.0.0)
test-kitchen (~> 1.4)
little-plugger (1.1.4)
logging (2.1.0)
little-plugger (~> 1.1)
multi_json (~> 1.10)
method_source (0.8.2)
- minitar (0.5.4)
- mixlib-archive (0.2.0)
+ minitar (0.6.1)
+ mixlib-archive (0.4.1)
mixlib-log
mixlib-authentication (1.4.1)
mixlib-log
mixlib-config (2.2.4)
- mixlib-install (2.1.5)
+ mixlib-install (2.1.12)
artifactory
mixlib-shellout
mixlib-versioning
@@ -122,24 +128,26 @@ GEM
win32-process (~> 0.8.2)
wmi-lite (~> 1.0)
mixlib-versioning (1.1.0)
- molinillo (0.5.3)
+ molinillo (0.5.6)
multi_json (1.12.1)
multipart-post (2.0.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
- net-ssh (3.2.0)
- net-ssh-gateway (1.2.0)
+ net-ssh (4.0.1)
+ net-ssh-gateway (1.3.0)
net-ssh (>= 2.6.5)
- nio4r (1.2.1)
+ nio4r (2.0.0)
nori (2.6.0)
- octokit (4.4.1)
- sawyer (~> 0.7.0, >= 0.5.3)
- parallel (1.9.0)
+ octokit (4.6.2)
+ sawyer (~> 0.8.0, >= 0.5.3)
+ parallel (1.10.0)
pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
- rainbow (2.1.0)
+ public_suffix (2.0.5)
+ rainbow (2.2.1)
+ rake (12.0.0)
retryable (2.0.4)
ridley (5.1.0)
addressable
@@ -175,35 +183,38 @@ GEM
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
+ rspec_junit_formatter (0.2.3)
+ builder (< 4)
+ rspec-core (>= 2, < 4, != 2.12.0)
rubyntlm (0.6.1)
- rubyzip (1.2.0)
+ rubyzip (1.2.1)
safe_yaml (1.0.4)
- sawyer (0.7.0)
- addressable (>= 2.3.5, < 2.5)
- faraday (~> 0.8, < 0.10)
+ sawyer (0.8.1)
+ addressable (>= 2.3.5, < 2.6)
+ faraday (~> 0.8, < 1.0)
semverse (2.0.0)
slop (3.6.0)
- solve (3.0.1)
- molinillo (~> 0.4)
+ solve (3.1.0)
+ molinillo (>= 0.5)
semverse (>= 1.1, < 3.0)
sslshake (1.0.13)
- test-kitchen (1.13.2)
+ test-kitchen (1.15.0)
mixlib-install (>= 1.2, < 3.0)
mixlib-shellout (>= 1.2, < 3.0)
net-scp (~> 1.1)
- net-ssh (>= 2.9, < 4.0)
- net-ssh-gateway (~> 1.2.0)
+ net-ssh (>= 2.9, < 5.0)
+ net-ssh-gateway (~> 1.2)
safe_yaml (~> 1.0)
thor (~> 0.18)
thor (0.19.1)
timers (4.0.4)
hitimes
- train (0.20.1)
+ train (0.22.1)
docker-api (~> 1.26)
json (>= 1.8, < 3.0)
mixlib-shellout (~> 2.0)
net-scp (~> 1.2)
- net-ssh (>= 2.9, < 4.0)
+ net-ssh (>= 2.9, < 5.0)
winrm (~> 2.0)
winrm-fs (~> 1.0)
vagrant-wrapper (2.0.3)
@@ -212,7 +223,7 @@ GEM
hashie (>= 2.0.2, < 4.0.0)
win32-process (0.8.3)
ffi (>= 1.0.0)
- winrm (2.1.0)
+ winrm (2.1.2)
builder (>= 2.1.2)
erubis (~> 2.7)
gssapi (~> 1.2)
@@ -221,7 +232,7 @@ GEM
logging (>= 1.6.1, < 3.0)
nori (~> 2.0)
rubyntlm (~> 0.6.0, >= 0.6.1)
- winrm-fs (1.0.0)
+ winrm-fs (1.0.1)
erubis (~> 2.7)
logging (>= 1.6.1, < 3.0)
rubyzip (~> 1.1)
@@ -235,10 +246,11 @@ PLATFORMS
DEPENDENCIES
berkshelf
kitchen-appbundle-updater
- kitchen-dokken
+ kitchen-dokken (< 2.0)
kitchen-ec2
kitchen-inspec
kitchen-vagrant
+ rake
ridley
test-kitchen
vagrant-wrapper
diff --git a/kitchen-tests/cookbooks/audit_test/Berksfile b/kitchen-tests/cookbooks/audit_test/Berksfile
index 0ac9b78cf7..967b9a78b6 100644
--- a/kitchen-tests/cookbooks/audit_test/Berksfile
+++ b/kitchen-tests/cookbooks/audit_test/Berksfile
@@ -1,3 +1,3 @@
-source "https://supermarket.getchef.com"
+source "https://supermarket.chef.io"
metadata
diff --git a/kitchen-tests/cookbooks/base/Berksfile b/kitchen-tests/cookbooks/base/Berksfile
index 4b6079016e..ba11c46c1d 100644
--- a/kitchen-tests/cookbooks/base/Berksfile
+++ b/kitchen-tests/cookbooks/base/Berksfile
@@ -1,4 +1,4 @@
-source "https://api.berkshelf.com"
+source "https://supermarket.chef.io"
metadata
diff --git a/kitchen-tests/cookbooks/base/attributes/default.rb b/kitchen-tests/cookbooks/base/attributes/default.rb
index ef273c969c..75e57cb27b 100644
--- a/kitchen-tests/cookbooks/base/attributes/default.rb
+++ b/kitchen-tests/cookbooks/base/attributes/default.rb
@@ -13,7 +13,6 @@ default["ubuntu"]["components"] = "main restricted universe multiverse"
#
# turn off old protocols client-side
-default["openssh"]["client"]["rsa_authentication"] = "no"
default["openssh"]["client"]["host_based_authentication"] = "no"
# allow typical ssh v2 rsa/dsa/ecdsa key auth client-side
default["openssh"]["client"]["pubkey_authentication"] = "yes"
@@ -34,8 +33,6 @@ default["openssh"]["server"]["use_dns"] = "no"
default["openssh"]["server"]["syslog_facility"] = "AUTH"
# only allow access via ssh pubkeys, all other mechanisms including passwords are turned off for all users
default["openssh"]["server"]["pubkey_authentication"] = "yes"
-default["openssh"]["server"]["rhosts_rsa_authentication"] = "no"
-default["openssh"]["server"]["rsa_authentication"] = "no"
default["openssh"]["server"]["password_authentication"] = "no"
default["openssh"]["server"]["host_based_authentication"] = "no"
default["openssh"]["server"]["gssapi_authentication"] = "no"
diff --git a/kitchen-tests/cookbooks/base/recipes/default.rb b/kitchen-tests/cookbooks/base/recipes/default.rb
index 397d50c016..c25673bef5 100644
--- a/kitchen-tests/cookbooks/base/recipes/default.rb
+++ b/kitchen-tests/cookbooks/base/recipes/default.rb
@@ -23,7 +23,7 @@ yum_repository "epel" do
gpgkey "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-#{node['platform_version'].to_i}"
gpgcheck true
mirrorlist "https://mirrors.fedoraproject.org/metalink?repo=epel-#{node['platform_version'].to_i}&arch=$basearch"
- only_if { node["platform_family"] == "rhel" }
+ only_if { node["platform_family"] == "rhel" && node["platform"] != "amazon" }
end
include_recipe "build-essential"
diff --git a/kitchen-tests/cookbooks/base/recipes/packages.rb b/kitchen-tests/cookbooks/base/recipes/packages.rb
index 1ca8d81968..c4457e5945 100644
--- a/kitchen-tests/cookbooks/base/recipes/packages.rb
+++ b/kitchen-tests/cookbooks/base/recipes/packages.rb
@@ -1,6 +1,7 @@
-
-pkgs = %w{lsof tcpdump strace zsh dmidecode ltrace bc curl wget telnet subversion git traceroute htop tmux s3cmd sysbench }
+# 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.
+pkgs = %w{lsof tcpdump strace zsh dmidecode ltrace bc curl wget telnet subversion git traceroute htop tmux }
# this deliberately calls the multipackage API N times in order to do one package installation in order to exercise the
# multipackage cookbook.
diff --git a/kitchen-tests/cookbooks/webapp/Berksfile b/kitchen-tests/cookbooks/webapp/Berksfile
index 4b6079016e..ba11c46c1d 100644
--- a/kitchen-tests/cookbooks/webapp/Berksfile
+++ b/kitchen-tests/cookbooks/webapp/Berksfile
@@ -1,4 +1,4 @@
-source "https://api.berkshelf.com"
+source "https://supermarket.chef.io"
metadata
diff --git a/kitchen-tests/test/integration/webapp/default_spec.rb b/kitchen-tests/test/integration/webapp/default_spec.rb
index ec23a57998..cf148218b7 100644
--- a/kitchen-tests/test/integration/webapp/default_spec.rb
+++ b/kitchen-tests/test/integration/webapp/default_spec.rb
@@ -12,7 +12,7 @@ when "debian", "ubuntu"
ssh_package = "openssh-client"
ssh_service = "ssh"
ntp_service = "ntp"
-when "centos", "redhat", "fedora"
+when "centos", "redhat", "fedora", "amazon"
ssh_package = "openssh-clients"
ssh_service = "sshd"
ntp_service = "ntpd"
@@ -91,7 +91,7 @@ describe package("autoconf") do
it { should be_installed }
end
-%w{lsof tcpdump strace zsh dmidecode ltrace bc curl wget telnet subversion git traceroute htop tmux s3cmd sysbench }.each do |pkg|
+%w{lsof tcpdump strace zsh dmidecode ltrace bc curl wget telnet subversion git traceroute htop tmux }.each do |pkg|
describe package pkg do
it { should be_installed }
end
diff --git a/lib-backcompat/chef/chef_fs/file_system/already_exists_error.rb b/lib-backcompat/chef/chef_fs/file_system/already_exists_error.rb
index 6d9973e8a4..75cebe5497 100644
--- a/lib-backcompat/chef/chef_fs/file_system/already_exists_error.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/already_exists_error.rb
@@ -17,4 +17,4 @@
#
require "chef/chef_fs/file_system/exceptions"
-Chef.log_deprecation "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
+Chef.deprecated :internal_api, "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
diff --git a/lib-backcompat/chef/chef_fs/file_system/cookbook_frozen_error.rb b/lib-backcompat/chef/chef_fs/file_system/cookbook_frozen_error.rb
index 6d9973e8a4..75cebe5497 100644
--- a/lib-backcompat/chef/chef_fs/file_system/cookbook_frozen_error.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/cookbook_frozen_error.rb
@@ -17,4 +17,4 @@
#
require "chef/chef_fs/file_system/exceptions"
-Chef.log_deprecation "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
+Chef.deprecated :internal_api, "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
diff --git a/lib-backcompat/chef/chef_fs/file_system/default_environment_cannot_be_modified_error.rb b/lib-backcompat/chef/chef_fs/file_system/default_environment_cannot_be_modified_error.rb
index 6d9973e8a4..75cebe5497 100644
--- a/lib-backcompat/chef/chef_fs/file_system/default_environment_cannot_be_modified_error.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/default_environment_cannot_be_modified_error.rb
@@ -17,4 +17,4 @@
#
require "chef/chef_fs/file_system/exceptions"
-Chef.log_deprecation "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
+Chef.deprecated :internal_api, "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
diff --git a/lib-backcompat/chef/chef_fs/file_system/file_system_error.rb b/lib-backcompat/chef/chef_fs/file_system/file_system_error.rb
index 6d9973e8a4..75cebe5497 100644
--- a/lib-backcompat/chef/chef_fs/file_system/file_system_error.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/file_system_error.rb
@@ -17,4 +17,4 @@
#
require "chef/chef_fs/file_system/exceptions"
-Chef.log_deprecation "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
+Chef.deprecated :internal_api, "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
diff --git a/lib-backcompat/chef/chef_fs/file_system/must_delete_recursively_error.rb b/lib-backcompat/chef/chef_fs/file_system/must_delete_recursively_error.rb
index 6d9973e8a4..75cebe5497 100644
--- a/lib-backcompat/chef/chef_fs/file_system/must_delete_recursively_error.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/must_delete_recursively_error.rb
@@ -17,4 +17,4 @@
#
require "chef/chef_fs/file_system/exceptions"
-Chef.log_deprecation "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
+Chef.deprecated :internal_api, "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
diff --git a/lib-backcompat/chef/chef_fs/file_system/not_found_error.rb b/lib-backcompat/chef/chef_fs/file_system/not_found_error.rb
index 6d9973e8a4..75cebe5497 100644
--- a/lib-backcompat/chef/chef_fs/file_system/not_found_error.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/not_found_error.rb
@@ -17,4 +17,4 @@
#
require "chef/chef_fs/file_system/exceptions"
-Chef.log_deprecation "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
+Chef.deprecated :internal_api, "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
diff --git a/lib-backcompat/chef/chef_fs/file_system/operation_failed_error.rb b/lib-backcompat/chef/chef_fs/file_system/operation_failed_error.rb
index 6d9973e8a4..75cebe5497 100644
--- a/lib-backcompat/chef/chef_fs/file_system/operation_failed_error.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/operation_failed_error.rb
@@ -17,4 +17,4 @@
#
require "chef/chef_fs/file_system/exceptions"
-Chef.log_deprecation "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
+Chef.deprecated :internal_api, "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
diff --git a/lib-backcompat/chef/chef_fs/file_system/operation_not_allowed_error.rb b/lib-backcompat/chef/chef_fs/file_system/operation_not_allowed_error.rb
index 6d9973e8a4..75cebe5497 100644
--- a/lib-backcompat/chef/chef_fs/file_system/operation_not_allowed_error.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/operation_not_allowed_error.rb
@@ -17,4 +17,4 @@
#
require "chef/chef_fs/file_system/exceptions"
-Chef.log_deprecation "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
+Chef.deprecated :internal_api, "Individual ChefFS error files are deprecated. Please require 'chef/chef_fs/file_system/exceptions' rather than 'chef/chef_fs/file_system/#{File.basename(__FILE__, ".rb")}'."
diff --git a/lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb b/lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb
index eb2c3e8ff6..7668c6b174 100644
--- a/lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/repository/chef_repository_file_system_entry.rb
@@ -1,6 +1,6 @@
require "chef/chef_fs/file_system/repository/file_system_entry"
module Chef::ChefFS::FileSystem::Repository
- Chef.log_deprecation "Chef::ChefFS::FileSystem::Repository::ChefRepositoryFileSystemEntry is deprecated. Please use FileSystemEntry directly"
+ Chef.deprecated :internal_api, "Chef::ChefFS::FileSystem::Repository::ChefRepositoryFileSystemEntry is deprecated. Please use FileSystemEntry directly"
ChefRepositoryFileSystemEntry = FileSystemEntry
end
diff --git a/lib-backcompat/chef/chef_fs/file_system/repository/file_system_root_dir.rb b/lib-backcompat/chef/chef_fs/file_system/repository/file_system_root_dir.rb
index 8565ee6029..1c8bb87d72 100644
--- a/lib-backcompat/chef/chef_fs/file_system/repository/file_system_root_dir.rb
+++ b/lib-backcompat/chef/chef_fs/file_system/repository/file_system_root_dir.rb
@@ -24,7 +24,7 @@ class Chef
module Repository
class FileSystemRootDir < FileSystemEntry
def initialize(file_path)
- Chef.log_deprecation "Chef::ChefFS::FileSystem::Repository::FileSystemRootDir is deprecated."
+ Chef.deprecated :internal_api, "Chef::ChefFS::FileSystem::Repository::FileSystemRootDir is deprecated."
super("", nil, file_path)
end
end
diff --git a/lib/chef/api_client.rb b/lib/chef/api_client.rb
index 3c1ef7a2b6..6999a4f52d 100644
--- a/lib/chef/api_client.rb
+++ b/lib/chef/api_client.rb
@@ -141,7 +141,7 @@ class Chef
end
def self.json_create(data)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::ApiClient#from_hash")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::ApiClient#from_hash")
from_hash(data)
end
@@ -162,7 +162,7 @@ class Chef
if inflate
response = Hash.new
Chef::Search::Query.new.search(:client) do |n|
- n = self.json_create(n) if n.instance_of?(Hash)
+ n = json_create(n) if n.instance_of?(Hash)
response[n.name] = n
end
response
@@ -188,15 +188,13 @@ class Chef
# Save this client via the REST API, returns a hash including the private key
def save
- begin
- http_api.put("clients/#{name}", { :name => self.name, :admin => self.admin, :validator => self.validator })
- rescue Net::HTTPServerException => e
- # If that fails, go ahead and try and update it
- if e.response.code == "404"
- http_api.post("clients", { :name => self.name, :admin => self.admin, :validator => self.validator })
- else
- raise e
- end
+ http_api.put("clients/#{name}", { :name => name, :admin => admin, :validator => validator })
+ rescue Net::HTTPServerException => e
+ # If that fails, go ahead and try and update it
+ if e.response.code == "404"
+ http_api.post("clients", { :name => name, :admin => admin, :validator => validator })
+ else
+ raise e
end
end
diff --git a/lib/chef/api_client_v1.rb b/lib/chef/api_client_v1.rb
index 47b0cd1c53..a1b9b8317e 100644
--- a/lib/chef/api_client_v1.rb
+++ b/lib/chef/api_client_v1.rb
@@ -190,7 +190,7 @@ class Chef
if inflate
response = Hash.new
Chef::Search::Query.new.search(:client) do |n|
- n = self.from_hash(n) if n.instance_of?(Hash)
+ n = from_hash(n) if n.instance_of?(Hash)
response[n.name] = n
end
response
@@ -212,15 +212,13 @@ class Chef
# Save this client via the REST API, returns a hash including the private key
def save
- begin
- update
- rescue Net::HTTPServerException => e
- # If that fails, go ahead and try and update it
- if e.response.code == "404"
- create
- else
- raise e
- end
+ update
+ rescue Net::HTTPServerException => e
+ # If that fails, go ahead and try and update it
+ if e.response.code == "404"
+ create
+ else
+ raise e
end
end
@@ -313,7 +311,7 @@ class Chef
new_client = chef_rest_v0.post("clients", payload)
end
- Chef::ApiClientV1.from_hash(self.to_hash.merge(new_client))
+ Chef::ApiClientV1.from_hash(to_hash.merge(new_client))
end
# As a string
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index 7f15859c8f..ab19e6571e 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -120,9 +120,10 @@ class Chef
end
def set_specific_recipes
- Chef::Config[:specific_recipes] =
- cli_arguments.map { |file| File.expand_path(file) } if
- cli_arguments.respond_to?(:map)
+ if cli_arguments.respond_to?(:map)
+ Chef::Config[:specific_recipes] =
+ cli_arguments.map { |file| File.expand_path(file) }
+ end
end
# Initialize and configure the logger.
@@ -333,7 +334,7 @@ class Chef
def emit_warnings
if Chef::Config[:chef_gem_compile_time]
- Chef.log_deprecation "setting chef_gem_compile_time to true is deprecated"
+ Chef.deprecated :chef_gem_compile_time, "setting chef_gem_compile_time to true is deprecated"
end
end
@@ -342,7 +343,7 @@ class Chef
message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
cause = e.cause if e.respond_to?(:cause)
- while cause != nil
+ until cause.nil?
message << "\n\n>>>> Caused by #{cause.class}: #{cause}\n#{cause.backtrace.join("\n")}"
cause = cause.respond_to?(:cause) ? cause.cause : nil
end
diff --git a/lib/chef/application/apply.rb b/lib/chef/application/apply.rb
index 3e3fb58448..d7f2359b02 100644
--- a/lib/chef/application/apply.rb
+++ b/lib/chef/application/apply.rb
@@ -200,16 +200,14 @@ class Chef::Application::Apply < Chef::Application
end
def run_application
- begin
- parse_options
- run_chef_recipe
- Chef::Application.exit! "Exiting", 0
- rescue SystemExit
- raise
- rescue Exception => e
- Chef::Application.debug_stacktrace(e)
- Chef::Application.fatal!("#{e.class}: #{e.message}", e)
- end
+ parse_options
+ run_chef_recipe
+ Chef::Application.exit! "Exiting", 0
+ rescue SystemExit
+ raise
+ rescue Exception => e
+ Chef::Application.debug_stacktrace(e)
+ Chef::Application.fatal!("#{e.class}: #{e.message}", e)
end
# Get this party started
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index 000aff905b..c8dbd76019 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -289,7 +289,7 @@ class Chef::Application::Client < Chef::Application
:boolean => true
option :fips,
- :long => "--fips",
+ :long => "--[no-]fips",
:description => "Enable fips mode",
:boolean => true
diff --git a/lib/chef/application/exit_code.rb b/lib/chef/application/exit_code.rb
index 6fec2524dd..610a356a7c 100644
--- a/lib/chef/application/exit_code.rb
+++ b/lib/chef/application/exit_code.rb
@@ -88,7 +88,7 @@ class Chef
def normalize_legacy_exit_code(exit_code)
case exit_code
- when Fixnum
+ when Integer
exit_code
when Exception
lookup_exit_code_by_exception(exit_code)
@@ -198,16 +198,14 @@ class Chef
end
def notify_on_deprecation(message)
- begin
- Chef.log_deprecation(message)
- rescue Chef::Exceptions::DeprecatedFeatureError
+ Chef.deprecated(:exit_code, message)
+ rescue Chef::Exceptions::DeprecatedFeatureError
# Have to rescue this, otherwise this unhandled error preempts
# the current exit code assignment.
- end
end
def deprecation_warning
- "Chef RFC 062 (https://github.com/chef/chef-rfc/master/rfc062-exit-status.md) defines the" \
+ "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."
@@ -222,7 +220,7 @@ class Chef
def default_exit_code
if normalization_disabled? || normalization_not_configured?
- return DEPRECATED_RFC_062_EXIT_CODES[:DEPRECATED_FAILURE]
+ DEPRECATED_RFC_062_EXIT_CODES[:DEPRECATED_FAILURE]
else
VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE]
end
diff --git a/lib/chef/application/knife.rb b/lib/chef/application/knife.rb
index c80d0245f1..521011348f 100644
--- a/lib/chef/application/knife.rb
+++ b/lib/chef/application/knife.rb
@@ -203,11 +203,11 @@ class Chef::Application::Knife < Chef::Application
Chef::Log.error(fatal_message) if fatal_message
begin
- self.parse_options
+ parse_options
rescue OptionParser::InvalidOption => e
puts "#{e}\n"
end
- puts self.opt_parser
+ puts opt_parser
puts
Chef::Knife.list_commands
exit exitcode
diff --git a/lib/chef/application/windows_service.rb b/lib/chef/application/windows_service.rb
index 2f1456ac45..7bc68a586d 100644
--- a/lib/chef/application/windows_service.rb
+++ b/lib/chef/application/windows_service.rb
@@ -183,39 +183,38 @@ class Chef
# The chef client will be started in a new process. We have used shell_out to start the chef-client.
# The log_location and config_file of the parent process is passed to the new chef-client process.
# We need to add the --no-fork, as by default it is set to fork=true.
- begin
- Chef::Log.info "Starting chef-client in a new process"
- # Pass config params to the new process
- config_params = " --no-fork"
- config_params += " -c #{Chef::Config[:config_file]}" unless Chef::Config[:config_file].nil?
- # log_location might be an event logger and if so we cannot pass as a command argument
- # but shed no tears! If the logger is an event logger, it must have been configured
- # as such in the config file and chef-client will use that when no arg is passed here
- config_params += " -L #{resolve_log_location}" if resolve_log_location.is_a?(String)
-
- # Starts a new process and waits till the process exits
-
- result = shell_out(
- "chef-client.bat #{config_params}",
- :timeout => Chef::Config[:windows_service][:watchdog_timeout],
- :logger => Chef::Log
- )
- Chef::Log.debug "#{result.stdout}"
- Chef::Log.debug "#{result.stderr}"
- rescue Mixlib::ShellOut::CommandTimeout => e
- Chef::Log.error "chef-client timed out\n(#{e})"
- Chef::Log.error(<<-EOF)
+
+ Chef::Log.info "Starting chef-client in a new process"
+ # Pass config params to the new process
+ config_params = " --no-fork"
+ config_params += " -c #{Chef::Config[:config_file]}" unless Chef::Config[:config_file].nil?
+ # log_location might be an event logger and if so we cannot pass as a command argument
+ # but shed no tears! If the logger is an event logger, it must have been configured
+ # as such in the config file and chef-client will use that when no arg is passed here
+ config_params += " -L #{resolve_log_location}" if resolve_log_location.is_a?(String)
+
+ # Starts a new process and waits till the process exits
+
+ result = shell_out(
+ "chef-client.bat #{config_params}",
+ :timeout => Chef::Config[:windows_service][:watchdog_timeout],
+ :logger => Chef::Log
+ )
+ Chef::Log.debug "#{result.stdout}"
+ Chef::Log.debug "#{result.stderr}"
+ rescue Mixlib::ShellOut::CommandTimeout => e
+ Chef::Log.error "chef-client timed out\n(#{e})"
+ Chef::Log.error(<<-EOF)
Your chef-client run timed out. You can increase the time chef-client is given
to complete by configuring windows_service.watchdog_timeout in your client.rb.
EOF
- rescue Mixlib::ShellOut::ShellCommandFailed => e
- Chef::Log.warn "Not able to start chef-client in new process (#{e})"
- rescue => e
- Chef::Log.error e
- ensure
- # Once process exits, we log the current process' pid
- Chef::Log.info "Child process exited (pid: #{Process.pid})"
- end
+ rescue Mixlib::ShellOut::ShellCommandFailed => e
+ Chef::Log.warn "Not able to start chef-client in new process (#{e})"
+ rescue => e
+ Chef::Log.error e
+ ensure
+ # Once process exits, we log the current process' pid
+ Chef::Log.info "Child process exited (pid: #{Process.pid})"
end
def apply_config(config_file_path)
diff --git a/lib/chef/application/windows_service_manager.rb b/lib/chef/application/windows_service_manager.rb
index 6f81dccc67..5c572bc260 100644
--- a/lib/chef/application/windows_service_manager.rb
+++ b/lib/chef/application/windows_service_manager.rb
@@ -126,10 +126,12 @@ class Chef
:password => @password,
:dependencies => @dependencies
)
- ::Win32::Service.configure(
- :service_name => @service_name,
- :delayed_start => @delayed_start
- ) unless @delayed_start.nil?
+ unless @delayed_start.nil?
+ ::Win32::Service.configure(
+ :service_name => @service_name,
+ :delayed_start => @delayed_start
+ )
+ end
puts "Service '#{@service_name}' has successfully been installed."
end
when "status"
@@ -166,7 +168,7 @@ class Chef
PAUSED = "paused"
def service_exists?
- return ::Win32::Service.exists?(@service_name)
+ ::Win32::Service.exists?(@service_name)
end
def take_action(action = nil, desired_state = nil)
diff --git a/lib/chef/audit/audit_event_proxy.rb b/lib/chef/audit/audit_event_proxy.rb
index c4d67fa8f4..25ff31ecb1 100644
--- a/lib/chef/audit/audit_event_proxy.rb
+++ b/lib/chef/audit/audit_event_proxy.rb
@@ -78,14 +78,14 @@ class Chef
# We know all of our examples each live in a top-level `control_group` block - get this name now
outermost_group_desc = describe_groups.shift
- return outermost_group_desc, {
+ [outermost_group_desc, {
:name => example.description,
:desc => example.full_description,
:resource_type => resource_type,
:resource_name => resource_name,
:context => describe_groups,
:line_number => example.metadata[:line_number],
- }
+ }]
end
end
diff --git a/lib/chef/audit/control_group_data.rb b/lib/chef/audit/control_group_data.rb
index 4dffbdf3dd..476ebe95e9 100644
--- a/lib/chef/audit/control_group_data.rb
+++ b/lib/chef/audit/control_group_data.rb
@@ -118,7 +118,7 @@ class Chef
def initialize(control_data = {})
control_data.each do |k, v|
- self.instance_variable_set("@#{k}", v)
+ instance_variable_set("@#{k}", v)
end
end
diff --git a/lib/chef/chef_class.rb b/lib/chef/chef_class.rb
index 0bb15c03ca..e61fd5e1d2 100644
--- a/lib/chef/chef_class.rb
+++ b/lib/chef/chef_class.rb
@@ -30,7 +30,9 @@ require "chef/platform/provider_priority_map"
require "chef/platform/resource_priority_map"
require "chef/platform/provider_handler_map"
require "chef/platform/resource_handler_map"
+require "chef/deprecated"
require "chef/event_dispatch/dsl"
+require "chef/deprecated"
class Chef
class << self
@@ -198,26 +200,35 @@ class Chef
#
# Emit a deprecation message.
#
- # @param message The message to send.
+ # @param type The message to send. This should be a symbol, referring to
+ # a class defined in Chef::Deprecated
+ # @param message An explicit message to display, rather than the generic one
+ # associated with the deprecation.
# @param location The location. Defaults to the caller who called you (since
# generally the person who triggered the check is the one that needs to be
# fixed).
#
# @example
- # Chef.deprecation("Deprecated!")
+ # Chef.deprecated(:my_deprecation, message: "This is deprecated!")
#
# @api private this will likely be removed in favor of an as-yet unwritten
# `Chef.log`
- def log_deprecation(message, location = nil)
+ def deprecated(type, message, location = nil)
location ||= Chef::Log.caller_location
+ deprecation = Chef::Deprecated.create(type, message, location)
# `run_context.events` is the primary deprecation target if we're in a
# run. If we are not yet in a run, print to `Chef::Log`.
if run_context && run_context.events
- run_context.events.deprecation(message, location)
+ run_context.events.deprecation(deprecation, location)
else
- Chef::Log.deprecation(message, location)
+ Chef::Log.deprecation(deprecation, location)
end
end
+
+ def log_deprecation(message, location = nil)
+ location ||= Chef::Log.caller_location
+ Chef.deprecated(:generic, message, location)
+ end
end
# @api private Only for test dependency injection; not evenly implemented as yet.
diff --git a/lib/chef/chef_fs/chef_fs_data_store.rb b/lib/chef/chef_fs/chef_fs_data_store.rb
index 6b3e830f8d..46fe5c4dd3 100644
--- a/lib/chef/chef_fs/chef_fs_data_store.rb
+++ b/lib/chef/chef_fs/chef_fs_data_store.rb
@@ -326,7 +326,7 @@ class Chef
else
relative << path[1]
end
- relative = relative + file[:path].split("/")
+ relative += file[:path].split("/")
file["url"] = ChefZero::RestBase.build_uri(request.base_uri, relative)
end
end
@@ -611,7 +611,7 @@ class Chef
private
def use_memory_store?(path)
- return path[0] == "sandboxes" || path[0] == "file_store" && path[1] == "checksums" || path == %w{environments _default}
+ path[0] == "sandboxes" || path[0] == "file_store" && path[1] == "checksums" || path == %w{environments _default}
end
def write_cookbook(path, data, *options)
@@ -779,15 +779,13 @@ class Chef
end
def path_always_exists?(path)
- return path.length == 1 && BASE_DIRNAMES.include?(path[0])
+ path.length == 1 && BASE_DIRNAMES.include?(path[0])
end
def with_entry(path)
- begin
- yield Chef::ChefFS::FileSystem.resolve_path(chef_fs, to_chef_fs_path(path))
- rescue Chef::ChefFS::FileSystem::NotFoundError => e
- raise ChefZero::DataStore::DataNotFoundError.new(to_zero_path(e.entry), e)
- end
+ yield Chef::ChefFS::FileSystem.resolve_path(chef_fs, to_chef_fs_path(path))
+ rescue Chef::ChefFS::FileSystem::NotFoundError => e
+ raise ChefZero::DataStore::DataNotFoundError.new(to_zero_path(e.entry), e)
end
def with_parent_dir(path, *options)
diff --git a/lib/chef/chef_fs/command_line.rb b/lib/chef/chef_fs/command_line.rb
index 2d887f4780..2aefe2fa88 100644
--- a/lib/chef/chef_fs/command_line.rb
+++ b/lib/chef/chef_fs/command_line.rb
@@ -229,7 +229,7 @@ class Chef
end
end
- if old_value == :none || (old_value == nil && !old_entry.exists?)
+ if old_value == :none || (old_value.nil? && !old_entry.exists?)
return [ [ :added, old_entry, new_entry, old_value, new_value ] ]
elsif new_value == :none
return [ [ :deleted, old_entry, new_entry, old_value, new_value ] ]
@@ -266,26 +266,25 @@ class Chef
def diff_text(old_path, new_path, old_value, new_value)
# Copy to tempfiles before diffing
# TODO don't copy things that are already in files! Or find an in-memory diff algorithm
- begin
- new_tempfile = Tempfile.new("new")
- new_tempfile.write(new_value)
- new_tempfile.close
- begin
- old_tempfile = Tempfile.new("old")
- old_tempfile.write(old_value)
- old_tempfile.close
+ new_tempfile = Tempfile.new("new")
+ new_tempfile.write(new_value)
+ new_tempfile.close
- result = Chef::Util::Diff.new.udiff(old_tempfile.path, new_tempfile.path)
- result = result.gsub(/^--- #{old_tempfile.path}/, "--- #{old_path}")
- result = result.gsub(/^\+\+\+ #{new_tempfile.path}/, "+++ #{new_path}")
- result
- ensure
- old_tempfile.close!
- end
+ begin
+ old_tempfile = Tempfile.new("old")
+ old_tempfile.write(old_value)
+ old_tempfile.close
+
+ result = Chef::Util::Diff.new.udiff(old_tempfile.path, new_tempfile.path)
+ result = result.gsub(/^--- #{old_tempfile.path}/, "--- #{old_path}")
+ result = result.gsub(/^\+\+\+ #{new_tempfile.path}/, "+++ #{new_path}")
+ result
ensure
- new_tempfile.close!
+ old_tempfile.close!
end
+ ensure
+ new_tempfile.close!
end
end
end
diff --git a/lib/chef/chef_fs/data_handler/client_data_handler.rb b/lib/chef/chef_fs/data_handler/client_data_handler.rb
index 5e120035ac..6c01d8d54c 100644
--- a/lib/chef/chef_fs/data_handler/client_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/client_data_handler.rb
@@ -25,7 +25,7 @@ class Chef
end
def preserve_key?(key)
- return key == "name"
+ key == "name"
end
def chef_class
diff --git a/lib/chef/chef_fs/data_handler/container_data_handler.rb b/lib/chef/chef_fs/data_handler/container_data_handler.rb
index 04973b5135..a8bd5f084c 100644
--- a/lib/chef/chef_fs/data_handler/container_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/container_data_handler.rb
@@ -12,7 +12,7 @@ class Chef
end
def preserve_key?(key)
- return key == "containername"
+ key == "containername"
end
# Verify that the JSON hash for this type has a key that matches its name.
diff --git a/lib/chef/chef_fs/data_handler/cookbook_data_handler.rb b/lib/chef/chef_fs/data_handler/cookbook_data_handler.rb
index 156c1eef4e..2861c5d3eb 100644
--- a/lib/chef/chef_fs/data_handler/cookbook_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/cookbook_data_handler.rb
@@ -24,7 +24,7 @@ class Chef
end
def preserve_key?(key)
- return key == "cookbook_name" || key == "version"
+ key == "cookbook_name" || key == "version"
end
def chef_class
diff --git a/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb b/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb
index c6b6449d52..e799e72e36 100644
--- a/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb
@@ -35,7 +35,7 @@ class Chef
end
def preserve_key?(key)
- return key == "id"
+ key == "id"
end
def chef_class
diff --git a/lib/chef/chef_fs/data_handler/environment_data_handler.rb b/lib/chef/chef_fs/data_handler/environment_data_handler.rb
index 68f6daee9a..ab8104b483 100644
--- a/lib/chef/chef_fs/data_handler/environment_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/environment_data_handler.rb
@@ -18,7 +18,7 @@ class Chef
end
def preserve_key?(key)
- return key == "name"
+ key == "name"
end
def chef_class
diff --git a/lib/chef/chef_fs/data_handler/group_data_handler.rb b/lib/chef/chef_fs/data_handler/group_data_handler.rb
index 7f38784826..8daced2e2e 100644
--- a/lib/chef/chef_fs/data_handler/group_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/group_data_handler.rb
@@ -41,7 +41,7 @@ class Chef
end
def preserve_key?(key)
- return key == "name"
+ key == "name"
end
def chef_class
diff --git a/lib/chef/chef_fs/data_handler/node_data_handler.rb b/lib/chef/chef_fs/data_handler/node_data_handler.rb
index 36a7bf545b..a0087ec5d6 100644
--- a/lib/chef/chef_fs/data_handler/node_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/node_data_handler.rb
@@ -22,7 +22,7 @@ class Chef
end
def preserve_key?(key)
- return key == "name"
+ key == "name"
end
def chef_class
diff --git a/lib/chef/chef_fs/data_handler/organization_data_handler.rb b/lib/chef/chef_fs/data_handler/organization_data_handler.rb
index 0facd5d55d..0a697ab69a 100644
--- a/lib/chef/chef_fs/data_handler/organization_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/organization_data_handler.rb
@@ -16,7 +16,7 @@ class Chef
end
def preserve_key?(key)
- return key == "name"
+ key == "name"
end
# Verify that the JSON hash for this type has a key that matches its name.
diff --git a/lib/chef/chef_fs/data_handler/role_data_handler.rb b/lib/chef/chef_fs/data_handler/role_data_handler.rb
index b09c146a5d..b26271f3e8 100644
--- a/lib/chef/chef_fs/data_handler/role_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/role_data_handler.rb
@@ -24,7 +24,7 @@ class Chef
end
def preserve_key?(key)
- return key == "name"
+ key == "name"
end
def chef_class
diff --git a/lib/chef/chef_fs/data_handler/user_data_handler.rb b/lib/chef/chef_fs/data_handler/user_data_handler.rb
index c2df4db49d..4da2f8225d 100644
--- a/lib/chef/chef_fs/data_handler/user_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/user_data_handler.rb
@@ -19,7 +19,7 @@ class Chef
end
def preserve_key?(key)
- return key == "name"
+ key == "name"
end
# There is no chef_class for users, nor does to_ruby work.
diff --git a/lib/chef/chef_fs/file_pattern.rb b/lib/chef/chef_fs/file_pattern.rb
index 9c12bd4b96..835e06eab7 100644
--- a/lib/chef/chef_fs/file_pattern.rb
+++ b/lib/chef/chef_fs/file_pattern.rb
@@ -84,7 +84,7 @@ class Chef
# Otherwise, it's possible we could match: the path matches to this point, and the pattern is longer than the path.
# TODO There is one edge case where the double star comes after some characters like abc**def--we could check whether the next
# bit of path starts with abc in that case.
- return true
+ true
end
# Returns the immediate child of a path that would be matched
@@ -114,7 +114,7 @@ class Chef
path = path[1, path.length - 1] if Chef::ChefFS::PathUtils.is_absolute?(path)
dirs_in_path = Chef::ChefFS::PathUtils.split(path).length
return nil if exact_parts.length <= dirs_in_path
- return exact_parts[dirs_in_path]
+ exact_parts[dirs_in_path]
end
# If this pattern represents an exact path, returns the exact path.
diff --git a/lib/chef/chef_fs/file_system.rb b/lib/chef/chef_fs/file_system.rb
index 1a8da2fd6b..cbd8aa71d9 100644
--- a/lib/chef/chef_fs/file_system.rb
+++ b/lib/chef/chef_fs/file_system.rb
@@ -419,7 +419,7 @@ class Chef
ui.output "Created #{parent_path}" if ui
end
end
- return parent
+ parent
end
def parallel_do(enum, options = {}, &block)
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 3fa5b49eb1..8f5faf2183 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
@@ -73,17 +73,16 @@ class Chef
# Since we're ignoring the rules and doing a network request here,
# we need to make sure we don't rethrow the exception. (child(name)
# is not supposed to fail.)
- begin
- children.find { |child| child.name == name }
- rescue Chef::ChefFS::FileSystem::NotFoundError
- nil
- end
+
+ children.find { |child| child.name == name }
+ rescue Chef::ChefFS::FileSystem::NotFoundError
+ nil
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 true
+ true
end
def children
diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb b/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb
index ad50054dc9..6b4657ae6a 100644
--- a/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb
@@ -37,16 +37,14 @@ class Chef
end
def read
- begin
- tmpfile = rest.streaming_request(file[:url])
- File.open(tmpfile, "rb") { |f| f.read }
- rescue Timeout::Error => e
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "Timeout reading #{file[:url]}: #{e}")
- rescue Net::HTTPServerException => e
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "#{e.message} retrieving #{file[:url]}")
- rescue Errno::ENOENT
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
- end
+ tmpfile = rest.streaming_request(file[:url])
+ File.open(tmpfile, "rb") { |f| f.read }
+ rescue Timeout::Error => e
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "Timeout reading #{file[:url]}: #{e}")
+ rescue Net::HTTPServerException => e
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "#{e.message} retrieving #{file[:url]}")
+ rescue Errno::ENOENT
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
end
def rest
diff --git a/lib/chef/chef_fs/file_system/chef_server/data_bags_dir.rb b/lib/chef/chef_fs/file_system/chef_server/data_bags_dir.rb
index ec382e60ef..205aa9fd86 100644
--- a/lib/chef/chef_fs/file_system/chef_server/data_bags_dir.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/data_bags_dir.rb
@@ -30,16 +30,14 @@ class Chef
end
def children
- begin
- @children ||= root.get_json(api_path).keys.sort.map { |entry| make_child_entry(entry, true) }
- rescue Timeout::Error => e
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "Timeout getting children: #{e}")
- rescue Net::HTTPServerException => e
- if e.response.code == "404"
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, e)
- else
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error getting children: #{e}")
- end
+ @children ||= root.get_json(api_path).keys.sort.map { |entry| make_child_entry(entry, true) }
+ rescue Timeout::Error => e
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "Timeout getting children: #{e}")
+ rescue Net::HTTPServerException => e
+ if e.response.code == "404"
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, e)
+ else
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error getting children: #{e}")
end
end
diff --git a/lib/chef/chef_fs/file_system/chef_server/nodes_dir.rb b/lib/chef/chef_fs/file_system/chef_server/nodes_dir.rb
index df2388f1df..c81e880744 100644
--- a/lib/chef/chef_fs/file_system/chef_server/nodes_dir.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/nodes_dir.rb
@@ -28,18 +28,16 @@ class Chef
class NodesDir < RestListDir
# Identical to RestListDir.children, except supports environments
def children
- begin
- @children ||= root.get_json(env_api_path).keys.sort.map do |key|
- make_child_entry(key, true)
- end
- rescue Timeout::Error => e
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "Timeout retrieving children: #{e}")
- rescue Net::HTTPServerException => e
- if $!.response.code == "404"
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
- else
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}")
- end
+ @children ||= root.get_json(env_api_path).keys.sort.map do |key|
+ make_child_entry(key, true)
+ end
+ rescue Timeout::Error => e
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "Timeout retrieving children: #{e}")
+ rescue Net::HTTPServerException => e
+ if $!.response.code == "404"
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
+ else
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}")
end
end
diff --git a/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb b/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb
index 4a4be19fe4..a4add1378d 100644
--- a/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb
@@ -66,42 +66,40 @@ class Chef
# }
# }
def children
- begin
# Grab the names of the children, append json, and make child entries
- @children ||= begin
- result = []
- data = root.get_json(api_path)
- data.keys.sort.each do |policy_name|
- data[policy_name]["revisions"].keys.each do |policy_revision|
- filename = "#{policy_name}-#{policy_revision}.json"
- result << make_child_entry(filename, true)
- end
+ @children ||= begin
+ result = []
+ data = root.get_json(api_path)
+ data.keys.sort.each do |policy_name|
+ data[policy_name]["revisions"].keys.each do |policy_revision|
+ filename = "#{policy_name}-#{policy_revision}.json"
+ result << make_child_entry(filename, true)
end
- result
end
- rescue Timeout::Error => e
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "Timeout retrieving children: #{e}")
- rescue Net::HTTPServerException => e
- # 404 = NotFoundError
- if $!.response.code == "404"
- # GET /organizations/ORG/policies returned 404, but that just might be because
- # we are talking to an older version of the server that doesn't support policies.
- # Do GET /orgqanizations/ORG to find out if the org exists at all.
- # TODO use server API version instead of a second network request.
- begin
- root.get_json(parent.api_path)
- # Return empty list if the organization exists but /policies didn't work
- []
- rescue Net::HTTPServerException => e
- if e.response.code == "404"
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
- end
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}")
+ result
+ end
+ rescue Timeout::Error => e
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "Timeout retrieving children: #{e}")
+ rescue Net::HTTPServerException => e
+ # 404 = NotFoundError
+ if $!.response.code == "404"
+ # GET /organizations/ORG/policies returned 404, but that just might be because
+ # we are talking to an older version of the server that doesn't support policies.
+ # Do GET /orgqanizations/ORG to find out if the org exists at all.
+ # TODO use server API version instead of a second network request.
+ begin
+ root.get_json(parent.api_path)
+ # Return empty list if the organization exists but /policies didn't work
+ []
+ rescue Net::HTTPServerException => e
+ if e.response.code == "404"
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
end
- # Anything else is unexpected (OperationFailedError)
- else
raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}")
end
+ # Anything else is unexpected (OperationFailedError)
+ else
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}")
end
end
diff --git a/lib/chef/chef_fs/file_system/chef_server/policy_group_entry.rb b/lib/chef/chef_fs/file_system/chef_server/policy_group_entry.rb
index b7413c44c5..df3d393d35 100644
--- a/lib/chef/chef_fs/file_system/chef_server/policy_group_entry.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/policy_group_entry.rb
@@ -93,7 +93,7 @@ class Chef
end
begin
- existing_group = Chef::JSONCompat.parse(self.read)
+ existing_group = Chef::JSONCompat.parse(read)
rescue NotFoundError
# It's OK if the group doesn't already exist, just means no existing policies
end
diff --git a/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb b/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb
index dfd26a0241..6ba53fab4b 100644
--- a/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb
@@ -71,40 +71,38 @@ class Chef
# Children are foo.json and bar.json in this case.
#
def children
- begin
# Grab the names of the children, append json, and make child entries
- @children ||= root.get_json(api_path).keys.sort.map do |key|
- make_child_entry(key, true)
- end
- rescue Timeout::Error => e
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "Timeout retrieving children: #{e}")
- rescue Net::HTTPServerException => e
- # 404 = NotFoundError
- if $!.response.code == "404"
-
- if parent.is_a?(ChefServerRootDir)
- # GET /organizations/ORG/<container> returned 404, but that just might be because
- # we are talking to an older version of the server that doesn't support policies.
- # Do GET /organizations/ORG to find out if the org exists at all.
- # TODO use server API version instead of a second network request.
- begin
- root.get_json(parent.api_path)
- # Return empty list if the organization exists but /policies didn't work
- []
- rescue Net::HTTPServerException => e
- if e.response.code == "404"
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
- end
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}")
+ @children ||= root.get_json(api_path).keys.sort.map do |key|
+ make_child_entry(key, true)
+ end
+ rescue Timeout::Error => e
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "Timeout retrieving children: #{e}")
+ rescue Net::HTTPServerException => e
+ # 404 = NotFoundError
+ if $!.response.code == "404"
+
+ if parent.is_a?(ChefServerRootDir)
+ # GET /organizations/ORG/<container> returned 404, but that just might be because
+ # we are talking to an older version of the server that doesn't support policies.
+ # Do GET /organizations/ORG to find out if the org exists at all.
+ # TODO use server API version instead of a second network request.
+ begin
+ root.get_json(parent.api_path)
+ # Return empty list if the organization exists but /policies didn't work
+ []
+ rescue Net::HTTPServerException => e
+ if e.response.code == "404"
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
end
- else
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}")
end
-
- # Anything else is unexpected (OperationFailedError)
else
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}")
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
end
+
+ # Anything else is unexpected (OperationFailedError)
+ else
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:children, self, e, "HTTP error retrieving children: #{e}")
end
end
diff --git a/lib/chef/chef_fs/file_system/chef_server/rest_list_entry.rb b/lib/chef/chef_fs/file_system/chef_server/rest_list_entry.rb
index b8ec5f8524..8f9e554526 100644
--- a/lib/chef/chef_fs/file_system/chef_server/rest_list_entry.rb
+++ b/lib/chef/chef_fs/file_system/chef_server/rest_list_entry.rb
@@ -69,7 +69,14 @@ class Chef
def exists?
if @exists.nil?
begin
- @exists = parent.children.any? { |child| child.api_child_name == api_child_name }
+ rest.get(api_path)
+ @exists = true
+ rescue Net::HTTPServerException => e
+ if e.response.code == "404"
+ @exists = false
+ else
+ raise
+ end
rescue Chef::ChefFS::FileSystem::NotFoundError
@exists = false
end
@@ -78,16 +85,14 @@ class Chef
end
def delete(recurse)
- begin
- rest.delete(api_path)
- rescue Timeout::Error => e
+ rest.delete(api_path)
+ rescue Timeout::Error => e
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:delete, self, e, "Timeout deleting: #{e}")
+ rescue Net::HTTPServerException => e
+ if e.response.code == "404"
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, e)
+ else
raise Chef::ChefFS::FileSystem::OperationFailedError.new(:delete, self, e, "Timeout deleting: #{e}")
- rescue Net::HTTPServerException => e
- if e.response.code == "404"
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, e)
- else
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:delete, self, e, "Timeout deleting: #{e}")
- end
end
end
@@ -96,17 +101,15 @@ class Chef
end
def _read_json
- begin
# Minimize the value (get rid of defaults) so the results don't look terrible
- root.get_json(api_path)
- rescue Timeout::Error => e
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "Timeout reading: #{e}")
- rescue Net::HTTPServerException => e
- if $!.response.code == "404"
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, e)
- else
- raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "HTTP error reading: #{e}")
- end
+ root.get_json(api_path)
+ rescue Timeout::Error => e
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "Timeout reading: #{e}")
+ rescue Net::HTTPServerException => e
+ if $!.response.code == "404"
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, e)
+ else
+ raise Chef::ChefFS::FileSystem::OperationFailedError.new(:read, self, e, "HTTP error reading: #{e}")
end
end
@@ -183,11 +186,9 @@ class Chef
end
def api_error_text(response)
- begin
- Chef::JSONCompat.parse(response.body)["error"].join("\n")
- rescue
- response.body
- end
+ Chef::JSONCompat.parse(response.body)["error"].join("\n")
+ rescue
+ response.body
end
end
diff --git a/lib/chef/chef_fs/file_system/memory/memory_file.rb b/lib/chef/chef_fs/file_system/memory/memory_file.rb
index 7eabc8fcb1..6dcefc72eb 100644
--- a/lib/chef/chef_fs/file_system/memory/memory_file.rb
+++ b/lib/chef/chef_fs/file_system/memory/memory_file.rb
@@ -11,7 +11,7 @@ class Chef
end
def read
- return @value
+ @value
end
end
end
diff --git a/lib/chef/chef_fs/file_system/multiplexed_dir.rb b/lib/chef/chef_fs/file_system/multiplexed_dir.rb
index 21abc012f8..cf1fb34345 100644
--- a/lib/chef/chef_fs/file_system/multiplexed_dir.rb
+++ b/lib/chef/chef_fs/file_system/multiplexed_dir.rb
@@ -17,22 +17,20 @@ class Chef
end
def children
- begin
- result = []
- seen = {}
+ result = []
+ seen = {}
# If multiple things have the same name, the first one wins.
- multiplexed_dirs.each do |dir|
- dir.children.each do |child|
- if seen[child.name]
- Chef::Log.warn("Child with name '#{child.name}' found in multiple directories: #{seen[child.name].path_for_printing} and #{child.path_for_printing}") unless seen[child.name].path_for_printing == child.path_for_printing
- else
- result << child
- seen[child.name] = child
- end
+ multiplexed_dirs.each do |dir|
+ dir.children.each do |child|
+ if seen[child.name]
+ Chef::Log.warn("Child with name '#{child.name}' found in multiple directories: #{seen[child.name].path_for_printing} and #{child.path_for_printing}") unless seen[child.name].path_for_printing == child.path_for_printing
+ else
+ result << child
+ seen[child.name] = child
end
end
- result
end
+ result
end
def make_child_entry(name)
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 1b640bc076..31b538b9ce 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
@@ -80,18 +80,16 @@ class Chef
# Customizations of base class
def chef_object
- begin
- cb = cookbook_version
- if !cb
- Chef::Log.error("Cookbook #{file_path} empty.")
- raise "Cookbook #{file_path} empty."
- end
- cb
- rescue => e
- Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{e}")
- Chef::Log.error(e.backtrace.join("\n"))
- raise
+ cb = cookbook_version
+ if !cb
+ Chef::Log.error("Cookbook #{file_path} empty.")
+ raise "Cookbook #{file_path} empty."
end
+ cb
+ rescue => e
+ Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{e}")
+ Chef::Log.error(e.backtrace.join("\n"))
+ raise
end
def children
@@ -112,7 +110,7 @@ class Chef
def self.canonical_cookbook_name(entry_name)
name_match = Chef::ChefFS::FileSystem::ChefServer::VersionedCookbookDir::VALID_VERSIONED_COOKBOOK_NAME.match(entry_name)
return nil if name_match.nil?
- return name_match[1]
+ name_match[1]
end
def canonical_cookbook_name(entry_name)
diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb
index 4019c6985b..90b8c88cff 100644
--- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb
+++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_cookbook_entry.rb
@@ -52,14 +52,12 @@ class Chef
end
def children
- begin
- entries = Dir.entries(file_path).sort.
- map { |child_name| make_child_entry(child_name) }.
- select { |child| child && can_have_child?(child.name, child.dir?) }
- entries.select { |entry| !(entry.dir? && entry.children.size == 0 ) }
- rescue Errno::ENOENT
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
- end
+ entries = Dir.entries(file_path).sort.
+ map { |child_name| make_child_entry(child_name) }.
+ select { |child| child && can_have_child?(child.name, child.dir?) }
+ entries.select { |entry| !(entry.dir? && entry.children.size == 0 ) }
+ rescue Errno::ENOENT
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
end
def can_have_child?(name, is_dir)
@@ -140,11 +138,9 @@ class Chef
end
def read
- begin
- File.open(file_path, "rb") { |f| f.read }
- rescue Errno::ENOENT
- raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
- end
+ File.open(file_path, "rb") { |f| f.read }
+ rescue Errno::ENOENT
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(self, $!)
end
def write(content)
diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb
index 1b26ced372..9ea9268ab1 100644
--- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb
+++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb
@@ -44,6 +44,7 @@ require "chef/chef_fs/data_handler/role_data_handler"
require "chef/chef_fs/data_handler/user_data_handler"
require "chef/chef_fs/data_handler/group_data_handler"
require "chef/chef_fs/data_handler/container_data_handler"
+require "chef/win32/security" if Chef::Platform.windows?
class Chef
module ChefFS
@@ -109,7 +110,19 @@ class Chef
else
child_paths[name].each do |path|
begin
- Dir.mkdir(path)
+ Dir.mkdir(path, 0700)
+ if Chef::Platform.windows?
+ all_mask = Chef::ReservedNames::Win32::API::Security::GENERIC_ALL
+ administrators = Chef::ReservedNames::Win32::Security::SID.Administrators
+ owner = Chef::ReservedNames::Win32::Security::SID.default_security_object_owner
+ dacl = Chef::ReservedNames::Win32::Security::ACL.create([
+ Chef::ReservedNames::Win32::Security::ACE.access_allowed(owner, all_mask),
+ Chef::ReservedNames::Win32::Security::ACE.access_allowed(administrators, all_mask),
+ ])
+ so = Chef::ReservedNames::Win32::Security::SecurableObject.new(path)
+ so.owner = owner
+ so.set_dacl(dacl, false)
+ end
rescue Errno::EEXIST
end
end
diff --git a/lib/chef/chef_fs/file_system/repository/cookbooks_dir.rb b/lib/chef/chef_fs/file_system/repository/cookbooks_dir.rb
index 0fd249a2c4..86eca95ba8 100644
--- a/lib/chef/chef_fs/file_system/repository/cookbooks_dir.rb
+++ b/lib/chef/chef_fs/file_system/repository/cookbooks_dir.rb
@@ -28,7 +28,7 @@ class Chef
class CookbooksDir < Repository::Directory
def chefignore
- @chefignore ||= Chef::Cookbook::Chefignore.new(self.file_path)
+ @chefignore ||= Chef::Cookbook::Chefignore.new(file_path)
rescue Errno::EISDIR, Errno::EACCES
# Work around a bug in Chefignore when chefignore is a directory
end
diff --git a/lib/chef/chef_fs/file_system/repository/nodes_dir.rb b/lib/chef/chef_fs/file_system/repository/nodes_dir.rb
index 33ca7ca709..a0dd0c9e51 100644
--- a/lib/chef/chef_fs/file_system/repository/nodes_dir.rb
+++ b/lib/chef/chef_fs/file_system/repository/nodes_dir.rb
@@ -20,6 +20,7 @@
require "chef/chef_fs/file_system/repository/node"
require "chef/chef_fs/file_system/repository/directory"
require "chef/chef_fs/file_system/exceptions"
+require "chef/win32/security" if Chef::Platform.windows?
class Chef
module ChefFS
@@ -30,6 +31,27 @@ class Chef
def make_child_entry(child_name)
Node.new(child_name, self)
end
+
+ def create_child(child_name, file_contents = nil)
+ child = super
+ File.chmod(0600, child.file_path)
+ if Chef::Platform.windows?
+ read_mask = Chef::ReservedNames::Win32::API::Security::GENERIC_READ
+ write_mask = Chef::ReservedNames::Win32::API::Security::GENERIC_WRITE
+ administrators = Chef::ReservedNames::Win32::Security::SID.Administrators
+ owner = Chef::ReservedNames::Win32::Security::SID.default_security_object_owner
+ dacl = Chef::ReservedNames::Win32::Security::ACL.create([
+ Chef::ReservedNames::Win32::Security::ACE.access_allowed(owner, read_mask),
+ Chef::ReservedNames::Win32::Security::ACE.access_allowed(owner, write_mask),
+ Chef::ReservedNames::Win32::Security::ACE.access_allowed(administrators, read_mask),
+ Chef::ReservedNames::Win32::Security::ACE.access_allowed(administrators, write_mask),
+ ])
+ so = Chef::ReservedNames::Win32::Security::SecurableObject.new(child.file_path)
+ so.owner = owner
+ so.set_dacl(dacl, false)
+ end
+ child
+ end
end
end
end
diff --git a/lib/chef/chef_fs/parallelizer.rb b/lib/chef/chef_fs/parallelizer.rb
index ccbf7ad96e..32de61e048 100644
--- a/lib/chef/chef_fs/parallelizer.rb
+++ b/lib/chef/chef_fs/parallelizer.rb
@@ -86,19 +86,17 @@ class Chef
private
def worker_loop
- begin
- until @stop_thread[Thread.current]
- begin
- task = @tasks.pop
- task.call
- rescue
- puts "ERROR #{$!}"
- puts $!.backtrace
- end
+ until @stop_thread[Thread.current]
+ begin
+ task = @tasks.pop
+ task.call
+ rescue
+ puts "ERROR #{$!}"
+ puts $!.backtrace
end
- ensure
- @stop_thread.delete(Thread.current)
end
+ ensure
+ @stop_thread.delete(Thread.current)
end
end
end
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index c857da1b93..c064d33209 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -22,6 +22,7 @@ require "chef/config"
require "chef/mixin/params_validate"
require "chef/mixin/path_sanity"
require "chef/log"
+require "chef/deprecated"
require "chef/server_api"
require "chef/api_client"
require "chef/api_client/registration"
diff --git a/lib/chef/cookbook/chefignore.rb b/lib/chef/cookbook/chefignore.rb
index 71ef53c9e5..dce58ecdb8 100644
--- a/lib/chef/cookbook/chefignore.rb
+++ b/lib/chef/cookbook/chefignore.rb
@@ -52,7 +52,7 @@ class Chef
ignore_globs << line.strip unless line =~ COMMENTS_AND_WHITESPACE
end
else
- Chef::Log.debug("No chefignore file found at #@ignore_file no files will be ignored")
+ Chef::Log.debug("No chefignore file found at #{@ignore_file} no files will be ignored")
end
ignore_globs
end
diff --git a/lib/chef/cookbook/cookbook_version_loader.rb b/lib/chef/cookbook/cookbook_version_loader.rb
index af8b2e043e..b9de9a7482 100644
--- a/lib/chef/cookbook/cookbook_version_loader.rb
+++ b/lib/chef/cookbook/cookbook_version_loader.rb
@@ -108,10 +108,10 @@ class Chef
@uploaded_cookbook_version_file = File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE)
end
- if File.exists?(File.join(cookbook_path, "metadata.rb"))
- @metadata_filenames << File.join(cookbook_path, "metadata.rb")
- elsif File.exists?(File.join(cookbook_path, "metadata.json"))
+ if File.exists?(File.join(cookbook_path, "metadata.json"))
@metadata_filenames << File.join(cookbook_path, "metadata.json")
+ elsif File.exists?(File.join(cookbook_path, "metadata.rb"))
+ @metadata_filenames << File.join(cookbook_path, "metadata.rb")
elsif @uploaded_cookbook_version_file
@metadata_filenames << @uploaded_cookbook_version_file
end
@@ -305,40 +305,34 @@ class Chef
end
def apply_ruby_metadata(file)
- begin
- @metadata.from_file(file)
- rescue Chef::Exceptions::JSON::ParseError
- Chef::Log.error("Error evaluating metadata.rb for #@inferred_cookbook_name in " + file)
- raise
- end
+ @metadata.from_file(file)
+ rescue Chef::Exceptions::JSON::ParseError
+ Chef::Log.error("Error evaluating metadata.rb for #{@inferred_cookbook_name} in " + file)
+ raise
end
def apply_json_metadata(file)
- begin
- @metadata.from_json(IO.read(file))
- rescue Chef::Exceptions::JSON::ParseError
- Chef::Log.error("Couldn't parse cookbook metadata JSON for #@inferred_cookbook_name in " + file)
- raise
- end
+ @metadata.from_json(IO.read(file))
+ rescue Chef::Exceptions::JSON::ParseError
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #{@inferred_cookbook_name} in " + file)
+ raise
end
def apply_json_cookbook_version_metadata(file)
- begin
- data = Chef::JSONCompat.parse(IO.read(file))
- @metadata.from_hash(data["metadata"])
- # the JSON cookbok metadata file is only used by chef-zero.
- # The Chef Server API currently does not enforce that the metadata
- # have a `name` field, but that will cause an error when attempting
- # to load the cookbook. To keep compatibility, we fake it by setting
- # the metadata name from the cookbook version object's name.
- #
- # This behavior can be removed if/when Chef Server enforces that the
- # metadata contains a name key.
- @metadata.name(data["cookbook_name"]) unless data["metadata"].key?("name")
- rescue Chef::Exceptions::JSON::ParseError
- Chef::Log.error("Couldn't parse cookbook metadata JSON for #@inferred_cookbook_name in " + file)
- raise
- end
+ data = Chef::JSONCompat.parse(IO.read(file))
+ @metadata.from_hash(data["metadata"])
+ # the JSON cookbok metadata file is only used by chef-zero.
+ # The Chef Server API currently does not enforce that the metadata
+ # have a `name` field, but that will cause an error when attempting
+ # to load the cookbook. To keep compatibility, we fake it by setting
+ # the metadata name from the cookbook version object's name.
+ #
+ # This behavior can be removed if/when Chef Server enforces that the
+ # metadata contains a name key.
+ @metadata.name(data["cookbook_name"]) unless data["metadata"].key?("name")
+ rescue Chef::Exceptions::JSON::ParseError
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #{@inferred_cookbook_name} in " + file)
+ raise
end
def set_frozen
@@ -347,7 +341,7 @@ class Chef
data = Chef::JSONCompat.parse(IO.read(uploaded_cookbook_version_file))
@frozen = data["frozen?"]
rescue Chef::Exceptions::JSON::ParseError
- Chef::Log.error("Couldn't parse cookbook metadata JSON for #@inferred_cookbook_name in #{uploaded_cookbook_version_file}")
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #{@inferred_cookbook_name} in #{uploaded_cookbook_version_file}")
raise
end
end
diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb
index 02f9831d70..3f23bc2056 100644
--- a/lib/chef/cookbook/metadata.rb
+++ b/lib/chef/cookbook/metadata.rb
@@ -462,7 +462,7 @@ class Chef
cookbook.fully_qualified_recipe_names.map do |recipe_name|
unqualified_name =
if recipe_name =~ /::default$/
- self.name.to_s
+ name.to_s
else
recipe_name
end
@@ -567,29 +567,29 @@ class Chef
def to_hash
{
- NAME => self.name,
- DESCRIPTION => self.description,
- LONG_DESCRIPTION => self.long_description,
- MAINTAINER => self.maintainer,
- MAINTAINER_EMAIL => self.maintainer_email,
- LICENSE => self.license,
- PLATFORMS => self.platforms,
- DEPENDENCIES => self.dependencies,
- RECOMMENDATIONS => self.recommendations,
- SUGGESTIONS => self.suggestions,
- CONFLICTING => self.conflicting,
- PROVIDING => self.providing,
- REPLACING => self.replacing,
- ATTRIBUTES => self.attributes,
- GROUPINGS => self.groupings,
- RECIPES => self.recipes,
- VERSION => self.version,
- SOURCE_URL => self.source_url,
- ISSUES_URL => self.issues_url,
- PRIVACY => self.privacy,
- CHEF_VERSIONS => gem_requirements_to_array(*self.chef_versions),
- OHAI_VERSIONS => gem_requirements_to_array(*self.ohai_versions),
- GEMS => self.gems,
+ NAME => name,
+ DESCRIPTION => description,
+ LONG_DESCRIPTION => long_description,
+ MAINTAINER => maintainer,
+ MAINTAINER_EMAIL => maintainer_email,
+ 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,
+ ISSUES_URL => issues_url,
+ PRIVACY => privacy,
+ CHEF_VERSIONS => gem_requirements_to_array(*chef_versions),
+ OHAI_VERSIONS => gem_requirements_to_array(*ohai_versions),
+ GEMS => gems,
}
end
@@ -598,7 +598,7 @@ class Chef
end
def self.from_hash(o)
- cm = self.new()
+ cm = new()
cm.from_hash(o)
cm
end
@@ -632,7 +632,7 @@ class Chef
def self.from_json(string)
o = Chef::JSONCompat.from_json(string)
- self.from_hash(o)
+ from_hash(o)
end
def self.validate_json(json_str)
@@ -641,8 +641,8 @@ class Chef
VERSION_CONSTRAINTS.each do |dependency_type, hash_key|
if dependency_group = o[hash_key]
dependency_group.each do |cb_name, constraints|
- if metadata.respond_to?(method_name)
- metadata.public_send(method_name, cb_name, *Array(constraints))
+ if metadata.respond_to?(dependency_type)
+ metadata.public_send(dependency_type, cb_name, *Array(constraints))
end
end
end
@@ -862,12 +862,12 @@ INVALID
return if !options[:choice].is_a?(Array) || options[:choice].empty?
if options[:default].is_a?(String) && options[:default] != ""
- raise ArgumentError, "Default must be one of your choice values!" if options[:choice].index(options[:default]) == nil
+ raise ArgumentError, "Default must be one of your choice values!" if options[:choice].index(options[:default]).nil?
end
if options[:default].is_a?(Array) && !options[:default].empty?
options[:default].each do |val|
- raise ArgumentError, "Default values must be a subset of your choice values!" if options[:choice].index(val) == nil
+ raise ArgumentError, "Default values must be a subset of your choice values!" if options[:choice].index(val).nil?
end
end
end
diff --git a/lib/chef/cookbook/syntax_check.rb b/lib/chef/cookbook/syntax_check.rb
index f8559433dc..8d0d636bd2 100644
--- a/lib/chef/cookbook/syntax_check.rb
+++ b/lib/chef/cookbook/syntax_check.rb
@@ -110,7 +110,7 @@ class Chef
end
def remove_uninteresting_ruby_files(file_list)
- file_list.reject { |f| f =~ %r{#{cookbook_path}/(files|templates)/} }
+ file_list.reject { |f| f =~ %r{#{Regexp.quote(cookbook_path)}/(files|templates)/} }
end
def ruby_files
diff --git a/lib/chef/cookbook_loader.rb b/lib/chef/cookbook_loader.rb
index bff77fa13b..a965b43c61 100644
--- a/lib/chef/cookbook_loader.rb
+++ b/lib/chef/cookbook_loader.rb
@@ -137,7 +137,7 @@ class Chef
alias :key? :has_key?
def each
- @cookbooks_by_name.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |cname|
+ @cookbooks_by_name.keys.sort_by(&:to_s).each do |cname|
yield(cname, @cookbooks_by_name[cname])
end
end
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 8de9cb26dd..2037b5f972 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -54,12 +54,12 @@ class Chef
attr_accessor :metadata_filenames
def status=(new_status)
- Chef.log_deprecation("Deprecated method `status' called. This method will be removed.")
+ Chef.deprecated(:internal_api, "Deprecated method `status' called. This method will be removed.")
@status = new_status
end
def status
- Chef.log_deprecation("Deprecated method `status' called. This method will be removed.")
+ Chef.deprecated(:internal_api, "Deprecated method `status' called. This method will be removed.")
@status
end
@@ -485,7 +485,7 @@ class Chef
end
def self.json_create(o)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::CookbookVersion#from_hash")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::CookbookVersion#from_hash")
from_hash(o)
end
@@ -496,7 +496,7 @@ class Chef
# @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.log_deprecation("Deprecated method #generate_manifest_with_urls.")
+ Chef.deprecated(:internal_api, "Deprecated method #generate_manifest_with_urls.")
rendered_manifest = manifest.dup
COOKBOOK_SEGMENTS.each do |segment|
@@ -549,7 +549,7 @@ class Chef
end
def chef_server_rest
- @chef_server_rest ||= self.chef_server_rest
+ @chef_server_rest ||= chef_server_rest
end
def self.chef_server_rest
@@ -600,11 +600,11 @@ class Chef
end
def <=>(other)
- raise Chef::Exceptions::CookbookVersionNameMismatch if self.name != other.name
+ raise Chef::Exceptions::CookbookVersionNameMismatch if name != other.name
# FIXME: can we change the interface to the Metadata class such
# that metadata.version returns a Chef::Version instance instead
# of a string?
- Chef::Version.new(self.version) <=> Chef::Version.new(other.version)
+ Chef::Version.new(version) <=> Chef::Version.new(other.version)
end
private
diff --git a/lib/chef/data_bag.rb b/lib/chef/data_bag.rb
index f107f98f28..4bb656a2c8 100644
--- a/lib/chef/data_bag.rb
+++ b/lib/chef/data_bag.rb
@@ -80,7 +80,7 @@ class Chef
# Create a Chef::Role from JSON
def self.json_create(o)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::DataBag#from_hash")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::DataBag#from_hash")
from_hash(o)
end
@@ -137,7 +137,7 @@ class Chef
end
end
end
- return data_bag
+ data_bag
else
Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("data/#{name}")
end
diff --git a/lib/chef/data_bag_item.rb b/lib/chef/data_bag_item.rb
index 568c511c44..2bd27e3eef 100644
--- a/lib/chef/data_bag_item.rb
+++ b/lib/chef/data_bag_item.rb
@@ -107,9 +107,9 @@ class Chef
end
def to_hash
- result = self.raw_data.dup
+ result = raw_data.dup
result["chef_type"] = "data_bag_item"
- result["data_bag"] = self.data_bag.to_s
+ result["data_bag"] = data_bag.to_s
result
end
@@ -141,7 +141,7 @@ class Chef
# Create a Chef::DataBagItem from JSON
def self.json_create(o)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::DataBagItem#from_hash")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::DataBagItem#from_hash")
from_hash(o)
end
@@ -207,7 +207,7 @@ class Chef
end
def pretty_print(pretty_printer)
- pretty_printer.pp({ "data_bag_item('#{data_bag}', '#{id}')" => self.to_hash })
+ pretty_printer.pp({ "data_bag_item('#{data_bag}', '#{id}')" => to_hash })
end
def id
diff --git a/lib/chef/data_collector.rb b/lib/chef/data_collector.rb
index da7aeee3b8..0a92b800a6 100644
--- a/lib/chef/data_collector.rb
+++ b/lib/chef/data_collector.rb
@@ -2,7 +2,7 @@
# Author:: Adam Leff (<adamleff@chef.io>)
# Author:: Ryan Cragun (<ryan@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");
@@ -174,12 +174,13 @@ class Chef
# resource, and we only care about tracking top-level resources.
def resource_current_state_loaded(new_resource, action, current_resource)
return if nested_resource?(new_resource)
- update_current_resource_report(create_resource_report(new_resource, action, current_resource))
+ initialize_resource_report_if_needed(new_resource, action, current_resource)
end
# see EventDispatch::Base#resource_up_to_date
# Mark our ResourceReport status accordingly
def resource_up_to_date(new_resource, action)
+ initialize_resource_report_if_needed(new_resource, action)
current_resource_report.up_to_date unless nested_resource?(new_resource)
end
@@ -190,15 +191,15 @@ class Chef
def resource_skipped(new_resource, action, conditional)
return if nested_resource?(new_resource)
- resource_report = create_resource_report(new_resource, action)
- resource_report.skipped(conditional)
- update_current_resource_report(resource_report)
+ initialize_resource_report_if_needed(new_resource, action)
+ current_resource_report.skipped(conditional)
end
# see EventDispatch::Base#resource_updated
# Flag the current ResourceReport instance as updated (as long as it's
# a top-level resource).
def resource_updated(new_resource, action)
+ initialize_resource_report_if_needed(new_resource, action)
current_resource_report.updated unless nested_resource?(new_resource)
end
@@ -207,6 +208,7 @@ class Chef
# long as it's a top-level resource, and update the run error text
# with the proper Formatter.
def resource_failed(new_resource, action, exception)
+ initialize_resource_report_if_needed(new_resource, action)
current_resource_report.failed(exception) unless nested_resource?(new_resource)
update_error_description(
Formatters::ErrorMapper.resource_failed(
@@ -224,7 +226,7 @@ class Chef
if current_resource_report && !nested_resource?(new_resource)
current_resource_report.finish
add_resource_report(current_resource_report)
- update_current_resource_report(nil)
+ clear_current_resource_report
end
end
@@ -274,7 +276,7 @@ class Chef
# see EventDispatch::Base#deprecation
# Append a received deprecation to the list of deprecations
def deprecation(message, location = caller(2..2)[0])
- add_deprecation(message, location)
+ add_deprecation(message.message, message.url, location)
end
private
@@ -286,9 +288,9 @@ class Chef
# raise an exception.
def setup_http_client
if data_collector_token.nil?
- Chef::ServerAPI.new(data_collector_server_url)
+ Chef::ServerAPI.new(data_collector_server_url, validate_utf8: false)
else
- Chef::HTTP::SimpleJSON.new(data_collector_server_url)
+ Chef::HTTP::SimpleJSON.new(data_collector_server_url, validate_utf8: false)
end
end
@@ -331,7 +333,6 @@ class Chef
def send_to_data_collector(message)
return unless data_collector_accessible?
- Chef::Log.debug("data_collector_reporter: POSTing the following message to #{data_collector_server_url}: #{message}")
http.post(nil, message, headers)
end
@@ -402,16 +403,17 @@ class Chef
@run_status = run_status
end
- def update_current_resource_report(resource_report)
- @current_resource_report = resource_report
- end
-
def update_error_description(discription_hash)
@error_descriptions = discription_hash
end
- def add_deprecation(message, location)
- @deprecations << { message: message, location: location }
+ def add_deprecation(message, url, location)
+ @deprecations << { message: message, url: url, location: location }
+ end
+
+ def initialize_resource_report_if_needed(new_resource, action, current_resource = nil)
+ return unless current_resource_report.nil?
+ @current_resource_report = create_resource_report(new_resource, action, current_resource)
end
def create_resource_report(new_resource, action, current_resource = nil)
@@ -422,27 +424,38 @@ class Chef
)
end
+ def clear_current_resource_report
+ @current_resource_report = nil
+ end
+
def detect_unprocessed_resources
- # create a Set containing all resource+action combinations from
- # the Resource Collection
- collection_resources = Set.new
+ # create a Hash (for performance reasons, rather than an Array) containing all
+ # resource+action combinations from the Resource Collection
+ #
+ # We use the object ID instead of the resource itself in the Hash key because
+ # we currently allow users to create a property called "hash" which creates
+ # a #hash instance method on the resource. Ruby expects that to be a Fixnum,
+ # so bad things happen when adding an object to an Array or a Hash if it's not.
+ collection_resources = {}
run_context.resource_collection.all_resources.each do |resource|
Array(resource.action).each do |action|
- collection_resources.add([resource, action])
+ collection_resources[[resource.__id__, action]] = resource
end
end
- # Delete from the Set any resource+action combination we have
+ # Delete from the Hash any resource+action combination we have
# already processed.
all_resource_reports.each do |report|
- collection_resources.delete([report.resource, report.action])
+ collection_resources.delete([report.resource.__id__, report.action])
end
- # The items remaining in the Set are unprocessed resource+actions,
+ # The items remaining in the Hash are unprocessed resource+actions,
# so we'll create new resource reports for them which default to
# a state of "unprocessed".
- collection_resources.each do |resource, action|
- add_resource_report(create_resource_report(resource, action))
+ collection_resources.each do |key, resource|
+ # The Hash key is an array of the Resource's object ID and the action.
+ # We need to pluck out the action.
+ add_resource_report(create_resource_report(resource, key[1]))
end
end
@@ -455,8 +468,10 @@ class Chef
end
def validate_data_collector_server_url!
- raise Chef::Exceptions::ConfigurationError,
- "Chef::Config[:data_collector][:server_url] is empty. Please supply a valid URL." if data_collector_server_url.empty?
+ if data_collector_server_url.empty?
+ raise Chef::Exceptions::ConfigurationError,
+ "Chef::Config[:data_collector][:server_url] is empty. Please supply a valid URL."
+ end
begin
uri = URI(data_collector_server_url)
@@ -464,8 +479,10 @@ class Chef
raise Chef::Exceptions::ConfigurationError, "Chef::Config[:data_collector][:server_url] (#{data_collector_server_url}) is not a valid URI."
end
- raise Chef::Exceptions::ConfigurationError,
- "Chef::Config[:data_collector][:server_url] (#{data_collector_server_url}) is a URI with no host. Please supply a valid URL." if uri.host.nil?
+ if uri.host.nil?
+ raise Chef::Exceptions::ConfigurationError,
+ "Chef::Config[:data_collector][:server_url] (#{data_collector_server_url}) is a URI with no host. Please supply a valid URL."
+ end
end
end
end
diff --git a/lib/chef/data_collector/messages.rb b/lib/chef/data_collector/messages.rb
index e0dfd6cb67..c0683534a9 100644
--- a/lib/chef/data_collector/messages.rb
+++ b/lib/chef/data_collector/messages.rb
@@ -18,7 +18,6 @@
# limitations under the License.
#
-require "json"
require "securerandom"
require_relative "messages/helpers"
@@ -83,12 +82,14 @@ class Chef
"deprecations" => reporter_data[:deprecations],
}
- message["error"] = {
- "class" => run_status.exception.class,
- "message" => run_status.exception.message,
- "backtrace" => run_status.exception.backtrace,
- "description" => reporter_data[:error_descriptions],
- } if run_status.exception
+ if run_status.exception
+ message["error"] = {
+ "class" => run_status.exception.class,
+ "message" => run_status.exception.message,
+ "backtrace" => run_status.exception.backtrace,
+ "description" => reporter_data[:error_descriptions],
+ }
+ end
message
end
diff --git a/lib/chef/data_collector/messages/helpers.rb b/lib/chef/data_collector/messages/helpers.rb
index c0c700f847..f42ddaaa4e 100644
--- a/lib/chef/data_collector/messages/helpers.rb
+++ b/lib/chef/data_collector/messages/helpers.rb
@@ -76,7 +76,7 @@ class Chef
def chef_server_organization
return "unknown_organization" unless Chef::Config[:chef_server_url]
- Chef::Config[:chef_server_url].match(%r{/+organizations/+(\w+)}).nil? ? "unknown_organization" : $1
+ Chef::Config[:chef_server_url].match(%r{/+organizations/+([a-z0-9][a-z0-9_-]{0,254})}).nil? ? "unknown_organization" : $1
end
#
@@ -142,14 +142,14 @@ class Chef
# @return [Hash] DataCollector metadata for this node
#
def metadata
- JSON.load(Chef::FileCache.load(metadata_filename))
+ Chef::JSONCompat.parse(Chef::FileCache.load(metadata_filename))
rescue Chef::Exceptions::FileNotFound
{}
end
def update_metadata(key, value)
updated_metadata = metadata.tap { |x| x[key] = value }
- Chef::FileCache.store(metadata_filename, updated_metadata.to_json, 0644)
+ Chef::FileCache.store(metadata_filename, Chef::JSONCompat.to_json(updated_metadata), 0644)
end
def metadata_filename
diff --git a/lib/chef/decorator.rb b/lib/chef/decorator.rb
index 546c49baed..ac0f8fdfbb 100644
--- a/lib/chef/decorator.rb
+++ b/lib/chef/decorator.rb
@@ -52,7 +52,7 @@ class Chef
# adding the define_singleton_method call and @__defined_methods__ tracking
def method_missing(m, *args, &block)
r = true
- target = self.__getobj__ { r = false }
+ target = __getobj__ { r = false }
if r && target.respond_to?(m)
# these next 4 lines are the patched code
diff --git a/lib/chef/decorator/unchain.rb b/lib/chef/decorator/unchain.rb
index 8093c70f4c..b1e1f9fce1 100644
--- a/lib/chef/decorator/unchain.rb
+++ b/lib/chef/decorator/unchain.rb
@@ -44,10 +44,10 @@ class Chef
if symbol == :to_ary
merged_attributes.send(symbol, *args)
elsif args.empty?
- Chef.log_deprecation %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"])}
+ 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.log_deprecation %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")}
+ 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
diff --git a/lib/chef/deprecated.rb b/lib/chef/deprecated.rb
new file mode 100644
index 0000000000..e5026d2317
--- /dev/null
+++ b/lib/chef/deprecated.rb
@@ -0,0 +1,250 @@
+#--
+# Copyright:: Copyright 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/convert_to_class_name"
+
+# Structured deprecations have a unique URL associated with them, which must exist before the deprecation is merged.
+class Chef
+ class Deprecated
+
+ class << self
+ include Chef::Mixin::ConvertToClassName
+
+ def create(type, message = nil, location = nil)
+ Chef::Deprecated.const_get(convert_to_class_name(type.to_s)).send(:new, message, location)
+ end
+ end
+
+ class Base
+ BASE_URL = "https://docs.chef.io/deprecations_"
+
+ attr_accessor :message, :location
+
+ def initialize(msg = nil, location = nil)
+ @message = msg if msg
+ @location = location if location
+ end
+
+ def link
+ "Please see #{url} for further details and information on how to correct this problem."
+ end
+
+ def url
+ "#{BASE_URL}#{target}"
+ end
+
+ # We know that the only time this gets called is by Chef::Log.deprecation,
+ # so special case
+ def <<(location)
+ @location = location
+ end
+
+ def inspect
+ "#{message} (CHEF-#{id})#{location}.\n#{link}"
+ end
+
+ def id
+ raise NotImplementedError, "subclasses of Chef::Deprecated::Base should define #id with a unique number"
+ end
+
+ def target
+ raise NotImplementedError, "subclasses of Chef::Deprecated::Base should define #target"
+ end
+ end
+
+ class JsonAutoInflate < Base
+ def id
+ 1
+ end
+
+ def target
+ "json_auto_inflate.html"
+ end
+ end
+
+ class ExitCode < Base
+ def id
+ 2
+ end
+
+ def target
+ "exit_code.html"
+ end
+ end
+
+ class ChefGemCompileTime < Base
+ def id
+ 3
+ end
+
+ def target
+ "chef_gem_compile_time.html"
+ end
+ end
+
+ class Attributes < Base
+ def id
+ 4
+ end
+
+ def target
+ "attributes.html"
+ end
+ end
+
+ class CustomResource < Base
+ def id
+ 5
+ end
+
+ def target
+ "custom_resource_cleanups.html"
+ end
+ end
+
+ class EasyInstall < Base
+ def id
+ 6
+ end
+
+ def target
+ "easy_install.html"
+ end
+ end
+
+ class VerifyFile < Base
+ def id
+ 7
+ end
+
+ def target
+ "verify_file.html"
+ end
+ end
+
+ class SupportsProperty < Base
+ def id
+ 8
+ end
+
+ def target
+ "supports_property.html"
+ end
+ end
+
+ class ChefRest < Base
+ def id
+ 9
+ end
+
+ def target
+ "chef_rest.html"
+ end
+ end
+
+ class PropertyNameCollision < Base
+ def id
+ 11
+ end
+
+ def target
+ "property_name_collision.html"
+ end
+ end
+
+ class LaunchdHashProperty < Base
+ def id
+ 12
+ end
+
+ def target
+ "launchd_hash_property.html"
+ end
+ end
+
+ class ChefPlatformMethods < Base
+ def id
+ 13
+ end
+
+ def target
+ "chef_platform_methods.html"
+ end
+ end
+
+ class RunCommand < Base
+ def id
+ 14
+ end
+
+ def target
+ "run_command.html"
+ end
+ end
+
+ class PackageMisc < Base
+ def id
+ 15
+ end
+
+ def target
+ "package_misc.html"
+ end
+ end
+
+ class ResourceCloning < Base
+ def id
+ 3694
+ end
+
+ def target
+ "resource_cloning.html"
+ end
+ end
+
+ class InternalApi < Base
+ def id
+ 0
+ end
+
+ def target
+ "internal_api.html"
+ end
+ end
+
+ class DnfPackageAllowDowngrade < Base
+ def id
+ 10
+ end
+
+ def target
+ "dnf_package_allow_downgrade.html"
+ end
+ end
+
+ class Generic < Base
+ def url
+ "https://docs.chef.io/chef_deprecations_client.html"
+ end
+
+ def inspect
+ "#{message}\nThis is a generic error message and should be updated to have a proper deprecation class. #{location}\nPlease see #{url} for an overview of Chef deprecations."
+ end
+ end
+
+ end
+end
diff --git a/lib/chef/deprecation/provider/remote_directory.rb b/lib/chef/deprecation/provider/remote_directory.rb
index 5e5188f28b..9b442651d7 100644
--- a/lib/chef/deprecation/provider/remote_directory.rb
+++ b/lib/chef/deprecation/provider/remote_directory.rb
@@ -22,7 +22,7 @@ class Chef
module RemoteDirectory
def directory_root_in_cookbook_cache
- Chef.log_deprecation "the Chef::Provider::RemoteDirectory#directory_root_in_cookbook_cache method is deprecated"
+ Chef.deprecated :internal_api, "the Chef::Provider::RemoteDirectory#directory_root_in_cookbook_cache method is deprecated"
@directory_root_in_cookbook_cache ||=
begin
diff --git a/lib/chef/deprecation/warnings.rb b/lib/chef/deprecation/warnings.rb
index 411e95ea39..f5feb91063 100644
--- a/lib/chef/deprecation/warnings.rb
+++ b/lib/chef/deprecation/warnings.rb
@@ -23,10 +23,9 @@ class Chef
def add_deprecation_warnings_for(method_names)
method_names.each do |name|
define_method(name) do |*args|
- message = []
- message << "Method '#{name}' of '#{self.class}' is deprecated. It will be removed in Chef 13."
- message << "Please update your cookbooks accordingly."
- Chef.log_deprecation(message)
+ message = "Method '#{name}' of '#{self.class}' is deprecated. It will be removed in Chef 13."
+ message << " Please update your cookbooks accordingly."
+ Chef.deprecated(:internal_api, message)
super(*args)
end
end
diff --git a/lib/chef/dsl/audit.rb b/lib/chef/dsl/audit.rb
index 98271dc5cb..9ef798df91 100644
--- a/lib/chef/dsl/audit.rb
+++ b/lib/chef/dsl/audit.rb
@@ -38,8 +38,8 @@ class Chef
cookbook_name = self.cookbook_name
metadata = {
cookbook_name: cookbook_name,
- cookbook_version: self.run_context.cookbook_collection[cookbook_name].version,
- recipe_name: self.recipe_name,
+ cookbook_version: run_context.cookbook_collection[cookbook_name].version,
+ recipe_name: recipe_name,
line_number: block.source_location[1],
}
diff --git a/lib/chef/dsl/declare_resource.rb b/lib/chef/dsl/declare_resource.rb
index 5bd1f7fb8e..e48d741c60 100644
--- a/lib/chef/dsl/declare_resource.rb
+++ b/lib/chef/dsl/declare_resource.rb
@@ -287,7 +287,7 @@ class Chef
run_context: run_context,
cookbook_name: cookbook_name,
recipe_name: recipe_name,
- enclosing_provider: self.is_a?(Chef::Provider) ? self : nil
+ enclosing_provider: is_a?(Chef::Provider) ? self : nil
).build(&resource_attrs_block)
end
end
diff --git a/lib/chef/dsl/method_missing.rb b/lib/chef/dsl/method_missing.rb
index 51c3eac606..2917a54ee8 100644
--- a/lib/chef/dsl/method_missing.rb
+++ b/lib/chef/dsl/method_missing.rb
@@ -37,7 +37,7 @@ class Chef
# method_missing manually. Not a fan. Not. A. Fan.
#
if respond_to?(method_symbol)
- Chef.log_deprecation("Calling method_missing(#{method_symbol.inspect}) directly is deprecated in Chef 12 and will be removed in Chef 13. Use public_send() or send() instead.")
+ Chef.deprecated(:internal_api, "Calling method_missing(#{method_symbol.inspect}) directly is deprecated in Chef 12 and will be removed in Chef 13. Use public_send() or send() instead.")
return send(method_symbol, *args, &block)
end
@@ -46,7 +46,7 @@ class Chef
# never called. DEPRECATED.
#
if run_context.definitions.has_key?(method_symbol.to_sym)
- Chef.log_deprecation("Definition #{method_symbol} (#{run_context.definitions[method_symbol.to_sym]}) was added to the run_context without calling Chef::DSL::Definitions.add_definition(#{method_symbol.to_sym.inspect}). This will become required in Chef 13.")
+ Chef.deprecated(:internal_api, "Definition #{method_symbol} (#{run_context.definitions[method_symbol.to_sym]}) was added to the run_context without calling Chef::DSL::Definitions.add_definition(#{method_symbol.to_sym.inspect}). This will become required in Chef 13.")
Chef::DSL::Definitions.add_definition(method_symbol)
return send(method_symbol, *args, &block)
end
diff --git a/lib/chef/dsl/platform_introspection.rb b/lib/chef/dsl/platform_introspection.rb
index a0c2d33967..dc309f9acb 100644
--- a/lib/chef/dsl/platform_introspection.rb
+++ b/lib/chef/dsl/platform_introspection.rb
@@ -68,41 +68,39 @@ class Chef
private
def match_versions(node)
- begin
- platform, version = node[:platform].to_s, node[:platform_version].to_s
- return nil unless @values.key?(platform)
- node_version = Chef::Version::Platform.new(version)
- key_matches = []
- keys = @values[platform].keys
- keys.each do |k|
- begin
- if Chef::VersionConstraint::Platform.new(k).include?(node_version)
- key_matches << k
- end
- rescue Chef::Exceptions::InvalidVersionConstraint => e
- Chef::Log.debug "Caught InvalidVersionConstraint. This means that a key in value_for_platform cannot be interpreted as a Chef::VersionConstraint::Platform."
- Chef::Log.debug(e)
+ platform, version = node[:platform].to_s, node[:platform_version].to_s
+ return nil unless @values.key?(platform)
+ node_version = Chef::Version::Platform.new(version)
+ key_matches = []
+ keys = @values[platform].keys
+ keys.each do |k|
+ begin
+ if Chef::VersionConstraint::Platform.new(k).include?(node_version)
+ key_matches << k
end
+ rescue Chef::Exceptions::InvalidVersionConstraint => e
+ Chef::Log.debug "Caught InvalidVersionConstraint. This means that a key in value_for_platform cannot be interpreted as a Chef::VersionConstraint::Platform."
+ Chef::Log.debug(e)
end
- return @values[platform][version] if key_matches.include?(version)
- case key_matches.length
- when 0
- return nil
- when 1
- return @values[platform][key_matches.first]
- else
- raise "Multiple matches detected for #{platform} with values #{@values}. The matches are: #{key_matches}"
- end
- rescue Chef::Exceptions::InvalidCookbookVersion => e
- # Lets not break because someone passes a weird string like 'default' :)
- Chef::Log.debug(e)
- Chef::Log.debug "InvalidCookbookVersion exceptions are common and expected here: the generic constraint matcher attempted to match something which is not a constraint. Moving on to next version or constraint"
- return nil
- rescue Chef::Exceptions::InvalidPlatformVersion => e
- Chef::Log.debug "Caught InvalidPlatformVersion, this means that Chef::Version::Platform does not know how to turn #{node_version} into an x.y.z format"
- Chef::Log.debug(e)
+ end
+ return @values[platform][version] if key_matches.include?(version)
+ case key_matches.length
+ when 0
return nil
+ when 1
+ return @values[platform][key_matches.first]
+ else
+ raise "Multiple matches detected for #{platform} with values #{@values}. The matches are: #{key_matches}"
end
+ rescue Chef::Exceptions::InvalidCookbookVersion => e
+ # Lets not break because someone passes a weird string like 'default' :)
+ Chef::Log.debug(e)
+ Chef::Log.debug "InvalidCookbookVersion exceptions are common and expected here: the generic constraint matcher attempted to match something which is not a constraint. Moving on to next version or constraint"
+ return nil
+ rescue Chef::Exceptions::InvalidPlatformVersion => e
+ Chef::Log.debug "Caught InvalidPlatformVersion, this means that Chef::Version::Platform does not know how to turn #{node_version} into an x.y.z format"
+ Chef::Log.debug(e)
+ return nil
end
def set(platforms, value)
@@ -257,8 +255,8 @@ class Chef
def docker?(node = run_context.nil? ? nil : run_context.node)
# Using "File.exist?('/.dockerinit') || File.exist?('/.dockerenv')" makes Travis sad,
# and that makes us sad too.
- node && node[:virtualization] && node[:virtualization][:systems] &&
- node[:virtualization][:systems][:docker] && node[:virtualization][:systems][:docker] == "guest"
+ !!(node && node[:virtualization] && node[:virtualization][:systems] &&
+ node[:virtualization][:systems][:docker] && node[:virtualization][:systems][:docker] == "guest")
end
end
diff --git a/lib/chef/dsl/reboot_pending.rb b/lib/chef/dsl/reboot_pending.rb
index e8982d290e..fdd0f5a62b 100644
--- a/lib/chef/dsl/reboot_pending.rb
+++ b/lib/chef/dsl/reboot_pending.rb
@@ -30,7 +30,7 @@ class Chef
# Note that we will silently miss any other platform-specific reboot notices besides Windows+Ubuntu.
def reboot_pending?
# don't break when used as a mixin in contexts without #node (e.g. specs).
- if self.respond_to?(:node, true) && node.run_context.reboot_requested?
+ if respond_to?(:node, true) && node.run_context.reboot_requested?
true
elsif platform?("windows")
# PendingFileRenameOperations contains pairs (REG_MULTI_SZ) of filenames that cannot be updated
diff --git a/lib/chef/dsl/resources.rb b/lib/chef/dsl/resources.rb
index 7bbfeb2914..1401e3ed53 100644
--- a/lib/chef/dsl/resources.rb
+++ b/lib/chef/dsl/resources.rb
@@ -33,19 +33,17 @@ class Chef
include Chef::DSL::ChefProvisioning
def self.add_resource_dsl(dsl_name)
- begin
- module_eval(<<-EOM, __FILE__, __LINE__ + 1)
+ module_eval(<<-EOM, __FILE__, __LINE__ + 1)
def #{dsl_name}(*args, &block)
- Chef.log_deprecation("Cannot create resource #{dsl_name} with more than one argument. All arguments except the name (\#{args[0].inspect}) will be ignored. This will cause an error in Chef 13. Arguments: \#{args}") if args.size > 1
+ Chef.deprecated(:internal_api, "Cannot create resource #{dsl_name} with more than one argument. All arguments except the name (\#{args[0].inspect}) will be ignored. This will cause an error in Chef 13. Arguments: \#{args}") if args.size > 1
declare_resource(#{dsl_name.inspect}, args[0], caller[0], &block)
end
EOM
- rescue SyntaxError
- # Handle the case where dsl_name has spaces, etc.
- define_method(dsl_name.to_sym) do |*args, &block|
- Chef.log_deprecation("Cannot create resource #{dsl_name} with more than one argument. All arguments except the name (#{args[0].inspect}) will be ignored. This will cause an error in Chef 13. Arguments: #{args}") if args.size > 1
- declare_resource(dsl_name, args[0], caller[0], &block)
- end
+ rescue SyntaxError
+ # Handle the case where dsl_name has spaces, etc.
+ define_method(dsl_name.to_sym) do |*args, &block|
+ Chef.deprecated(:internal_api, "Cannot create resource #{dsl_name} with more than one argument. All arguments except the name (#{args[0].inspect}) will be ignored. This will cause an error in Chef 13. Arguments: #{args}") if args.size > 1
+ declare_resource(dsl_name, args[0], caller[0], &block)
end
end
diff --git a/lib/chef/encrypted_data_bag_item.rb b/lib/chef/encrypted_data_bag_item.rb
index e696199c63..c7c6145f61 100644
--- a/lib/chef/encrypted_data_bag_item.rb
+++ b/lib/chef/encrypted_data_bag_item.rb
@@ -121,8 +121,8 @@ class Chef::EncryptedDataBagItem
#
def self.load(data_bag, name, secret = nil)
raw_hash = Chef::DataBagItem.load(data_bag, name)
- secret = secret || self.load_secret
- self.new(raw_hash, secret)
+ secret ||= load_secret
+ new(raw_hash, secret)
end
def self.load_secret(path = nil)
diff --git a/lib/chef/encrypted_data_bag_item/decryptor.rb b/lib/chef/encrypted_data_bag_item/decryptor.rb
index 773ff4e154..f35611d185 100644
--- a/lib/chef/encrypted_data_bag_item/decryptor.rb
+++ b/lib/chef/encrypted_data_bag_item/decryptor.rb
@@ -93,7 +93,7 @@ class Chef::EncryptedDataBagItem
plaintext << openssl_decryptor.final
rescue OpenSSL::Cipher::CipherError => e
# if the key length is less than 255 characters, and it contains slashes, we think it may be a path.
- raise DecryptionFailure, "Error decrypting data bag value: '#{e.message}'. Most likely the provided key is incorrect. #{ (@key.length < 255 && @key.include?('/')) ? 'You may need to use --secret-file rather than --secret.' : '' }"
+ raise DecryptionFailure, "Error decrypting data bag value: '#{e.message}'. Most likely the provided key is incorrect. #{(@key.length < 255 && @key.include?('/')) ? 'You may need to use --secret-file rather than --secret.' : ''}"
end
end
@@ -144,7 +144,7 @@ class Chef::EncryptedDataBagItem
plaintext << openssl_decryptor.final
rescue OpenSSL::Cipher::CipherError => e
# if the key length is less than 255 characters, and it contains slashes, we think it may be a path.
- raise DecryptionFailure, "Error decrypting data bag value: '#{e.message}'. Most likely the provided key is incorrect. #{ ( @key.length < 255 && @key.include?('/')) ? 'You may need to use --secret-file rather than --secret.' : '' }"
+ raise DecryptionFailure, "Error decrypting data bag value: '#{e.message}'. Most likely the provided key is incorrect. #{( @key.length < 255 && @key.include?('/')) ? 'You may need to use --secret-file rather than --secret.' : ''}"
end
end
diff --git a/lib/chef/environment.rb b/lib/chef/environment.rb
index 32ebde6f4f..545a2e51eb 100644
--- a/lib/chef/environment.rb
+++ b/lib/chef/environment.rb
@@ -171,7 +171,7 @@ class Chef
unless params[:cookbook_version].nil?
params[:cookbook_version].each do |index, cookbook_constraint_spec|
unless cookbook_constraint_spec.nil? || cookbook_constraint_spec.size == 0
- valid = valid && update_cookbook_constraint_from_param(index, cookbook_constraint_spec)
+ valid &&= update_cookbook_constraint_from_param(index, cookbook_constraint_spec)
end
end
end
@@ -217,7 +217,7 @@ class Chef
end
def self.json_create(o)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::Environment#from_hash")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::Environment#from_hash")
from_hash(o)
end
@@ -247,7 +247,7 @@ class Chef
if Chef::Config[:solo_legacy_mode]
load_from_file(name)
else
- self.from_hash(chef_server_rest.get("environments/#{name}"))
+ from_hash(chef_server_rest.get("environments/#{name}"))
end
end
@@ -309,17 +309,15 @@ class Chef
end
def self.validate_cookbook_version(version)
- begin
- if Chef::Config[:solo_legacy_mode]
- raise Chef::Exceptions::IllegalVersionConstraint,
- "Environment cookbook version constraints not allowed in chef-solo"
- else
- Chef::VersionConstraint.new version
- true
- end
- rescue ArgumentError
- false
+ if Chef::Config[:solo_legacy_mode]
+ raise Chef::Exceptions::IllegalVersionConstraint,
+ "Environment cookbook version constraints not allowed in chef-solo"
+ else
+ Chef::VersionConstraint.new version
+ true
end
+ rescue ArgumentError
+ false
end
end
diff --git a/lib/chef/event_loggers/windows_eventlog.rb b/lib/chef/event_loggers/windows_eventlog.rb
index f8c3d346c5..1ff87945e7 100644
--- a/lib/chef/event_loggers/windows_eventlog.rb
+++ b/lib/chef/event_loggers/windows_eventlog.rb
@@ -38,7 +38,7 @@ class Chef
SOURCE = "Chef"
def self.available?
- return Chef::Platform.windows?
+ Chef::Platform.windows?
end
def initialize
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index 7126323ff7..ae62f42b09 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -76,10 +76,10 @@ class Chef
class Group < RuntimeError; end
class Link < RuntimeError; end
class Mount < RuntimeError; end
- class Reboot < Exception; end
- class RebootPending < Exception; end
+ class Reboot < Exception; end # rubocop:disable Lint/InheritException
+ class RebootPending < Exception; end # rubocop:disable Lint/InheritException
class RebootFailed < Mixlib::ShellOut::ShellCommandFailed; end
- class ClientUpgraded < Exception; end
+ class ClientUpgraded < Exception; end # rubocop:disable Lint/InheritException
class PrivateKeyMissing < RuntimeError; end
class CannotWritePrivateKey < RuntimeError; end
class RoleNotFound < RuntimeError; end
@@ -159,7 +159,7 @@ class Chef
# Thrown when Win32 API layer binds to non-existent Win32 function. Occurs
# when older versions of Windows don't support newer Win32 API functions.
- class Win32APIFunctionNotImplemented < NotImplementedError; end
+ class Win32APIFunctionNotImplemented < NotImplementedError; end # rubocop:disable Lint/InheritException
# Attempting to run windows code on a not-windows node
class Win32NotWindows < RuntimeError; end
class WindowsNotAdmin < RuntimeError; end
@@ -196,7 +196,7 @@ class Chef
class InvalidVersionConstraint < ArgumentError; end
# Version constraints are not allowed in chef-solo
- class IllegalVersionConstraint < NotImplementedError; end
+ class IllegalVersionConstraint < NotImplementedError; end # rubocop:disable Lint/InheritException
class MetadataNotValid < StandardError; end
class MetadataNotFound < StandardError
@@ -262,7 +262,7 @@ class Chef
class ChildConvergeError < RuntimeError; end
- class DeprecatedFeatureError < RuntimeError;
+ class DeprecatedFeatureError < RuntimeError
def initalize(message)
super("#{message} (raising error due to treat_deprecation_warnings_as_errors being set)")
end
@@ -315,7 +315,7 @@ class Chef
def raise!
unless empty?
- raise self.for_raise
+ raise for_raise
end
end
@@ -525,5 +525,8 @@ This error is most often caused by network issues (proxies, etc) outside of chef
super "Found multiple matching resources. #{matches_info.join("\n")}"
end
end
+
+ # exception specific to invalid usage of 'dsc_resource' resource
+ class DSCModuleNameMissing < ArgumentError; end
end
end
diff --git a/lib/chef/file_access_control/unix.rb b/lib/chef/file_access_control/unix.rb
index 1746db44d3..66f724ddd8 100644
--- a/lib/chef/file_access_control/unix.rb
+++ b/lib/chef/file_access_control/unix.rb
@@ -80,19 +80,19 @@ class Chef
if target_uid.nil?
# the user has not specified a permission on the new resource, so we never manage it with FAC
Chef::Log.debug("Found target_uid == nil, so no owner was specified on resource, not managing owner")
- return false
+ false
elsif current_uid.nil?
# the user has specified a permission, and we are creating a file, so always enforce permissions
Chef::Log.debug("Found current_uid == nil, so we are creating a new file, updating owner")
- return true
+ true
elsif target_uid != current_uid
# the user has specified a permission, and it does not match the file, so fix the permission
Chef::Log.debug("Found target_uid != current_uid, updating owner")
- return true
+ true
else
Chef::Log.debug("Found target_uid == current_uid, not updating owner")
# the user has specified a permission, but it matches the file, so behave idempotently
- return false
+ false
end
end
@@ -117,13 +117,13 @@ class Chef
end
def gid_from_resource(resource)
- return nil if resource == nil || resource.group.nil?
+ return nil if resource.nil? || resource.group.nil?
if resource.group.kind_of?(String)
diminished_radix_complement( Etc.getgrnam(resource.group).gid )
elsif resource.group.kind_of?(Integer)
resource.group
else
- Chef::Log.error("The `group` parameter of the #@resource resource is set to an invalid value (#{resource.owner.inspect})")
+ Chef::Log.error("The `group` parameter of the #{@resource} resource is set to an invalid value (#{resource.owner.inspect})")
raise ArgumentError, "cannot resolve #{resource.group.inspect} to gid, group must be a string or integer"
end
rescue ArgumentError
@@ -139,19 +139,19 @@ class Chef
if target_gid.nil?
# the user has not specified a permission on the new resource, so we never manage it with FAC
Chef::Log.debug("Found target_gid == nil, so no group was specified on resource, not managing group")
- return false
+ false
elsif current_gid.nil?
# the user has specified a permission, and we are creating a file, so always enforce permissions
Chef::Log.debug("Found current_gid == nil, so we are creating a new file, updating group")
- return true
+ true
elsif target_gid != current_gid
# the user has specified a permission, and it does not match the file, so fix the permission
Chef::Log.debug("Found target_gid != current_gid, updating group")
- return true
+ true
else
Chef::Log.debug("Found target_gid == current_gid, not updating group")
# the user has specified a permission, but it matches the file, so behave idempotently
- return false
+ false
end
end
@@ -168,7 +168,7 @@ class Chef
end
def mode_from_resource(res)
- return nil if res == nil || res.mode.nil?
+ return nil if res.nil? || res.mode.nil?
(res.mode.respond_to?(:oct) ? res.mode.oct : res.mode.to_i) & 007777
end
@@ -188,21 +188,21 @@ class Chef
if target_mode.nil?
# the user has not specified a permission on the new resource, so we never manage it with FAC
Chef::Log.debug("Found target_mode == nil, so no mode was specified on resource, not managing mode")
- return false
+ false
elsif current_mode.nil?
# the user has specified a permission, and we are creating a file, so always enforce permissions
Chef::Log.debug("Found current_mode == nil, so we are creating a new file, updating mode")
- return true
+ true
elsif target_mode != current_mode
# the user has specified a permission, and it does not match the file, so fix the permission
Chef::Log.debug("Found target_mode != current_mode, updating mode")
- return true
+ true
elsif suid_bit_set? && (should_update_group? || should_update_owner?)
- return true
+ true
else
Chef::Log.debug("Found target_mode == current_mode, not updating mode")
# the user has specified a permission, but it matches the file, so behave idempotently
- return false
+ false
end
end
@@ -264,13 +264,13 @@ class Chef
end
def uid_from_resource(resource)
- return nil if resource == nil || resource.owner.nil?
+ return nil if resource.nil? || resource.owner.nil?
if resource.owner.kind_of?(String)
diminished_radix_complement( Etc.getpwnam(resource.owner).uid )
elsif resource.owner.kind_of?(Integer)
resource.owner
else
- Chef::Log.error("The `owner` parameter of the #@resource resource is set to an invalid value (#{resource.owner.inspect})")
+ Chef::Log.error("The `owner` parameter of the #{@resource} resource is set to an invalid value (#{resource.owner.inspect})")
raise ArgumentError, "cannot resolve #{resource.owner.inspect} to uid, owner must be a string or integer"
end
rescue ArgumentError
@@ -283,7 +283,7 @@ class Chef
end
def suid_bit_set?
- return target_mode & 04000 > 0
+ target_mode & 04000 > 0
end
end
end
diff --git a/lib/chef/file_access_control/windows.rb b/lib/chef/file_access_control/windows.rb
index 6f1ac5f581..2c6b69c257 100644
--- a/lib/chef/file_access_control/windows.rb
+++ b/lib/chef/file_access_control/windows.rb
@@ -100,7 +100,7 @@ class Chef
new_target_acl << children_ace
end
end
- return actual_acl == new_target_acl
+ actual_acl == new_target_acl
end
def existing_descriptor
diff --git a/lib/chef/formatters/base.rb b/lib/chef/formatters/base.rb
index 536bf72e02..2fbe00862c 100644
--- a/lib/chef/formatters/base.rb
+++ b/lib/chef/formatters/base.rb
@@ -213,7 +213,17 @@ class Chef
end
def deprecation(message, location = caller(2..2)[0])
- Chef::Log.deprecation("#{message} at #{location}")
+ out = if is_structured_deprecation?(message)
+ message.inspect
+ else
+ "#{message} at #{location}"
+ end
+
+ Chef::Log.deprecation(out)
+ end
+
+ def is_structured_deprecation?(deprecation)
+ deprecation.kind_of?(Chef::Deprecated::Base)
end
def is_formatter?
diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb
index 7dbbf1d948..0c51cc2cfb 100644
--- a/lib/chef/formatters/doc.rb
+++ b/lib/chef/formatters/doc.rb
@@ -61,9 +61,10 @@ class Chef
if !deprecations.empty?
puts_line ""
puts_line "Deprecated features used!"
- deprecations.each do |message, locations|
+ deprecations.each do |message, details|
+ locations = details[:locations]
if locations.size == 1
- puts_line " #{message} at #{locations.size} location:"
+ puts_line " #{message} at 1 location:"
else
puts_line " #{message} at #{locations.size} locations:"
end
@@ -74,6 +75,9 @@ class Chef
prefix = " "
end
end
+ unless details[:url].nil?
+ puts_line " See #{details[:url]} for further details."
+ end
end
puts_line ""
end
@@ -416,8 +420,13 @@ class Chef
end
# Save deprecations to the screen until the end
- deprecations[message] ||= Set.new
- deprecations[message] << location
+ if is_structured_deprecation?(message)
+ url = message.url
+ message = message.message
+ end
+
+ deprecations[message] ||= { url: url, locations: Set.new }
+ deprecations[message][:locations] << location
end
def indent
diff --git a/lib/chef/formatters/error_description.rb b/lib/chef/formatters/error_description.rb
index 8d7f940181..ece33bdd49 100644
--- a/lib/chef/formatters/error_description.rb
+++ b/lib/chef/formatters/error_description.rb
@@ -48,7 +48,7 @@ class Chef
display_section("Platform:", RUBY_PLATFORM, out)
end
- def for_json()
+ def for_json
{
"title" => @title,
"sections" => @sections,
diff --git a/lib/chef/formatters/error_inspectors/api_error_formatting.rb b/lib/chef/formatters/error_inspectors/api_error_formatting.rb
index 2415d0f4bb..53549ee77c 100644
--- a/lib/chef/formatters/error_inspectors/api_error_formatting.rb
+++ b/lib/chef/formatters/error_inspectors/api_error_formatting.rb
@@ -172,11 +172,10 @@ E
# .../lib/ruby/1.9.1/net/http.rb:2709:in `read_body'
# .../lib/ruby/1.9.1/net/http.rb:2736:in `body'
# .../lib/chef/formatters/error_inspectors/api_error_formatting.rb:91:in `rescue in format_rest_error'
- begin
- exception.response.body
- rescue Exception
- "Cannot fetch the contents of the response."
- end
+
+ exception.response.body
+ rescue Exception
+ "Cannot fetch the contents of the response."
end
end
diff --git a/lib/chef/formatters/error_mapper.rb b/lib/chef/formatters/error_mapper.rb
index 4786a20465..eb89662308 100644
--- a/lib/chef/formatters/error_mapper.rb
+++ b/lib/chef/formatters/error_mapper.rb
@@ -30,7 +30,7 @@ class Chef
headline = "Chef encountered an error attempting to create the client \"#{node_name}\""
description = ErrorDescription.new(headline)
error_inspector.add_explanation(description)
- return description
+ description
end
def self.node_load_failed(node_name, exception, config)
@@ -38,7 +38,7 @@ class Chef
headline = "Chef encountered an error attempting to load the node data for \"#{node_name}\""
description = ErrorDescription.new(headline)
error_inspector.add_explanation(description)
- return description
+ description
end
def self.run_list_expand_failed(node, exception)
@@ -46,7 +46,7 @@ class Chef
headline = "Error expanding the run_list:"
description = ErrorDescription.new(headline)
error_inspector.add_explanation(description)
- return description
+ description
end
def self.cookbook_resolution_failed(expanded_run_list, exception)
@@ -54,7 +54,7 @@ class Chef
headline = "Error Resolving Cookbooks for Run List:"
description = ErrorDescription.new(headline)
error_inspector.add_explanation(description)
- return description
+ description
end
def self.cookbook_sync_failed(cookbooks, exception)
@@ -62,7 +62,7 @@ class Chef
headline = "Error Syncing Cookbooks:"
description = ErrorDescription.new(headline)
error_inspector.add_explanation(description)
- return description
+ description
end
def self.resource_failed(resource, action, exception)
@@ -70,7 +70,7 @@ class Chef
headline = "Error executing action `#{action}` on resource '#{resource}'"
description = ErrorDescription.new(headline)
error_inspector.add_explanation(description)
- return description
+ description
end
def self.file_load_failed(path, exception)
diff --git a/lib/chef/http/api_versions.rb b/lib/chef/http/api_versions.rb
new file mode 100644
index 0000000000..e164da262d
--- /dev/null
+++ b/lib/chef/http/api_versions.rb
@@ -0,0 +1,50 @@
+#--
+# 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 "chef/server_api_versions"
+
+class Chef
+ class HTTP
+ # An HTTP middleware to retrieve and store the Chef Server's minimum
+ # and maximum supported API versions.
+ class APIVersions
+
+ def initialize(options = {})
+ end
+
+ def handle_request(method, url, headers = {}, data = false)
+ [method, url, headers, data]
+ end
+
+ def handle_response(http_response, rest_request, return_value)
+ if http_response.key?("x-ops-server-api-version")
+ ServerAPIVersions.instance.set_versions(http_response["x-ops-server-api-version"])
+ end
+ [http_response, rest_request, return_value]
+ end
+
+ def stream_response_handler(response)
+ nil
+ end
+
+ def handle_stream_complete(http_response, rest_request, return_value)
+ [http_response, rest_request, return_value]
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/http/basic_client.rb b/lib/chef/http/basic_client.rb
index 460744ea2a..9a000136e6 100644
--- a/lib/chef/http/basic_client.rb
+++ b/lib/chef/http/basic_client.rb
@@ -111,7 +111,7 @@ class Chef
# match no_proxy with a fuzzy matcher, rather than letting Net::HTTP
# do it.
http_client = http_client_builder.new(host, port, nil)
- http_client.proxy_port = nil if http_client.proxy_address == nil
+ http_client.proxy_port = nil if http_client.proxy_address.nil?
if url.scheme == HTTPS
configure_ssl(http_client)
diff --git a/lib/chef/http/json_input.rb b/lib/chef/http/json_input.rb
index 4cc1aa2e10..7cf2e4012f 100644
--- a/lib/chef/http/json_input.rb
+++ b/lib/chef/http/json_input.rb
@@ -33,7 +33,7 @@ class Chef
def handle_request(method, url, headers = {}, data = false)
if data && should_encode_as_json?(headers)
- headers.delete_if { |key, _value| key.casecmp("content-type").zero? }
+ headers.delete_if { |key, _value| key.casecmp("content-type") == 0 }
headers["Content-Type"] = "application/json"
json_opts = {}
json_opts[:validate_utf8] = opts[:validate_utf8] if opts.has_key?(:validate_utf8)
@@ -64,7 +64,7 @@ class Chef
# ruby/Net::HTTP don't enforce capitalized headers (it normalizes them
# for you before sending the request), so we have to account for all
# the variations we might find
- requested_content_type = headers.find { |k, v| k.casecmp("content-type").zero? }
+ requested_content_type = headers.find { |k, v| k.casecmp("content-type") == 0 }
requested_content_type.nil? || requested_content_type.last.include?("json")
end
diff --git a/lib/chef/http/validate_content_length.rb b/lib/chef/http/validate_content_length.rb
index c1073867d3..3a8d3bda2b 100644
--- a/lib/chef/http/validate_content_length.rb
+++ b/lib/chef/http/validate_content_length.rb
@@ -50,7 +50,7 @@ class Chef
def handle_response(http_response, rest_request, return_value)
validate(http_response, http_response.body.bytesize) if http_response && http_response.body
- return [http_response, rest_request, return_value]
+ [http_response, rest_request, return_value]
end
def handle_stream_complete(http_response, rest_request, return_value)
@@ -63,7 +63,7 @@ class Chef
# Make sure the counter is reset since this object might get used
# again. See CHEF-5100
@content_length_counter = nil
- return [http_response, rest_request, return_value]
+ [http_response, rest_request, return_value]
end
def stream_response_handler(response)
diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb
index f8f05a0074..c8f5496345 100644
--- a/lib/chef/json_compat.rb
+++ b/lib/chef/json_compat.rb
@@ -47,11 +47,9 @@ class Chef
# API to use to avoid create_addtions
def parse(source, opts = {})
- begin
- FFI_Yajl::Parser.parse(source, opts)
- rescue FFI_Yajl::ParseError => e
- raise Chef::Exceptions::JSON::ParseError, e.message
- end
+ FFI_Yajl::Parser.parse(source, opts)
+ rescue FFI_Yajl::ParseError => e
+ raise Chef::Exceptions::JSON::ParseError, e.message
end
# Just call the JSON gem's parse method with a modified :max_nesting field
@@ -102,11 +100,9 @@ class Chef
end
def to_json(obj, opts = nil)
- begin
- FFI_Yajl::Encoder.encode(obj, opts)
- rescue FFI_Yajl::EncodeError => e
- raise Chef::Exceptions::JSON::EncodeError, e.message
- end
+ FFI_Yajl::Encoder.encode(obj, opts)
+ rescue FFI_Yajl::EncodeError => e
+ raise Chef::Exceptions::JSON::EncodeError, e.message
end
def to_json_pretty(obj, opts = nil)
diff --git a/lib/chef/key.rb b/lib/chef/key.rb
index 38822e8b26..c68fe1039c 100644
--- a/lib/chef/key.rb
+++ b/lib/chef/key.rb
@@ -155,7 +155,7 @@ class Chef
result = chef_rest.post("#{api_base}/#{@actor}/keys", payload)
# append the private key to the current key if the server returned one,
# since the POST endpoint just returns uri and private_key if needed.
- new_key = self.to_hash
+ new_key = to_hash
new_key["private_key"] = result["private_key"] if result["private_key"]
Chef::Key.from_hash(new_key)
end
@@ -178,9 +178,9 @@ class Chef
new_key = chef_rest.put("#{api_base}/#{@actor}/keys/#{put_name}", to_hash)
# if the server returned a public_key, remove the create_key field, as we now have a key
if new_key["public_key"]
- self.delete_create_key
+ delete_create_key
end
- Chef::Key.from_hash(self.to_hash.merge(new_key))
+ Chef::Key.from_hash(to_hash.merge(new_key))
end
def save
@@ -223,18 +223,18 @@ class Chef
end
def json_create(json)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::Key#from_json or one of the load_by methods.")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::Key#from_json or one of the load_by methods.")
Chef::Key.from_json(json)
end
def list_by_user(actor, inflate = false)
keys = Chef::ServerAPI.new(Chef::Config[:chef_server_root]).get("users/#{actor}/keys")
- self.list(keys, actor, :load_by_user, inflate)
+ list(keys, actor, :load_by_user, inflate)
end
def list_by_client(actor, inflate = false)
keys = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("clients/#{actor}/keys")
- self.list(keys, actor, :load_by_client, inflate)
+ list(keys, actor, :load_by_client, inflate)
end
def load_by_user(actor, key_name)
diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb
index 8d40e06a43..47ce85b9e3 100644
--- a/lib/chef/knife.rb
+++ b/lib/chef/knife.rb
@@ -145,7 +145,7 @@ class Chef
end
def self.subcommand_class_from(args)
- if args.size == 1 && args[0].strip.casecmp("rehash").zero?
+ if args.size == 1 && args[0].strip.casecmp("rehash") == 0
# To prevent issues with the rehash file not pointing to the correct plugins,
# we always use the glob loader when regenerating the rehash file
@subcommand_loader = Chef::Knife::SubcommandLoader.gem_glob_loader(chef_config_dir)
@@ -430,11 +430,11 @@ class Chef
end
def show_usage
- stdout.puts("USAGE: " + self.opt_parser.to_s)
+ stdout.puts("USAGE: " + opt_parser.to_s)
end
def run_with_pretty_exceptions(raise_exception = false)
- unless self.respond_to?(:run)
+ unless respond_to?(:run)
ui.error "You need to add a #run method to your knife command before you can use it"
end
enforce_path_sanity
@@ -553,7 +553,7 @@ class Chef
pretty_name ||= output
- self.msg("Created #{pretty_name}")
+ msg("Created #{pretty_name}")
output(output) if config[:print_after]
end
@@ -572,7 +572,7 @@ class Chef
output(format_for_display(object)) if config[:print_after]
obj_name = delete_name ? "#{delete_name}[#{name}]" : object
- self.msg("Deleted #{obj_name}")
+ msg("Deleted #{obj_name}")
end
# helper method for testing if a field exists
diff --git a/lib/chef/knife/client_delete.rb b/lib/chef/knife/client_delete.rb
index 08cdf6c7dd..38da5c2a73 100644
--- a/lib/chef/knife/client_delete.rb
+++ b/lib/chef/knife/client_delete.rb
@@ -32,29 +32,32 @@ class Chef
:long => "--delete-validators",
:description => "Force deletion of client if it's a validator"
- banner "knife client delete CLIENT (options)"
+ banner "knife client delete [CLIENT[,CLIENT]] (options)"
def run
- @client_name = @name_args[0]
-
- if @client_name.nil?
+ if @name_args.length == 0
show_usage
- ui.fatal("You must specify a client name")
+ ui.fatal("You must specify at least one client name")
exit 1
end
- delete_object(Chef::ApiClientV1, @client_name, "client") do
- object = Chef::ApiClientV1.load(@client_name)
+ @name_args.each do |client_name|
+ delete_client(client_name)
+ end
+ end
+
+ def delete_client(client_name)
+ delete_object(Chef::ApiClientV1, client_name, "client") do
+ object = Chef::ApiClientV1.load(client_name)
if object.validator
unless config[:delete_validators]
- ui.fatal("You must specify --delete-validators to delete the validator client #{@client_name}")
+ ui.fatal("You must specify --delete-validators to delete the validator client #{client_name}")
exit 2
end
end
object.destroy
end
end
-
end
end
end
diff --git a/lib/chef/knife/configure.rb b/lib/chef/knife/configure.rb
index e726e32684..48007bbee7 100644
--- a/lib/chef/knife/configure.rb
+++ b/lib/chef/knife/configure.rb
@@ -133,7 +133,7 @@ EOH
def ask_user_for_config
server_name = guess_servername
- @chef_server = config[:chef_server_url] || ask_question("Please enter the chef server URL: ", :default => "https://#{server_name}:443")
+ @chef_server = config[:chef_server_url] || ask_question("Please enter the chef server URL: ", :default => "https://#{server_name}/organizations/myorg")
if config[:initial]
@new_client_name = config[:node_name] || ask_question("Please enter a name for the new user: ", :default => Etc.getlogin)
@admin_client_name = config[:admin_client_name] || ask_question("Please enter the existing admin name: ", :default => "admin")
diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb
index 43d015dcc4..72fb426554 100644
--- a/lib/chef/knife/cookbook_site_install.rb
+++ b/lib/chef/knife/cookbook_site_install.rb
@@ -83,7 +83,7 @@ class Chef
# Check to ensure we have a valid source of cookbooks before continuing
#
@install_path = File.expand_path(Array(config[:cookbook_path]).first)
- ui.info "Installing #@cookbook_name to #{@install_path}"
+ ui.info "Installing #{@cookbook_name} to #{@install_path}"
@repo = CookbookSCMRepo.new(@install_path, ui, config)
#cookbook_path = File.join(vendor_path, name_args[0])
@@ -161,9 +161,9 @@ class Chef
def convert_path(upstream_file)
# converts a Windows path (C:\foo) to a mingw path (/c/foo)
if ENV["MSYSTEM"] == "MINGW32"
- return upstream_file.sub(/^([[:alpha:]]):/, '/\1')
+ upstream_file.sub(/^([[:alpha:]]):/, '/\1')
else
- return Shellwords.escape upstream_file
+ Shellwords.escape upstream_file
end
end
diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb
index b2670f196b..ceb067d48d 100644
--- a/lib/chef/knife/core/bootstrap_context.rb
+++ b/lib/chef/knife/core/bootstrap_context.rb
@@ -67,12 +67,36 @@ class Chef
@trusted_certs ||= trusted_certs_content
end
+ def get_log_location
+ if !(@chef_config[:config_log_location].class == IO ) && (@chef_config[:config_log_location].nil? || @chef_config[:config_log_location].to_s.empty?)
+ "STDOUT"
+ elsif @chef_config[:config_log_location].equal?(:win_evt)
+ raise "The value :win_evt is not supported for config_log_location on Linux Platforms \n"
+ elsif @chef_config[:config_log_location].equal?(:syslog)
+ ":syslog"
+ elsif @chef_config[:config_log_location].equal?(STDOUT)
+ "STDOUT"
+ elsif @chef_config[:config_log_location].equal?(STDERR)
+ "STDERR"
+ elsif @chef_config[:config_log_location]
+ %Q{"#{@chef_config[:config_log_location]}"}
+ else
+ "STDOUT"
+ end
+ end
+
def config_content
client_rb = <<-CONFIG
-log_location STDOUT
chef_server_url "#{@chef_config[:chef_server_url]}"
validation_client_name "#{@chef_config[:validation_client_name]}"
CONFIG
+
+ if !(@chef_config[:config_log_level].nil? || @chef_config[:config_log_level].empty?)
+ client_rb << %Q{log_level :#{@chef_config[:config_log_level]}\n}
+ end
+
+ client_rb << "log_location #{get_log_location}\n"
+
if @config[:chef_node_name]
client_rb << %Q{node_name "#{@config[:chef_node_name]}"\n}
else
diff --git a/lib/chef/knife/core/cookbook_scm_repo.rb b/lib/chef/knife/core/cookbook_scm_repo.rb
index e909066b02..38f432e5bb 100644
--- a/lib/chef/knife/core/cookbook_scm_repo.rb
+++ b/lib/chef/knife/core/cookbook_scm_repo.rb
@@ -122,7 +122,7 @@ class Chef
git("branch --no-color").stdout.lines.any? { |l| l =~ /\s#{Regexp.escape(branch_name)}(?:\s|$)/ }
end
- def get_current_branch()
+ def get_current_branch
ref = git("symbolic-ref HEAD").stdout
ref.chomp.split("/")[2]
end
@@ -131,9 +131,9 @@ class Chef
def git_repo?(directory)
if File.directory?(File.join(directory, ".git"))
- return true
+ true
elsif File.dirname(directory) == directory
- return false
+ false
else
git_repo?(File.dirname(directory))
end
diff --git a/lib/chef/knife/core/gem_glob_loader.rb b/lib/chef/knife/core/gem_glob_loader.rb
index 34c5c53d75..c4523d69ad 100644
--- a/lib/chef/knife/core/gem_glob_loader.rb
+++ b/lib/chef/knife/core/gem_glob_loader.rb
@@ -98,7 +98,7 @@ class Chef
files.concat gem_files
files.uniq! if check_load_path
- return files
+ files
end
def latest_gem_specs
diff --git a/lib/chef/knife/core/status_presenter.rb b/lib/chef/knife/core/status_presenter.rb
index 68c1acf4f1..df6c2fe942 100644
--- a/lib/chef/knife/core/status_presenter.rb
+++ b/lib/chef/knife/core/status_presenter.rb
@@ -148,7 +148,7 @@ class Chef
difference = difference % 3600
minutes = (difference / 60).to_i
seconds = (difference % 60)
- return [hours, minutes, seconds]
+ [hours, minutes, seconds]
end
end
diff --git a/lib/chef/knife/core/subcommand_loader.rb b/lib/chef/knife/core/subcommand_loader.rb
index e617b39ded..30a438b780 100644
--- a/lib/chef/knife/core/subcommand_loader.rb
+++ b/lib/chef/knife/core/subcommand_loader.rb
@@ -51,7 +51,7 @@ class Chef
Chef::Log.debug("Using autogenerated hashed command manifest #{plugin_manifest_path}")
Knife::SubcommandLoader::HashedCommandLoader.new(chef_config_dir, plugin_manifest)
elsif custom_manifest?
- Chef.log_deprecation("Using custom manifest #{plugin_manifest_path} is deprecated. Please use a `knife rehash` autogenerated manifest instead.")
+ 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)
@@ -90,7 +90,7 @@ class Chef
# Deprecated and un-used instance variable.
@env = env
unless env.nil?
- Chef.log_deprecation("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.")
+ 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
@@ -154,7 +154,7 @@ class Chef
# to get in the past.
#
def subcommand_files
- Chef.log_deprecation "Using Chef::Knife::SubcommandLoader directly is deprecated.
+ 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
diff --git a/lib/chef/knife/core/ui.rb b/lib/chef/knife/core/ui.rb
index 67e431f1a7..1fc6d3d0e2 100644
--- a/lib/chef/knife/core/ui.rb
+++ b/lib/chef/knife/core/ui.rb
@@ -65,22 +65,18 @@ class Chef
# Prints a message to stdout. Aliased as +info+ for compatibility with
# the logger API.
def msg(message)
- begin
- stdout.puts message
- rescue Errno::EPIPE => e
- raise e if @config[:verbosity] >= 2
- exit 0
- end
+ stdout.puts message
+ rescue Errno::EPIPE => e
+ raise e if @config[:verbosity] >= 2
+ exit 0
end
# Prints a msg to stderr. Used for info, warn, error, and fatal.
def log(message)
- begin
- stderr.puts message
- rescue Errno::EPIPE => e
- raise e if @config[:verbosity] >= 2
- exit 0
- end
+ stderr.puts message
+ rescue Errno::EPIPE => e
+ raise e if @config[:verbosity] >= 2
+ exit 0
end
alias :info :log
@@ -138,7 +134,7 @@ class Chef
end
def ask_question(question, opts = {})
- question = question + "[#{opts[:default]}] " if opts[:default]
+ question += "[#{opts[:default]}] " if opts[:default]
if opts[:default] && config[:defaults]
opts[:default]
@@ -155,12 +151,10 @@ class Chef
end
def pretty_print(data)
- begin
- stdout.puts data
- rescue Errno::EPIPE => e
- raise e if @config[:verbosity] >= 2
- exit 0
- end
+ stdout.puts data
+ rescue Errno::EPIPE => e
+ raise e if @config[:verbosity] >= 2
+ exit 0
end
# Hash -> Hash
@@ -186,7 +180,7 @@ class Chef
if parse_output
if object_class.nil?
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please pass in the class to inflate or use #edit_hash")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please pass in the class to inflate or use #edit_hash")
Chef::JSONCompat.from_json(output)
else
object_class.from_hash(Chef::JSONCompat.parse(output))
@@ -215,9 +209,9 @@ class Chef
output_parsed_again = Chef::JSONCompat.parse(Chef::JSONCompat.to_json(output))
if object_parsed_again != output_parsed_again
output.save
- self.msg("Saved #{output}")
+ msg("Saved #{output}")
else
- self.msg("Object unchanged, not saving")
+ msg("Object unchanged, not saving")
end
output(format_for_display(object)) if config[:print_after]
end
@@ -247,19 +241,19 @@ class Chef
when "Y", "y"
true
when "N", "n"
- self.msg("You said no, so I'm done here.")
+ msg("You said no, so I'm done here.")
false
when ""
unless default_choice.nil?
default_choice
else
- self.msg("I have no idea what to do with '#{answer}'")
- self.msg("Just say Y or N, please.")
+ msg("I have no idea what to do with '#{answer}'")
+ msg("Just say Y or N, please.")
confirm_without_exit(question, append_instructions, default_choice)
end
else
- self.msg("I have no idea what to do with '#{answer}'")
- self.msg("Just say Y or N, please.")
+ msg("I have no idea what to do with '#{answer}'")
+ msg("Just say Y or N, please.")
confirm_without_exit(question, append_instructions, default_choice)
end
end
diff --git a/lib/chef/knife/data_bag_secret_options.rb b/lib/chef/knife/data_bag_secret_options.rb
index b426cd442c..4246c9edfa 100644
--- a/lib/chef/knife/data_bag_secret_options.rb
+++ b/lib/chef/knife/data_bag_secret_options.rb
@@ -114,7 +114,7 @@ class Chef
# Certain situations (show and bootstrap) don't need a --encrypt flag to use the config file secret
return true
end
- return false
+ false
end
def has_cl_secret?
diff --git a/lib/chef/knife/deps.rb b/lib/chef/knife/deps.rb
index e773f65106..b5c6d6379a 100644
--- a/lib/chef/knife/deps.rb
+++ b/lib/chef/knife/deps.rb
@@ -72,49 +72,47 @@ class Chef
end
def get_dependencies(entry)
- begin
- if entry.parent && entry.parent.path == "/cookbooks"
- return entry.chef_object.metadata.dependencies.keys.map { |cookbook| "/cookbooks/#{cookbook}" }
+ if entry.parent && entry.parent.path == "/cookbooks"
+ return entry.chef_object.metadata.dependencies.keys.map { |cookbook| "/cookbooks/#{cookbook}" }
- elsif entry.parent && entry.parent.path == "/nodes"
- node = Chef::JSONCompat.parse(entry.read)
- result = []
- if node["chef_environment"] && node["chef_environment"] != "_default"
- result << "/environments/#{node['chef_environment']}.json"
- end
- if node["run_list"]
- result += dependencies_from_runlist(node["run_list"])
- end
- result
+ elsif entry.parent && entry.parent.path == "/nodes"
+ node = Chef::JSONCompat.parse(entry.read)
+ result = []
+ if node["chef_environment"] && node["chef_environment"] != "_default"
+ result << "/environments/#{node['chef_environment']}.json"
+ end
+ if node["run_list"]
+ result += dependencies_from_runlist(node["run_list"])
+ end
+ result
- elsif entry.parent && entry.parent.path == "/roles"
- role = Chef::JSONCompat.parse(entry.read)
- result = []
- if role["run_list"]
- dependencies_from_runlist(role["run_list"]).each do |dependency|
- result << dependency if !result.include?(dependency)
- end
+ elsif entry.parent && entry.parent.path == "/roles"
+ role = Chef::JSONCompat.parse(entry.read)
+ result = []
+ if role["run_list"]
+ dependencies_from_runlist(role["run_list"]).each do |dependency|
+ result << dependency if !result.include?(dependency)
end
- if role["env_run_lists"]
- role["env_run_lists"].each_pair do |env, run_list|
- dependencies_from_runlist(run_list).each do |dependency|
- result << dependency if !result.include?(dependency)
- end
+ end
+ if role["env_run_lists"]
+ role["env_run_lists"].each_pair do |env, run_list|
+ dependencies_from_runlist(run_list).each do |dependency|
+ result << dependency if !result.include?(dependency)
end
end
- result
+ end
+ result
- elsif !entry.exists?
- raise Chef::ChefFS::FileSystem::NotFoundError.new(entry)
+ elsif !entry.exists?
+ raise Chef::ChefFS::FileSystem::NotFoundError.new(entry)
- else
- []
- end
- rescue Chef::ChefFS::FileSystem::NotFoundError => e
- ui.error "#{format_path(e.entry)}: No such file or directory"
- self.exit_code = 2
+ else
[]
end
+ rescue Chef::ChefFS::FileSystem::NotFoundError => e
+ ui.error "#{format_path(e.entry)}: No such file or directory"
+ self.exit_code = 2
+ []
end
def dependencies_from_runlist(run_list)
diff --git a/lib/chef/knife/help.rb b/lib/chef/knife/help.rb
index e45b54eec8..075bf4b310 100644
--- a/lib/chef/knife/help.rb
+++ b/lib/chef/knife/help.rb
@@ -90,7 +90,7 @@ MOAR_HELP
def find_manpage_path(topic)
if ::File.exists?(::File.expand_path("../distro/common/man/man1/#{topic}.1", CHEF_ROOT))
# If we've provided the man page in the gem, give that
- return ::File.expand_path("../distro/common/man/man1/#{topic}.1", CHEF_ROOT)
+ ::File.expand_path("../distro/common/man/man1/#{topic}.1", CHEF_ROOT)
else
# Otherwise, we'll just be using MANPATH
topic
diff --git a/lib/chef/knife/list.rb b/lib/chef/knife/list.rb
index fcfde0eb45..6f314eb86d 100644
--- a/lib/chef/knife/list.rb
+++ b/lib/chef/knife/list.rb
@@ -97,7 +97,7 @@ class Chef
print_results(children.map { |result| maybe_add_slash(result.display_name, result.dir?) }.sort, "")
end
- exit self.exit_code if self.exit_code
+ exit exit_code if exit_code
end
def add_dir_result(result)
diff --git a/lib/chef/knife/node_delete.rb b/lib/chef/knife/node_delete.rb
index 4dd7d764a1..b03569cded 100644
--- a/lib/chef/knife/node_delete.rb
+++ b/lib/chef/knife/node_delete.rb
@@ -27,18 +27,18 @@ class Chef
require "chef/json_compat"
end
- banner "knife node delete NODE (options)"
+ banner "knife node delete [NODE[,NODE]] (options)"
def run
- @node_name = @name_args[0]
-
- if @node_name.nil?
+ if @name_args.length == 0
show_usage
- ui.fatal("You must specify a node name")
+ ui.fatal("You must specify at least one node name")
exit 1
end
- delete_object(Chef::Node, @node_name)
+ @name_args.each do |node_name|
+ delete_object(Chef::Node, node_name)
+ end
end
end
diff --git a/lib/chef/knife/search.rb b/lib/chef/knife/search.rb
index d102c1e955..046d1c7c52 100644
--- a/lib/chef/knife/search.rb
+++ b/lib/chef/knife/search.rb
@@ -183,7 +183,7 @@ class Chef
return_id, attr_path = f.split("=")
final_filter[return_id.to_sym] = attr_path.split(".")
end
- return final_filter
+ final_filter
end
def create_result_filter_from_attributes(filter_array)
@@ -193,7 +193,7 @@ class Chef
end
# adding magic filter so we can actually pull the name as before
final_filter["__display_name"] = [ "name" ]
- return final_filter
+ final_filter
end
end
diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb
index f827aca280..e206f72630 100644
--- a/lib/chef/knife/ssh.rb
+++ b/lib/chef/knife/ssh.rb
@@ -26,7 +26,6 @@ class Chef
deps do
require "net/ssh"
require "net/ssh/multi"
- require "chef/monkey_patches/net-ssh-multi"
require "readline"
require "chef/exceptions"
require "chef/search/query"
@@ -166,10 +165,10 @@ class Chef
def configure_session
list = config[:manual] ? @name_args[0].split(" ") : search_nodes
if list.length == 0
- if @action_nodes.length == 0
+ if @search_count == 0
ui.fatal("No nodes returned from search")
else
- ui.fatal("#{@action_nodes.length} #{@action_nodes.length > 1 ? "nodes" : "node"} found, " +
+ ui.fatal("#{@search_count} #{@search_count > 1 ? "nodes" : "node"} found, " +
"but does not have the required attribute to establish the connection. " +
"Try setting another attribute to open the connection using --attribute.")
end
@@ -184,41 +183,56 @@ class Chef
# 2) configuration file
# 3) cloud attribute
# 4) fqdn
- if config[:attribute]
- Chef::Log.debug("Using node attribute '#{config[:attribute]}' as the ssh target")
- attribute = config[:attribute]
+ if node["config"]
+ Chef::Log.debug("Using node attribute '#{config[:attribute]}' as the ssh target: #{node["config"]}")
+ node["config"]
elsif Chef::Config[:knife][:ssh_attribute]
- Chef::Log.debug("Using node attribute #{Chef::Config[:knife][:ssh_attribute]}")
- attribute = Chef::Config[:knife][:ssh_attribute]
- elsif node[:cloud] &&
- node[:cloud][:public_hostname] &&
- !node[:cloud][:public_hostname].empty?
- Chef::Log.debug("Using node attribute 'cloud[:public_hostname]' automatically as the ssh target")
- attribute = "cloud.public_hostname"
+ Chef::Log.debug("Using node attribute #{Chef::Config[:knife][:ssh_attribute]}: #{node["knife_config"]}")
+ node["knife_config"]
+ elsif node["cloud"] &&
+ node["cloud"]["public_hostname"] &&
+ !node["cloud"]["public_hostname"].empty?
+ Chef::Log.debug("Using node attribute 'cloud[:public_hostname]' automatically as the ssh target: #{node["cloud"]["public_hostname"]}")
+ node["cloud"]["public_hostname"]
else
# falling back to default of fqdn
- Chef::Log.debug("Using node attribute 'fqdn' as the ssh target")
- attribute = "fqdn"
+ Chef::Log.debug("Using node attribute 'fqdn' as the ssh target: #{node["fqdn"]}")
+ node["fqdn"]
end
- attribute
end
def search_nodes
list = Array.new
query = Chef::Search::Query.new
- @action_nodes = query.search(:node, @name_args[0])[0]
- @action_nodes.each do |item|
+ required_attributes = { fqdn: ["fqdn"], cloud: ["cloud"] }
+
+ separator = ui.presenter.attribute_field_separator
+
+ # if we've set an attribute to use on the command line
+ if config[:attribute]
+ required_attributes[:config] = config[:attribute].split(separator)
+ end
+
+ # if we've configured an attribute in our config
+ if Chef::Config[:knife][:ssh_attribute]
+ required_attributes[:knife_config] = Chef::Config[:knife][:ssh_attribute].split(separator)
+ end
+
+ @search_count = 0
+ query.search(:node, @name_args[0], filter_result: required_attributes) do |item|
+ @search_count += 1
# we should skip the loop to next iteration if the item
# returned by the search is nil
next if item.nil?
# next if we couldn't find the specified attribute in the
# returned node object
- host = extract_nested_value(item, get_ssh_attribute(item))
+ host = get_ssh_attribute(item)
next if host.nil?
ssh_port = item[:cloud].nil? ? nil : item[:cloud][:public_ssh_port]
srv = [host, ssh_port]
list.push(srv)
end
+
list
end
@@ -232,7 +246,7 @@ class Chef
# @param user [String] Optional username for this session.
# @return [Hash<Symbol, Object>]
def session_options(host, port, user = nil)
- ssh_config = Net::SSH.configuration_for(host)
+ ssh_config = Net::SSH.configuration_for(host, true)
{}.tap do |opts|
# Chef::Config[:knife][:ssh_user] is parsed in #configure_user and written to config[:ssh_user]
opts[:user] = user || config[:ssh_user] || ssh_config[:user]
@@ -309,9 +323,9 @@ class Chef
subsession ||= session
command = fixup_sudo(command)
command.force_encoding("binary") if command.respond_to?(:force_encoding)
- subsession.open_channel do |ch|
- ch.request_pty
- ch.exec command do |ch, success|
+ 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)
@@ -532,10 +546,6 @@ class Chef
config[:ssh_identity_file] = get_stripped_unfrozen_value(config[:ssh_identity_file] || config[:identity_file] || Chef::Config[:knife][:ssh_identity_file])
end
- def extract_nested_value(data_structure, path_spec)
- ui.presenter.extract_nested_value(data_structure, path_spec)
- end
-
def run
@longest = 0
diff --git a/lib/chef/knife/ssl_check.rb b/lib/chef/knife/ssl_check.rb
index 82ccb76ad7..b3374e0999 100644
--- a/lib/chef/knife/ssl_check.rb
+++ b/lib/chef/knife/ssl_check.rb
@@ -276,7 +276,7 @@ ADVICE
rescue OpenSSL::X509::StoreError => e
return e.message
end
- return nil
+ nil
end
end
end
diff --git a/lib/chef/knife/user_delete.rb b/lib/chef/knife/user_delete.rb
index ce4575ceab..cc92b4b36c 100644
--- a/lib/chef/knife/user_delete.rb
+++ b/lib/chef/knife/user_delete.rb
@@ -60,7 +60,7 @@ EOF
end
output(format_for_display(object)) if config[:print_after]
- self.msg("Deleted #{user_name}")
+ msg("Deleted #{user_name}")
end
def run
diff --git a/lib/chef/log.rb b/lib/chef/log.rb
index ac2baeb9d1..10c9f0f20d 100644
--- a/lib/chef/log.rb
+++ b/lib/chef/log.rb
@@ -58,7 +58,7 @@ class Chef
end
if Chef::Config[:treat_deprecation_warnings_as_errors]
error(msg, &block)
- raise Chef::Exceptions::DeprecatedFeatureError.new(msg)
+ raise Chef::Exceptions::DeprecatedFeatureError.new(msg.inspect)
else
warn(msg, &block)
end
diff --git a/lib/chef/mash.rb b/lib/chef/mash.rb
index 3858ff09dd..4e4f06634d 100644
--- a/lib/chef/mash.rb
+++ b/lib/chef/mash.rb
@@ -149,7 +149,7 @@ class Mash < Hash
#
# @return [Mash] A new mash with the hash values merged in.
def merge(hash)
- self.dup.update(hash)
+ dup.update(hash)
end
# @param key<Object>
diff --git a/lib/chef/mixin/command.rb b/lib/chef/mixin/command.rb
index 0cc3143ec7..b1fa7ebd89 100644
--- a/lib/chef/mixin/command.rb
+++ b/lib/chef/mixin/command.rb
@@ -103,10 +103,11 @@ class Chef
command_output << "STDERR: #{stderr}"
handle_command_failures(status, command_output, args)
- return status, stdout, stderr
+ [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
@@ -140,7 +141,7 @@ class Chef
Chef::Log.debug("Ran #{command} returned #{status.exitstatus}")
end
- return status, stdout_string, stderr_string
+ [status, stdout_string, stderr_string]
end
def handle_command_failures(status, command_output, opts = {})
diff --git a/lib/chef/mixin/create_path.rb b/lib/chef/mixin/create_path.rb
index 233f7b9521..21a945d2ae 100644
--- a/lib/chef/mixin/create_path.rb
+++ b/lib/chef/mixin/create_path.rb
@@ -53,7 +53,6 @@ class Chef
private
def create_dir(path)
- begin
# When doing multithreaded downloads into the file cache, the following
# interleaving raises an error here:
#
@@ -62,10 +61,9 @@ class Chef
# File.directory?(create_path) <- false
# Dir.mkdir(create_path)
# Dir.mkdir(create_path) <- raises Errno::EEXIST
- Chef::Log.debug("Creating directory #{path}")
- Dir.mkdir(path)
- rescue Errno::EEXIST
- end
+ Chef::Log.debug("Creating directory #{path}")
+ Dir.mkdir(path)
+ rescue Errno::EEXIST
end
end
diff --git a/lib/chef/mixin/deep_merge.rb b/lib/chef/mixin/deep_merge.rb
index c0b2d0d0c5..7016b08ff7 100644
--- a/lib/chef/mixin/deep_merge.rb
+++ b/lib/chef/mixin/deep_merge.rb
@@ -75,7 +75,7 @@ class Chef
end
when Array
if dest.kind_of?(Array)
- dest = dest | source
+ dest |= source
else
dest = source
end
diff --git a/lib/chef/mixin/deprecation.rb b/lib/chef/mixin/deprecation.rb
index 0f059a215f..14414036e7 100644
--- a/lib/chef/mixin/deprecation.rb
+++ b/lib/chef/mixin/deprecation.rb
@@ -65,7 +65,7 @@ class Chef
end
def method_missing(method_name, *args, &block)
- log_deprecation_msg(caller[0..3])
+ deprecated_msg(caller[0..3])
@target.send(method_name, *args, &block)
end
@@ -75,7 +75,7 @@ class Chef
private
- def log_deprecation_msg(*called_from)
+ def deprecated_msg(*called_from)
called_from = called_from.flatten
log("Accessing #{@ivar_name} by the variable @#{@ivar_name} is deprecated. Support will be removed in a future release.")
log("Please update your cookbooks to use #{@ivar_name} in place of @#{@ivar_name}. Accessed from:")
@@ -101,20 +101,14 @@ class Chef
def deprecated_attr_reader(name, alternative, level = :warn)
define_method(name) do
- Chef.log_deprecation("#{self.class}.#{name} is deprecated. Support will be removed in a future release.")
- Chef.log_deprecation(alternative)
- Chef.log_deprecation("Called from:")
- caller[0..3].each { |c| Chef.log_deprecation(c) }
+ Chef.deprecated(:internal_api, "#{self.class}.#{name} is deprecated. Support will be removed in a future release. #{alternative}")
instance_variable_get("@#{name}")
end
end
def deprecated_attr_writer(name, alternative, level = :warn)
define_method("#{name}=") do |value|
- Chef.log_deprecation("Writing to #{self.class}.#{name} with #{name}= is deprecated. Support will be removed in a future release.")
- Chef.log_deprecation(alternative)
- Chef.log_deprecation("Called from:")
- caller[0..3].each { |c| Chef.log_deprecation(c) }
+ Chef.deprecated(:internal_api, "Writing to #{self.class}.#{name} with #{name}= is deprecated. Support will be removed in a future release. #{alternative}")
instance_variable_set("@#{name}", value)
end
end
diff --git a/lib/chef/mixin/from_file.rb b/lib/chef/mixin/from_file.rb
index a6692d798d..4afea5d9f4 100644
--- a/lib/chef/mixin/from_file.rb
+++ b/lib/chef/mixin/from_file.rb
@@ -27,7 +27,7 @@ class Chef
# Raises an IOError if the file cannot be found, or is not readable.
def from_file(filename)
if File.exists?(filename) && File.readable?(filename)
- self.instance_eval(IO.read(filename), filename, 1)
+ instance_eval(IO.read(filename), filename, 1)
else
raise IOError, "Cannot open or read #{filename}!"
end
@@ -39,7 +39,7 @@ class Chef
# Raises an IOError if the file cannot be found, or is not readable.
def class_from_file(filename)
if File.exists?(filename) && File.readable?(filename)
- self.class_eval(IO.read(filename), filename, 1)
+ class_eval(IO.read(filename), filename, 1)
else
raise IOError, "Cannot open or read #{filename}!"
end
diff --git a/lib/chef/mixin/get_source_from_package.rb b/lib/chef/mixin/get_source_from_package.rb
index 555dd634f8..96cef058ed 100644
--- a/lib/chef/mixin/get_source_from_package.rb
+++ b/lib/chef/mixin/get_source_from_package.rb
@@ -37,9 +37,9 @@ class Chef
return if new_resource.package_name.is_a?(Array)
# if we're passed something that looks like a filesystem path, with no source, use it
# - require at least one '/' in the path to avoid gem_package "foo" breaking if a file named 'foo' exists in the cwd
- if new_resource.source.nil? && new_resource.package_name.match(/#{::File::SEPARATOR}/) && ::File.exists?(new_resource.package_name)
+ if new_resource.source.nil? && new_resource.package_name.match(/#{::File::SEPARATOR}/) && ::File.exist?(new_resource.package_name)
Chef::Log.debug("No package source specified, but #{new_resource.package_name} exists on the filesystem, copying to package source")
- new_resource.source(@new_resource.package_name)
+ new_resource.source(new_resource.package_name)
end
end
end
diff --git a/lib/chef/mixin/notifying_block.rb b/lib/chef/mixin/notifying_block.rb
index 2d6a82f493..d3f235f968 100644
--- a/lib/chef/mixin/notifying_block.rb
+++ b/lib/chef/mixin/notifying_block.rb
@@ -20,15 +20,13 @@ class Chef
module NotifyingBlock
def notifying_block(&block)
- begin
- subcontext = subcontext_block(&block)
- Chef::Runner.new(subcontext).converge
- ensure
- # recipes don't have a new_resource
- if respond_to?(:new_resource)
- if subcontext && subcontext.resource_collection.any?(&:updated?)
- new_resource.updated_by_last_action(true)
- end
+ subcontext = subcontext_block(&block)
+ Chef::Runner.new(subcontext).converge
+ ensure
+ # recipes don't have a new_resource
+ if respond_to?(:new_resource)
+ if subcontext && subcontext.resource_collection.any?(&:updated?)
+ new_resource.updated_by_last_action(true)
end
end
end
diff --git a/lib/chef/mixin/params_validate.rb b/lib/chef/mixin/params_validate.rb
index b16df41c8e..0db058c3ab 100644
--- a/lib/chef/mixin/params_validate.rb
+++ b/lib/chef/mixin/params_validate.rb
@@ -102,8 +102,8 @@ class Chef
when Hash
validation.each do |check, carg|
check_method = "_pv_#{check}"
- if self.respond_to?(check_method, true)
- self.send(check_method, opts, key, carg)
+ if respond_to?(check_method, true)
+ send(check_method, opts, key, carg)
else
raise ArgumentError, "Validation map has unknown check: #{check}"
end
@@ -333,7 +333,7 @@ class Chef
if is_name_property
if opts[key].nil?
raise CannotValidateStaticallyError, "name_property cannot be evaluated without a resource." if self == Chef::Mixin::ParamsValidate
- opts[key] = self.instance_variable_get(:"@name")
+ opts[key] = instance_variable_get(:"@name")
end
end
end
diff --git a/lib/chef/mixin/powershell_type_coercions.rb b/lib/chef/mixin/powershell_type_coercions.rb
index 6159c87948..792ec18842 100644
--- a/lib/chef/mixin/powershell_type_coercions.rb
+++ b/lib/chef/mixin/powershell_type_coercions.rb
@@ -21,31 +21,31 @@ class Chef
module Mixin
module PowershellTypeCoercions
- def type_coercions
- @type_coercions ||= {
- Fixnum => { :type => lambda { |x| x.to_s } },
- Float => { :type => lambda { |x| x.to_s } },
- FalseClass => { :type => lambda { |x| "$false" } },
- TrueClass => { :type => lambda { |x| "$true" } },
- Hash => { :type => Proc.new { |x| translate_hash(x) } },
- Array => { :type => Proc.new { |x| translate_array(x) } },
- Chef::Node::ImmutableMash => { :type => Proc.new { |x| translate_hash(x) } },
- Chef::Node::ImmutableArray => { :type => Proc.new { |x| translate_array(x) } },
- }
+ def type_coercion(value)
+ case value
+ when Integer, Float
+ value.to_s
+ when FalseClass
+ "$false"
+ when TrueClass
+ "$true"
+ when Hash, Chef::Node::ImmutableMash
+ translate_hash(value)
+ when Array, Chef::Node::ImmutableArray
+ translate_array(value)
+ end
end
- def translate_type(value)
- translation = type_coercions[value.class]
-
- if translation
- translation[:type].call(value)
- elsif value.respond_to? :to_psobject
+ def psobject_conversion(value)
+ if value.respond_to?(:to_psobject)
"(#{value.to_psobject})"
- else
- safe_string(value.to_s)
end
end
+ def translate_type(value)
+ type_coercion(value) || psobject_conversion(value) || safe_string(value.to_s)
+ end
+
private
def translate_hash(x)
diff --git a/lib/chef/mixin/securable.rb b/lib/chef/mixin/securable.rb
index 55b4e0a6d1..85c9dea1d4 100644
--- a/lib/chef/mixin/securable.rb
+++ b/lib/chef/mixin/securable.rb
@@ -110,7 +110,7 @@ class Chef
# equivalent to something like:
# def rights(permissions=nil, principals=nil, args_hash=nil)
define_method(name) do |permissions = nil, principals = nil, args_hash = nil|
- rights = self.instance_variable_get("@#{name}".to_sym)
+ rights = instance_variable_get("@#{name}".to_sym)
unless permissions.nil?
input = {
:permissions => permissions,
diff --git a/lib/chef/mixin/shell_out.rb b/lib/chef/mixin/shell_out.rb
index d8607c8de7..18bd067989 100644
--- a/lib/chef/mixin/shell_out.rb
+++ b/lib/chef/mixin/shell_out.rb
@@ -1,6 +1,6 @@
#--
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2010-2016, Chef Software Inc.
+# Copyright:: Copyright 2010-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,11 +16,84 @@
# limitations under the License.
require "mixlib/shellout"
+require "chef/deprecated"
class Chef
module Mixin
module ShellOut
+ # PREFERRED APIS:
+ #
+ # shell_out_compact and shell_out_compact! flatten their array arguments and remove nils and pass
+ # the resultant array to shell_out. this actually eliminates spaces-in-args bugs because this:
+ #
+ # shell_out!("command #{arg}")
+ #
+ # becomes two arguments if arg has spaces and requires quotations:
+ #
+ # shell_out!("command '#{arg}'")
+ #
+ # using shell_out_compact! this becomes:
+ #
+ # shell_out_compact!("command", arg)
+ #
+ # and spaces in the arg just works and it does not become two arguments (and the shell quoting around
+ # the argument must actually be removed).
+ #
+ # there's also an implicit join between all the array elements, and nested arrays are flattened which
+ # means that odd where-do-i-put-the-spaces options handling just works, and instead of this:
+ #
+ # opts = "" # needs to be empty string for when foo and bar are both missing
+ # opts << " -foo" if needs_foo? # needs the leading space on both of these
+ # opts << " -bar" if needs_bar?
+ # shell_out!("cmd#{opts}") # have to think way too hard about why there's no space here
+ #
+ # becomes:
+ #
+ # opts = []
+ # opts << "-foo" if needs_foo?
+ # opts << "-bar" if needs_bar?
+ # shell_out_compact!("cmd", opts)
+ #
+ # and opts can be an empty array or nil and it'll work out fine.
+ #
+ # generally its best to use shell_out_compact! in code and setup expectations on shell_out! in tests
+ #
+
+ def shell_out_compact(*args, **options)
+ if options.empty?
+ shell_out(*clean_array(*args))
+ else
+ shell_out(*clean_array(*args), **options)
+ end
+ end
+
+ def shell_out_compact!(*args, **options)
+ if options.empty?
+ shell_out!(*clean_array(*args))
+ else
+ shell_out!(*clean_array(*args), **options)
+ end
+ end
+
+ # helper sugar for resources that support passing timeouts to shell_out
+
+ def shell_out_compact_timeout(*args, **options)
+ raise "object is not a resource that supports timeouts" unless respond_to?(:new_resource) && new_resource.respond_to?(:timeout)
+ options_dup = options.dup
+ options_dup[:timeout] = new_resource.timeout if new_resource.timeout
+ options_dup[:timeout] = 900 unless options_dup.key?(:timeout)
+ shell_out_compact(*args, **options_dup)
+ end
+
+ def shell_out_compact_timeout!(*args, **options)
+ raise "object is not a resource that supports timeouts" unless respond_to?(:new_resource) && new_resource.respond_to?(:timeout)
+ options_dup = options.dup
+ options_dup[:timeout] = new_resource.timeout if new_resource.timeout
+ options_dup[:timeout] = 900 unless options_dup.key?(:timeout)
+ shell_out_compact!(*args, **options_dup)
+ end
+
# shell_out! runs a command on the system and will raise an error if the command fails, which is what you want
# for debugging, shell_out and shell_out! both will display command output to the tty when the log level is debug
# Generally speaking, 'extend Chef::Mixin::ShellOut' in your recipes and include 'Chef::Mixin::ShellOut' in your LWRPs
@@ -75,7 +148,7 @@ class Chef
my_options[new_option] = value
end
- return my_command_args
+ my_command_args
end
# Helper for sublcasses to convert an array of string args into a string. It
@@ -85,10 +158,12 @@ class Chef
# @param args [String] variable number of string arguments
# @return [String] nicely concatenated string or empty string
def a_to_s(*args)
- clean_array(*args).join(" ")
+ # can't quite deprecate this yet
+ #Chef.deprecated(:package_misc, "a_to_s is deprecated use shell_out_compact or shell_out_compact_timeout instead")
+ args.flatten.reject { |i| i.nil? || i == "" }.map(&:to_s).join(" ")
end
- # Helper for sublcasses to reject nil and empty strings out of an array. It allows
+ # Helper for sublcasses to reject nil out of an array. It allows
# using the array form of shell_out (which avoids the need to surround arguments with
# quote marks to deal with shells).
#
@@ -105,7 +180,7 @@ class Chef
# @param args [String] variable number of string arguments
# @return [Array] array of strings with nil and null string rejection
def clean_array(*args)
- args.flatten.reject { |i| i.nil? || i == "" }.map(&:to_s)
+ args.flatten.compact.map(&:to_s)
end
private
@@ -118,7 +193,7 @@ class Chef
end
def deprecate_option(old_option, new_option)
- Chef.log_deprecation "DEPRECATION: Chef::Mixin::ShellOut option :#{old_option} is deprecated. Use :#{new_option}"
+ Chef.deprecated :internal_api, "Chef::Mixin::ShellOut option :#{old_option} is deprecated. Use :#{new_option}"
end
def io_for_live_stream
diff --git a/lib/chef/mixin/unformatter.rb b/lib/chef/mixin/unformatter.rb
index 7dad56b270..5663749e58 100644
--- a/lib/chef/mixin/unformatter.rb
+++ b/lib/chef/mixin/unformatter.rb
@@ -22,9 +22,9 @@ class Chef
def write(message)
data = message.match(/(\[.+?\] )?([\w]+):(.*)$/)
- self.send(data[2].downcase.chomp.to_sym, data[3].strip)
+ send(data[2].downcase.chomp.to_sym, data[3].strip)
rescue NoMethodError
- self.send(:info, message)
+ send(:info, message)
end
end
diff --git a/lib/chef/mixin/uris.rb b/lib/chef/mixin/uris.rb
index 7dc04d662b..ea55eefd8f 100644
--- a/lib/chef/mixin/uris.rb
+++ b/lib/chef/mixin/uris.rb
@@ -31,12 +31,10 @@ class Chef
end
def as_uri(source)
- begin
- URI.parse(source)
- rescue URI::InvalidURIError
- Chef::Log.warn("#{source} was an invalid URI. Trying to escape invalid characters")
- URI.parse(Addressable::URI.encode(source))
- end
+ URI.parse(source)
+ rescue URI::InvalidURIError
+ Chef::Log.warn("#{source} was an invalid URI. Trying to escape invalid characters")
+ URI.parse(Addressable::URI.encode(source))
end
end
diff --git a/lib/chef/mixin/versioned_api.rb b/lib/chef/mixin/versioned_api.rb
new file mode 100644
index 0000000000..9c2f2f4cdb
--- /dev/null
+++ b/lib/chef/mixin/versioned_api.rb
@@ -0,0 +1,69 @@
+#--
+# 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.
+#
+
+class Chef
+ module Mixin
+ module VersionedAPI
+
+ def minimum_api_version(version = nil)
+ if version
+ @minimum_api_version = version
+ else
+ @minimum_api_version
+ end
+ end
+
+ end
+
+ module VersionedAPIFactory
+
+ def versioned_interfaces
+ @versioned_interfaces ||= []
+ end
+
+ def add_versioned_api_class(klass)
+ versioned_interfaces << klass
+ end
+
+ def versioned_api_class
+ versioned_interfaces.select do |klass|
+ version = klass.send(:minimum_api_version)
+ # min and max versions will be nil if we've not made a request to the server yet,
+ # in which case we'll just start with the highest version and see what happens
+ ServerAPIVersions.instance.min_server_version.nil? || (version >= ServerAPIVersions.instance.min_server_version && version <= ServerAPIVersions.instance.max_server_version)
+ end
+ .sort { |a, b| a.send(:minimum_api_version) <=> b.send(:minimum_api_version) }
+ .last
+ end
+
+ def def_versioned_delegator(method)
+ line_no = __LINE__; str = %{
+ def self.#{method}(*args, &block)
+ versioned_api_class.__send__(:#{method}, *args, &block)
+ end
+ }
+ module_eval(str, __FILE__, line_no)
+ end
+
+ def new(*args)
+ object = versioned_api_class.allocate
+ object.send(:initialize, *args)
+ object
+ end
+ end
+ end
+end
diff --git a/lib/chef/mixin/which.rb b/lib/chef/mixin/which.rb
index 63c84883d5..fd386241a0 100644
--- a/lib/chef/mixin/which.rb
+++ b/lib/chef/mixin/which.rb
@@ -1,6 +1,6 @@
#--
# Author:: Lamont Granquist <lamont@chef.io>
-# Copyright:: Copyright 2010-2016, Chef Software Inc.
+# Copyright:: Copyright 2010-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,19 +18,32 @@
class Chef
module Mixin
module Which
- def which(cmd, opts = {})
- extra_path =
- if opts[:extra_path].nil?
- [ "/bin", "/usr/bin", "/sbin", "/usr/sbin" ]
- else
- [ opts[:extra_path] ].flatten
- end
- paths = ENV["PATH"].split(File::PATH_SEPARATOR) + extra_path
- paths.each do |path|
- filename = File.join(path, cmd)
- return filename if File.executable?(Chef.path_to(filename))
- end
- false
+ def which(*cmds, extra_path: nil, &block)
+ where(*cmds, extra_path: extra_path, &block).first || false
+ end
+
+ def where(*cmds, extra_path: nil, &block)
+ # NOTE: unnecessarily duplicates function of path_sanity
+ extra_path ||= [ "/bin", "/usr/bin", "/sbin", "/usr/sbin" ]
+ paths = env_path.split(File::PATH_SEPARATOR) + extra_path
+ cmds.map do |cmd|
+ paths.map do |path|
+ filename = Chef.path_to(File.join(path, cmd))
+ filename if valid_executable?(filename, &block)
+ end.compact
+ end.flatten
+ end
+
+ private
+
+ # for test stubbing
+ def env_path
+ ENV["PATH"]
+ end
+
+ def valid_executable?(filename, &block)
+ return false unless File.executable?(filename) && !File.directory?(filename)
+ block ? yield(filename) : true
end
end
end
diff --git a/lib/chef/mixin/wide_string.rb b/lib/chef/mixin/wide_string.rb
index 4342ef1650..ef7828e2d8 100644
--- a/lib/chef/mixin/wide_string.rb
+++ b/lib/chef/mixin/wide_string.rb
@@ -34,7 +34,7 @@ class Chef
ustring = (ustring + "").force_encoding("UTF-8") if ustring.respond_to?(:force_encoding) && ustring.encoding.name != "UTF-8"
# ensure we have the double-null termination Windows Wide likes
- ustring = ustring + "\000\000" if ustring.length == 0 || ustring[-1].chr != "\000"
+ ustring += "\000\000" if ustring.length == 0 || ustring[-1].chr != "\000"
# encode it all as UTF-16LE AKA Windows Wide Character AKA Windows Unicode
ustring = begin
diff --git a/lib/chef/mixin/windows_architecture_helper.rb b/lib/chef/mixin/windows_architecture_helper.rb
index 49252af484..67c34a85a1 100644
--- a/lib/chef/mixin/windows_architecture_helper.rb
+++ b/lib/chef/mixin/windows_architecture_helper.rb
@@ -74,11 +74,11 @@ class Chef
def node_supports_windows_architecture?(node, desired_architecture)
assert_valid_windows_architecture!(desired_architecture)
- return ( node_windows_architecture(node) == :x86_64 ) || ( desired_architecture == :i386 )
+ ( node_windows_architecture(node) == :x86_64 ) || ( desired_architecture == :i386 )
end
def valid_windows_architecture?(architecture)
- return ( architecture == :x86_64 ) || ( architecture == :i386 )
+ ( architecture == :x86_64 ) || ( architecture == :i386 )
end
def assert_valid_windows_architecture!(architecture)
diff --git a/lib/chef/mixin/xml_escape.rb b/lib/chef/mixin/xml_escape.rb
index f9a41b9fd0..243bb7f044 100644
--- a/lib/chef/mixin/xml_escape.rb
+++ b/lib/chef/mixin/xml_escape.rb
@@ -103,11 +103,9 @@ class Chef
(0xE000..0xFFFD), (0x10000..0x10FFFF)]
def xml_escape(unescaped_str)
- begin
- unescaped_str.unpack("U*").map { |char| xml_escape_char!(char) }.join
- rescue
- unescaped_str.unpack("C*").map { |char| xml_escape_char!(char) }.join
- end
+ unescaped_str.unpack("U*").map { |char| xml_escape_char!(char) }.join
+ rescue
+ unescaped_str.unpack("C*").map { |char| xml_escape_char!(char) }.join
end
private
diff --git a/lib/chef/monkey_patches/net-ssh-multi.rb b/lib/chef/monkey_patches/net-ssh-multi.rb
deleted file mode 100644
index 7b7b1bbf7f..0000000000
--- a/lib/chef/monkey_patches/net-ssh-multi.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# Author:: Serdar Sutay (<serdar@chef.io>)
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# == net-ssh-multi gem patch for concurrency
-# net-ssh-multi gem has 2 bugs associated with the use of
-# :concurrent_connections option.
-# 1-) There is a race condition while fetching the next_session when
-# :concurrent_connections are set. @open_connections is being
-# incremented by the connection thread and sometimes
-# realize_pending_connections!() method can create more than required
-# connection threads before the @open_connections is set by the
-# previously created threads.
-# 2-) When :concurrent_connections is set, server classes are setup
-# with PendingConnection objects that always return true to busy?
-# calls. If a connection fails when :concurrent_connections is set,
-# server ends up returning true to all busy? calls since the session
-# object is not replaced. Due to this, main event loop (process()
-# function) never gets terminated.
-#
-# See: https://github.com/net-ssh/net-ssh-multi/pull/4
-
-require "net/ssh/multi/version"
-
-if Net::SSH::Multi::Version::STRING == "1.1.0" || Net::SSH::Multi::Version::STRING == "1.2.0"
-
- require "net/ssh/multi"
-
- module Net
- module SSH
- module Multi
- class Server
-
- # Make sure that server returns false if the ssh connection
- # has failed.
- def busy?(include_invisible = false)
- !failed? && session && session.busy?(include_invisible)
- end
-
- end
-
- class Session
- def next_session(server, force = false) #:nodoc:
- # don't retry a failed attempt
- return nil if server.failed?
-
- @session_mutex.synchronize do
- if !force && concurrent_connections && concurrent_connections <= open_connections
- connection = PendingConnection.new(server)
- @pending_sessions << connection
- return connection
- end
-
- # ===== PATCH START
- # Only increment the open_connections count if the connection
- # is not being forced. Incase of a force, it will already be
- # incremented.
- if !force
- @open_connections += 1
- end
- # ===== PATCH END
- end
-
- begin
- server.new_session
-
- # I don't understand why this should be necessary--StandardError is a
- # subclass of Exception, after all--but without explicitly rescuing
- # StandardError, things like Errno::* and SocketError don't get caught
- # here!
- rescue Exception, StandardError => e
- server.fail!
- @session_mutex.synchronize { @open_connections -= 1 }
-
- case on_error
- when :ignore then
- # do nothing
- when :warn then
- warn("error connecting to #{server}: #{e.class} (#{e.message})")
- when Proc then
- go = catch(:go) { on_error.call(server); nil }
- case go
- when nil, :ignore then # nothing
- when :retry then retry
- when :raise then raise
- else warn "unknown 'go' command: #{go.inspect}"
- end
- else
- raise
- end
-
- return nil
- end
- end
-
- def realize_pending_connections! #:nodoc:
- return unless concurrent_connections
-
- server_list.each do |server|
- server.close if !server.busy?(true)
- server.update_session!
- end
-
- @connect_threads.delete_if { |t| !t.alive? }
-
- count = concurrent_connections ? (concurrent_connections - open_connections) : @pending_sessions.length
- count.times do
- session = @pending_sessions.pop
- break unless session
- # ===== PATCH START
- # Increment the open_connections count here to prevent
- # creation of connection thread again before that is
- # incremented by the thread.
- @session_mutex.synchronize { @open_connections += 1 }
- # ===== PATCH END
- @connect_threads << Thread.new do
- session.replace_with(next_session(session.server, true))
- end
- end
- end
-
- end
- end
- end
- end
-
-end
diff --git a/lib/chef/monkey_patches/webrick-utils.rb b/lib/chef/monkey_patches/webrick-utils.rb
index ccca5825e2..7f525f122f 100644
--- a/lib/chef/monkey_patches/webrick-utils.rb
+++ b/lib/chef/monkey_patches/webrick-utils.rb
@@ -44,7 +44,7 @@ module WEBrick
end
end
raise last_error if sockets.empty?
- return sockets
+ sockets
end
module_function :create_listeners
end
diff --git a/lib/chef/node.rb b/lib/chef/node.rb
index 7351a7bfa5..808fb1dc6e 100644
--- a/lib/chef/node.rb
+++ b/lib/chef/node.rb
@@ -111,7 +111,7 @@ class Chef
# Set the name of this Node, or return the current name.
def name(arg = nil)
- if arg != nil
+ if !arg.nil?
validate(
{ :name => arg },
{ :name => { :kind_of => String,
@@ -201,7 +201,7 @@ class Chef
end
def set
- Chef.log_deprecation("node.set is deprecated and will be removed in Chef 14, please use node.default/node.override (or node.normal only if you really need persistence)")
+ Chef.deprecated(:attributes, "node.set is deprecated and will be removed in Chef 14, please use node.default/node.override (or node.normal only if you really need persistence)")
normal
end
@@ -333,8 +333,8 @@ class Chef
platform, version = Chef::Platform.find_platform_and_version(self)
Chef::Log.debug("Platform is #{platform} version #{version}")
- self.automatic[:platform] = platform
- self.automatic[:platform_version] = version
+ automatic[:platform] = platform
+ automatic[:platform_version] = version
end
# Consumes the combined run_list and other attributes in +attrs+
@@ -343,7 +343,7 @@ class Chef
normal_attrs_to_merge = consume_chef_environment(normal_attrs_to_merge)
Chef::Log.debug("Applying attributes from json file")
self.normal_attrs = Chef::Mixin::DeepMerge.merge(normal_attrs, normal_attrs_to_merge)
- self.tags # make sure they're defined
+ tags # make sure they're defined
end
# Lazy initializer for tags attribute
@@ -394,8 +394,8 @@ class Chef
# Clear defaults and overrides, so that any deleted attributes
# between runs are still gone.
def reset_defaults_and_overrides
- self.default.clear
- self.override.clear
+ default.clear
+ override.clear
end
# Expands the node's run list and sets the default and override
@@ -414,7 +414,7 @@ class Chef
expansion = run_list.expand(chef_environment, data_source)
raise Chef::Exceptions::MissingRole, expansion if expansion.errors?
- self.tags # make sure they're defined
+ tags # make sure they're defined
automatic_attrs[:recipes] = expansion.recipes.with_duplicate_names
automatic_attrs[:expanded_run_list] = expansion.recipes.with_fully_qualified_names_and_version_constraints
@@ -509,7 +509,7 @@ class Chef
# Create a Chef::Node from JSON
def self.json_create(o)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::Node#from_hash")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::Node#from_hash")
from_hash(o)
end
@@ -632,14 +632,14 @@ class Chef
def ==(other)
if other.kind_of?(self.class)
- self.name == other.name
+ name == other.name
else
false
end
end
def <=>(other)
- self.name <=> other.name
+ name <=> other.name
end
private
diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb
index d5b0ee5d72..4febd47b44 100644
--- a/lib/chef/node/attribute.rb
+++ b/lib/chef/node/attribute.rb
@@ -416,23 +416,22 @@ class Chef
def normal_unless(*args)
return Decorator::Unchain.new(self, :normal_unless) unless args.length > 0
- write(:normal, *args) if read(*args[0...-1]).nil?
+ write(:normal, *args) if normal.read(*args[0...-1]).nil?
end
def default_unless(*args)
return Decorator::Unchain.new(self, :default_unless) unless args.length > 0
- write(:default, *args) if read(*args[0...-1]).nil?
+ write(:default, *args) if default.read(*args[0...-1]).nil?
end
def override_unless(*args)
return Decorator::Unchain.new(self, :override_unless) unless args.length > 0
- write(:override, *args) if read(*args[0...-1]).nil?
+ write(:override, *args) if override.read(*args[0...-1]).nil?
end
def set_unless(*args)
- Chef.log_deprecation("node.set_unless is deprecated and will be removed in Chef 14, please use node.default_unless/node.override_unless (or node.normal_unless if you really need persistence)")
- return Decorator::Unchain.new(self, :default_unless) unless args.length > 0
- write(:normal, *args) if read(*args[0...-1]).nil?
+ Chef.deprecated(:attributes, "node.set_unless is deprecated and will be removed in Chef 14, please use node.default_unless/node.override_unless (or node.normal_unless if you really need persistence)")
+ normal_unless(*args)
end
def has_key?(key)
@@ -455,19 +454,19 @@ class Chef
end
def write(level, *args, &block)
- self.send(level).write(*args, &block)
+ send(level).write(*args, &block)
end
def write!(level, *args, &block)
- self.send(level).write!(*args, &block)
+ send(level).write!(*args, &block)
end
def unlink(level, *path)
- self.send(level).unlink(*path)
+ send(level).unlink(*path)
end
def unlink!(level, *path)
- self.send(level).unlink!(*path)
+ send(level).unlink!(*path)
end
alias :attribute? :has_key?
@@ -481,15 +480,14 @@ class Chef
if symbol == :to_ary
merged_attributes.send(symbol, *args)
elsif args.empty?
- puts symbol
- Chef.log_deprecation %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"])}
+ 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"])})
if key?(symbol)
self[symbol]
else
raise NoMethodError, "Undefined method or attribute `#{symbol}' on `node'"
end
elsif symbol.to_s =~ /=$/
- Chef.log_deprecation %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")}
+ 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
diff --git a/lib/chef/node/common_api.rb b/lib/chef/node/common_api.rb
index 9bb83a5178..a703c1ef54 100644
--- a/lib/chef/node/common_api.rb
+++ b/lib/chef/node/common_api.rb
@@ -24,7 +24,7 @@ class Chef
# method-style access to attributes
def valid_container?(obj, key)
- return obj.is_a?(Hash) || (obj.is_a?(Array) && key.is_a?(Fixnum))
+ obj.is_a?(Hash) || (obj.is_a?(Array) && key.is_a?(Integer))
end
private :valid_container?
@@ -85,16 +85,14 @@ class Chef
end
end
end
- return true
+ true
end
# this is a safe non-autovivifying reader that returns nil if the attribute does not exist
def read(*path)
- begin
- read!(*path)
- rescue Chef::Exceptions::NoSuchAttribute
- nil
- end
+ read!(*path)
+ rescue Chef::Exceptions::NoSuchAttribute
+ nil
end
# non-autovivifying reader that throws an exception if the attribute does not exist
diff --git a/lib/chef/node/mixin/state_tracking.rb b/lib/chef/node/mixin/state_tracking.rb
index 469d4d300f..5958973024 100644
--- a/lib/chef/node/mixin/state_tracking.rb
+++ b/lib/chef/node/mixin/state_tracking.rb
@@ -34,14 +34,17 @@ class Chef
@__precedence__ = precedence
end
- def [](key)
+ def [](*args)
ret = super
+ key = args.first
next_path = [ __path__, convert_key(key) ].flatten.compact
copy_state_to(ret, next_path)
end
- def []=(key, value)
+ def []=(*args)
ret = super
+ key = args.first
+ value = args.last
next_path = [ __path__, convert_key(key) ].flatten.compact
send_attribute_changed_event(next_path, value)
copy_state_to(ret, next_path)
diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb
index 5eac63d380..552c90b8d1 100644
--- a/lib/chef/node_map.rb
+++ b/lib/chef/node_map.rb
@@ -32,8 +32,8 @@ class Chef
# @return [NodeMap] Returns self for possible chaining
#
def set(key, value, platform: nil, platform_version: nil, platform_family: nil, os: nil, on_platform: nil, on_platforms: nil, canonical: nil, override: nil, &block)
- Chef.log_deprecation("The on_platform option to node_map has been deprecated") if on_platform
- Chef.log_deprecation("The on_platforms option to node_map has been deprecated") if on_platforms
+ Chef.deprecated(:internal_api, "The on_platform option to node_map has been deprecated") if on_platform
+ Chef.deprecated(:internal_api, "The on_platforms option to node_map has been deprecated") if on_platforms
platform ||= on_platform || on_platforms
filters = {}
filters[:platform] = platform if platform
@@ -113,7 +113,7 @@ class Chef
remaining
end
- protected
+ private
#
# Succeeds if:
@@ -172,7 +172,8 @@ class Chef
!!canonical == !!matcher[:canonical]
end
- def compare_matchers(key, new_matcher, matcher)
+ # @api private
+ def dispatch_compare_matchers(key, new_matcher, matcher)
cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:block] }
return cmp if cmp != 0
cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform_version] }
@@ -189,6 +190,21 @@ class Chef
0
end
+ #
+ # "provides" lines with identical filters sort by class name (ascending).
+ #
+ def compare_matchers(key, new_matcher, matcher)
+ cmp = dispatch_compare_matchers(key, new_matcher, matcher)
+ if cmp == 0
+ # Sort by class name (ascending) as well, if all other properties
+ # are exactly equal
+ if new_matcher[:value].is_a?(Class) && !new_matcher[:override]
+ cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:value].name }
+ end
+ end
+ cmp
+ end
+
def compare_matcher_properties(new_matcher, matcher)
a = yield(new_matcher)
b = yield(matcher)
diff --git a/lib/chef/org.rb b/lib/chef/org.rb
index a148e37aea..bed5600920 100644
--- a/lib/chef/org.rb
+++ b/lib/chef/org.rb
@@ -73,15 +73,15 @@ class Chef
end
def create
- payload = { :name => self.name, :full_name => self.full_name }
+ payload = { :name => name, :full_name => full_name }
new_org = chef_rest.post("organizations", payload)
- Chef::Org.from_hash(self.to_hash.merge(new_org))
+ Chef::Org.from_hash(to_hash.merge(new_org))
end
def update
- payload = { :name => self.name, :full_name => self.full_name }
+ payload = { :name => name, :full_name => full_name }
new_org = chef_rest.put("organizations/#{name}", payload)
- Chef::Org.from_hash(self.to_hash.merge(new_org))
+ Chef::Org.from_hash(to_hash.merge(new_org))
end
def destroy
@@ -89,14 +89,12 @@ class Chef
end
def save
- begin
- create
- rescue Net::HTTPServerException => e
- if e.response.code == "409"
- update
- else
- raise e
- end
+ create
+ rescue Net::HTTPServerException => e
+ if e.response.code == "409"
+ update
+ else
+ raise e
end
end
@@ -125,7 +123,7 @@ class Chef
end
def self.json_create(json)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::Org#from_json or Chef::Org#load.")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::Org#from_json or Chef::Org#load.")
Chef::Org.from_json(json)
end
diff --git a/lib/chef/platform/handler_map.rb b/lib/chef/platform/handler_map.rb
deleted file mode 100644
index da8f84237f..0000000000
--- a/lib/chef/platform/handler_map.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Author:: John Keiser (<jkeiser@chef.io>)
-# Copyright:: Copyright 2015-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/node_map"
-
-class Chef
- class Platform
- class HandlerMap < Chef::NodeMap
- #
- # "provides" lines with identical filters sort by class name (ascending).
- #
- def compare_matchers(key, new_matcher, matcher)
- cmp = super
- if cmp == 0
- # Sort by class name (ascending) as well, if all other properties
- # are exactly equal
- if new_matcher[:value].is_a?(Class) && !new_matcher[:override]
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:value].name }
- end
- end
- cmp
- end
- end
- end
-end
diff --git a/lib/chef/platform/provider_handler_map.rb b/lib/chef/platform/provider_handler_map.rb
index 26acf150df..4f87a36d1d 100644
--- a/lib/chef/platform/provider_handler_map.rb
+++ b/lib/chef/platform/provider_handler_map.rb
@@ -17,12 +17,12 @@
#
require "singleton"
-require "chef/platform/handler_map"
+require "chef/node_map"
class Chef
class Platform
# @api private
- class ProviderHandlerMap < Chef::Platform::HandlerMap
+ class ProviderHandlerMap < Chef::NodeMap
include Singleton
end
end
diff --git a/lib/chef/platform/provider_mapping.rb b/lib/chef/platform/provider_mapping.rb
index bc565d92ef..55e831c343 100644
--- a/lib/chef/platform/provider_mapping.rb
+++ b/lib/chef/platform/provider_mapping.rb
@@ -35,6 +35,7 @@ class Chef
include Chef::Mixin::ParamsValidate
def find(name, version)
+ Chef.deprecated(:chef_platform_methods, "#{self.name}.find is deprecated")
provider_map = platforms[:default].clone
name_sym = name
@@ -86,10 +87,11 @@ class Chef
raise ArgumentError, "Cannot find a version for #{node}" unless version
- return platform, version
+ [platform, version]
end
def provider_for_resource(resource, action = :nothing)
+ Chef.deprecated(:chef_platform_methods, "#{name}.provider_for_resource is deprecated")
node = resource.run_context && resource.run_context.node
raise ArgumentError, "Cannot find the provider for a resource with no run context set" unless node
provider = find_provider_for_node(node, resource).new(resource, resource.run_context)
@@ -98,15 +100,17 @@ class Chef
end
def provider_for_node(node, resource_type)
- raise NotImplementedError, "#{self.class.name} no longer supports #provider_for_node"
+ raise NotImplementedError, "#{name} no longer supports #provider_for_node"
end
def find_provider_for_node(node, resource_type)
+ Chef.deprecated(:chef_platform_methods, "#{name}.find_provider_for_node is deprecated")
platform, version = find_platform_and_version(node)
find_provider(platform, version, resource_type)
end
def set(args)
+ Chef.deprecated(:chef_platform_methods, "#{name}.set is deprecated")
validate(
args,
{
@@ -172,6 +176,7 @@ class Chef
end
def find_provider(platform, version, resource_type)
+ Chef.deprecated(:chef_platform_methods, "#{name}.find_provider is deprecated")
provider_klass = explicit_provider(platform, version, resource_type) ||
platform_provider(platform, version, resource_type) ||
resource_matching_provider(platform, version, resource_type)
diff --git a/lib/chef/platform/query_helpers.rb b/lib/chef/platform/query_helpers.rb
index 7d522072a3..624dc05e9c 100644
--- a/lib/chef/platform/query_helpers.rb
+++ b/lib/chef/platform/query_helpers.rb
@@ -55,7 +55,7 @@ class Chef
# If accessing the registry key failed, then we're probably not on
# nano. Fail through.
end
- return nano == 1
+ nano == 1
end
def supports_msi?
diff --git a/lib/chef/platform/rebooter.rb b/lib/chef/platform/rebooter.rb
index 74c8b2da1f..6829b66539 100644
--- a/lib/chef/platform/rebooter.rb
+++ b/lib/chef/platform/rebooter.rb
@@ -35,7 +35,9 @@ class Chef
cmd = if Chef::Platform.windows?
# should this do /f as well? do we then need a minimum delay to let apps quit?
- "shutdown /r /t #{reboot_info[:delay_mins] * 60} /c \"#{reboot_info[:reason]}\""
+ # Use explicit path to shutdown.exe, to protect against https://github.com/chef/chef/issues/5594
+ windows_shutdown_path = "#{ENV['SYSTEMROOT']}/System32/shutdown.exe"
+ "#{windows_shutdown_path} /r /t #{reboot_info[:delay_mins] * 60} /c \"#{reboot_info[:reason]}\""
else
# probably Linux-only.
"shutdown -r +#{reboot_info[:delay_mins]} \"#{reboot_info[:reason]}\""
diff --git a/lib/chef/platform/resource_handler_map.rb b/lib/chef/platform/resource_handler_map.rb
index be1b9c28f5..0aab04212f 100644
--- a/lib/chef/platform/resource_handler_map.rb
+++ b/lib/chef/platform/resource_handler_map.rb
@@ -17,12 +17,12 @@
#
require "singleton"
-require "chef/platform/handler_map"
+require "chef/node_map"
class Chef
class Platform
# @api private
- class ResourceHandlerMap < Chef::Platform::HandlerMap
+ class ResourceHandlerMap < Chef::NodeMap
include Singleton
end
end
diff --git a/lib/chef/policy_builder/expand_node_object.rb b/lib/chef/policy_builder/expand_node_object.rb
index df6956cc77..d8f4f752de 100644
--- a/lib/chef/policy_builder/expand_node_object.rb
+++ b/lib/chef/policy_builder/expand_node_object.rb
@@ -112,7 +112,7 @@ class Chef
# to create a PolicyBuilder::Dynamc policy builder and allow it to select
# the proper implementation.
def load_node
- Chef.log_deprecation("ExpandNodeObject#load_node is deprecated. Please use Chef::PolicyBuilder::Dynamic instead of using ExpandNodeObject directly")
+ Chef.deprecated(:internal_api, "ExpandNodeObject#load_node is deprecated. Please use Chef::PolicyBuilder::Dynamic instead of using ExpandNodeObject directly")
events.node_load_start(node_name, config)
Chef::Log.debug("Building node object for #{node_name}")
diff --git a/lib/chef/policy_builder/policyfile.rb b/lib/chef/policy_builder/policyfile.rb
index 8d2437fef5..f0009eac6c 100644
--- a/lib/chef/policy_builder/policyfile.rb
+++ b/lib/chef/policy_builder/policyfile.rb
@@ -173,6 +173,7 @@ class Chef
CookbookCacheCleaner.instance.skip_removal = true if named_run_list_requested?
node.run_list(run_list)
+ node.automatic_attrs[:policy_revision] = revision_id
node.automatic_attrs[:roles] = []
node.automatic_attrs[:recipes] = run_list_expansion_ish.recipes
run_list_expansion_ish
diff --git a/lib/chef/property.rb b/lib/chef/property.rb
index 9433326b5b..8fa290251a 100644
--- a/lib/chef/property.rb
+++ b/lib/chef/property.rb
@@ -116,7 +116,7 @@ class Chef
options.delete(:name_property)
preferred_default = :default
end
- Chef.log_deprecation("Cannot specify both default and name_property together on property #{self}. Only one (#{preferred_default}) will be obeyed. In Chef 13, this will become an error. Please remove one or the other from the property.")
+ Chef.deprecated(:custom_resource, "Cannot specify both default and name_property together on property #{self}. Only one (#{preferred_default}) will be obeyed. In Chef 13, this will become an error. Please remove one or the other from the property.")
end
# Validate the default early, so the user gets a good error message, and
@@ -287,13 +287,13 @@ class Chef
input_to_stored_value(resource, value)
# If nil is valid, and it would change the value, warn that this will change to a set.
if !result.nil?
- Chef.log_deprecation("An attempt was made to change #{name} from #{result.inspect} to nil by calling #{name}(nil). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil.")
+ Chef.deprecated(:custom_resource, "An attempt was made to change #{name} from #{result.inspect} to nil by calling #{name}(nil). In Chef 12, this does a get rather than a set. In Chef 13, this will change to set the value to nil.")
end
rescue Chef::Exceptions::DeprecatedFeatureError
raise
rescue
# If nil is invalid, warn that this will become an error.
- Chef.log_deprecation("nil is an invalid value for #{self}. In Chef 13, this warning will change to an error. Error: #{$!}")
+ Chef.deprecated(:custom_resource, "nil is an invalid value for #{self}. In Chef 13, this warning will change to an error. Error: #{$!}")
end
result
@@ -518,6 +518,13 @@ class Chef
# be using the existing getter/setter to manipulate it instead.
return if !instance_variable_name
+ # We deprecate any attempt to create a property that already exists as a
+ # method in some Classes that we know would cause our users problems.
+ # For example, creating a `hash` property could cause issues when adding
+ # a Chef::Resource instance to an data structure that expects to be able
+ # to call the `#hash` method and get back an appropriate Fixnum.
+ emit_property_redefinition_deprecations
+
# We prefer this form because the property name won't show up in the
# stack trace if you use `define_method`.
declared_in.class_eval <<-EOM, __FILE__, __LINE__ + 1
@@ -632,6 +639,30 @@ class Chef
private
+ def emit_property_redefinition_deprecations
+ # We only emit deprecations if this property already exists as an instance method.
+ # Weeding out class methods avoids unnecessary deprecations such Chef::Resource
+ # defining a `name` property when there's an already-existing `name` method
+ # for a Module.
+ return unless declared_in.instance_methods.include?(name)
+
+ # Only emit deprecations for some well-known classes. This will still
+ # allow more advanced users to subclass their own custom resources and
+ # override their own properties.
+ return unless [ Object, BasicObject, Kernel, Chef::Resource ].include?(declared_in.instance_method(name).owner)
+
+ # Allow top-level Chef::Resource proprties, such as `name`, to be overridden.
+ # As of this writing, `name` is the only Chef::Resource property created with the
+ # `property` definition, but this will allow for future properties to be extended
+ # as needed.
+ return if Chef::Resource.properties.keys.include?(name)
+
+ # Emit the deprecation.
+ resource_name = declared_in.respond_to?(:resource_name) ? declared_in.resource_name : declared_in
+ Chef.deprecated(:property_name_collision, "Property `#{name}` of resource `#{resource_name}` overwrites an existing method. " \
+ "Please use a different property name. This will raise an exception in Chef 13.")
+ end
+
def exec_in_resource(resource, proc, *args)
if resource
if proc.arity > args.size
@@ -677,9 +708,9 @@ class Chef
# warn and return the (possibly coerced) value to the user.
if is_default
if value.nil?
- Chef.log_deprecation("Default value nil is invalid for property #{self}. Possible fixes: 1. Remove 'default: nil' if nil means 'undefined'. 2. Set a valid default value if there is a reasonable one. 3. Allow nil as a valid value of your property (for example, 'property #{name.inspect}, [ String, nil ], default: nil'). Error: #{$!}")
+ Chef.deprecated(:custom_resource, "Default value nil is invalid for property #{self}. Possible fixes: 1. Remove 'default: nil' if nil means 'undefined'. 2. Set a valid default value if there is a reasonable one. 3. Allow nil as a valid value of your property (for example, 'property #{name.inspect}, [ String, nil ], default: nil'). Error: #{$!}")
else
- Chef.log_deprecation("Default value #{value.inspect} is invalid for property #{self}. In Chef 13 this will become an error: #{$!}.")
+ Chef.deprecated(:custom_resource, "Default value #{value.inspect} is invalid for property #{self}. In Chef 13 this will become an error: #{$!}.")
end
else
raise
diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb
index 7cfddba0cb..40c31e4371 100644
--- a/lib/chef/provider.rb
+++ b/lib/chef/provider.rb
@@ -205,7 +205,7 @@ class Chef
specified_properties = properties.select { |property| new_resource.property_is_set?(property) }
modified = specified_properties.select { |p| new_resource.send(p) != current_resource.send(p) }
if modified.empty?
- properties_str = if sensitive
+ properties_str = if new_resource.sensitive
specified_properties.join(", ")
else
specified_properties.map { |p| "#{p}=#{new_resource.send(p).inspect}" }.join(", ")
@@ -217,7 +217,7 @@ class Chef
# Print the pretty green text and run the block
property_size = modified.map { |p| p.size }.max
modified.map! do |p|
- properties_str = if sensitive
+ properties_str = if new_resource.sensitive
"(suppressed sensitive property)"
else
"#{new_resource.send(p).inspect} (was #{current_resource.send(p).inspect})"
@@ -232,7 +232,7 @@ class Chef
property_size = properties.map { |p| p.size }.max
created = properties.map do |property|
default = " (default value)" unless new_resource.property_is_set?(property)
- properties_str = if sensitive
+ properties_str = if new_resource.sensitive
"(suppressed sensitive property)"
else
new_resource.send(property).inspect
@@ -424,7 +424,7 @@ class Chef
module DeprecatedLWRPClass
def const_missing(class_name)
if Chef::Provider.deprecated_constants[class_name.to_sym]
- Chef.log_deprecation("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.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}"
diff --git a/lib/chef/provider/deploy/revision.rb b/lib/chef/provider/deploy/revision.rb
index f61e439486..06138e4f05 100644
--- a/lib/chef/provider/deploy/revision.rb
+++ b/lib/chef/provider/deploy/revision.rb
@@ -91,11 +91,9 @@ class Chef
end
def load_cache
- begin
- Chef::JSONCompat.parse(Chef::FileCache.load("revision-deploys/#{new_resource.name}"))
- rescue Chef::Exceptions::FileNotFound
- sorted_releases_from_filesystem
- end
+ Chef::JSONCompat.parse(Chef::FileCache.load("revision-deploys/#{new_resource.name}"))
+ rescue Chef::Exceptions::FileNotFound
+ sorted_releases_from_filesystem
end
def save_cache(cache)
diff --git a/lib/chef/provider/directory.rb b/lib/chef/provider/directory.rb
index 619ab5d8b6..1cacc3fcb9 100644
--- a/lib/chef/provider/directory.rb
+++ b/lib/chef/provider/directory.rb
@@ -138,7 +138,7 @@ class Chef
end
do_acl_changes
do_selinux(true)
- load_resource_attributes_from_file(@new_resource)
+ load_resource_attributes_from_file(@new_resource) unless Chef::Config[:why_run]
end
def action_delete
diff --git a/lib/chef/provider/dsc_resource.rb b/lib/chef/provider/dsc_resource.rb
index 0f25065925..026d2ef104 100644
--- a/lib/chef/provider/dsc_resource.rb
+++ b/lib/chef/provider/dsc_resource.rb
@@ -29,6 +29,7 @@ class Chef
super
@new_resource = new_resource
@module_name = new_resource.module_name
+ @module_version = new_resource.module_version
@reboot_resource = nil
end
@@ -65,6 +66,13 @@ class Chef
a.whyrun err + ["Assuming a previous resource sets the RefreshMode."]
a.block_action!
end
+ requirements.assert(:run) do |a|
+ a.assertion { module_usage_valid? }
+ err = ["module_name must be supplied along with module_version."]
+ a.failure_message Chef::Exceptions::DSCModuleNameMissing,
+ err
+ a.block_action!
+ end
end
protected
@@ -92,6 +100,10 @@ class Chef
Chef::Platform.supports_refresh_mode_enabled?(node)
end
+ def module_usage_valid?
+ !(!@module_name && @module_version)
+ end
+
def generate_description
@converge_description
end
@@ -148,10 +160,14 @@ class Chef
end
end
+ def module_info_object
+ @module_version.nil? ? module_name : "@{ModuleName='#{module_name}';ModuleVersion='#{@module_version}'}"
+ end
+
def invoke_resource(method, output_format = :object)
properties = translate_type(@new_resource.properties)
switches = "-Method #{method} -Name #{@new_resource.resource}"\
- " -Property #{properties} -Module #{module_name} -Verbose"
+ " -Property #{properties} -Module #{module_info_object} -Verbose"
cmdlet = Chef::Util::Powershell::Cmdlet.new(
node,
"Invoke-DscResource #{switches}",
diff --git a/lib/chef/provider/env/windows.rb b/lib/chef/provider/env/windows.rb
index a68c8276e0..e25cab31d2 100644
--- a/lib/chef/provider/env/windows.rb
+++ b/lib/chef/provider/env/windows.rb
@@ -36,7 +36,7 @@ class Chef
obj.variablevalue = @new_resource.value
obj.put_
value = @new_resource.value
- value = expand_path(value) if @new_resource.key_name.casecmp("PATH").zero?
+ value = expand_path(value) if @new_resource.key_name.casecmp("PATH") == 0
ENV[@new_resource.key_name] = value
broadcast_env_change
end
@@ -54,7 +54,7 @@ class Chef
def env_value(key_name)
obj = env_obj(key_name)
- return obj ? obj.variablevalue : ENV[key_name]
+ obj ? obj.variablevalue : ENV[key_name]
end
def env_obj(key_name)
diff --git a/lib/chef/provider/execute.rb b/lib/chef/provider/execute.rb
index 45f0ad5488..a605d9f7ec 100644
--- a/lib/chef/provider/execute.rb
+++ b/lib/chef/provider/execute.rb
@@ -27,7 +27,7 @@ class Chef
provides :execute
- def_delegators :@new_resource, :command, :returns, :environment, :user, :group, :cwd, :umask, :creates
+ def_delegators :@new_resource, :command, :returns, :environment, :user, :domain, :password, :group, :cwd, :umask, :creates
def load_current_resource
current_resource = Chef::Resource::Execute.new(new_resource.name)
@@ -39,7 +39,7 @@ class Chef
end
def define_resource_requirements
- # @todo: this should change to raise in some appropriate major version bump.
+ # @todo: this should change to raise in some appropriate major version bump.
if creates && creates_relative? && !cwd
Chef::Log.warn "Providing a relative path for the creates attribute without the cwd is deprecated and will be changed to fail in the future (CHEF-3819)"
end
@@ -92,6 +92,8 @@ class Chef
opts[:returns] = returns if returns
opts[:environment] = environment if environment
opts[:user] = user if user
+ opts[:domain] = domain if domain
+ opts[:password] = password if password
opts[:group] = group if group
opts[:cwd] = cwd if cwd
opts[:umask] = umask if umask
@@ -120,6 +122,7 @@ class Chef
( cwd && creates_relative? ) ? ::File.join(cwd, creates) : creates
))
end
+
end
end
end
diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb
index 84bb4d1c94..d87004d543 100644
--- a/lib/chef/provider/file.rb
+++ b/lib/chef/provider/file.rb
@@ -154,7 +154,7 @@ class Chef
do_contents_changes
do_acl_changes
do_selinux
- load_resource_attributes_from_file(@new_resource)
+ load_resource_attributes_from_file(@new_resource) unless Chef::Config[:why_run]
end
def action_create_if_missing
@@ -312,11 +312,9 @@ class Chef
# like real_file? that follows (sane) symlinks
def symlink_to_real_file?(path)
- begin
- real_file?(::File.realpath(path))
- rescue Errno::ELOOP, Errno::ENOENT
- false
- end
+ real_file?(::File.realpath(path))
+ rescue Errno::ELOOP, Errno::ENOENT
+ false
end
# Similar to File.exist?, but also returns true in the case that the
diff --git a/lib/chef/provider/git.rb b/lib/chef/provider/git.rb
index d051bb1d92..a5c5e0d267 100644
--- a/lib/chef/provider/git.rb
+++ b/lib/chef/provider/git.rb
@@ -65,7 +65,7 @@ class Chef
# this can't be recovered from in why-run mode, because nothing that
# we do in the course of a run is likely to create a valid target_revision
# if we can't resolve it up front.
- a.assertion { target_revision != nil }
+ a.assertion { !target_revision.nil? }
a.failure_message Chef::Exceptions::UnresolvableGitReference,
"Unable to parse SHA reference for '#{@new_resource.revision}' in repository '#{@new_resource.repository}'. " +
"Verify your (case-sensitive) repository URL and revision.\n" +
diff --git a/lib/chef/provider/group.rb b/lib/chef/provider/group.rb
index 8936bd2031..6751052ae4 100644
--- a/lib/chef/provider/group.rb
+++ b/lib/chef/provider/group.rb
@@ -39,38 +39,38 @@ class Chef
end
def load_current_resource
- @current_resource = Chef::Resource::Group.new(@new_resource.name)
- @current_resource.group_name(@new_resource.group_name)
+ @current_resource = Chef::Resource::Group.new(new_resource.name)
+ current_resource.group_name(new_resource.group_name)
group_info = nil
begin
- group_info = Etc.getgrnam(@new_resource.group_name)
- rescue ArgumentError => e
+ group_info = Etc.getgrnam(new_resource.group_name)
+ rescue ArgumentError
@group_exists = false
- Chef::Log.debug("#{@new_resource} group does not exist")
+ Chef::Log.debug("#{new_resource} group does not exist")
end
if group_info
- @new_resource.gid(group_info.gid) unless @new_resource.gid
- @current_resource.gid(group_info.gid)
- @current_resource.members(group_info.mem)
+ new_resource.gid(group_info.gid) unless new_resource.gid
+ current_resource.gid(group_info.gid)
+ current_resource.members(group_info.mem)
end
- @current_resource
+ current_resource
end
def define_resource_requirements
requirements.assert(:modify) do |a|
a.assertion { @group_exists }
- a.failure_message(Chef::Exceptions::Group, "Cannot modify #{@new_resource} - group does not exist!")
- a.whyrun("Group #{@new_resource} does not exist. Unless it would have been created earlier in this run, this attempt to modify it would fail.")
+ a.failure_message(Chef::Exceptions::Group, "Cannot modify #{new_resource} - group does not exist!")
+ a.whyrun("Group #{new_resource} does not exist. Unless it would have been created earlier in this run, this attempt to modify it would fail.")
end
requirements.assert(:all_actions) do |a|
# Make sure that the resource doesn't contain any common
# user names in the members and exclude_members properties.
- if !@new_resource.members.nil? && !@new_resource.excluded_members.nil?
- common_members = @new_resource.members & @new_resource.excluded_members
+ if !new_resource.members.nil? && !new_resource.excluded_members.nil?
+ common_members = new_resource.members & new_resource.excluded_members
a.assertion { common_members.empty? }
a.failure_message(Chef::Exceptions::ConflictingMembersInGroup, "Attempting to both add and remove users from a group: '#{common_members.join(', ')}'")
# No why-run alternative
@@ -86,41 +86,39 @@ class Chef
# <false>:: If a change is not required
def compare_group
@change_desc = [ ]
- if @new_resource.gid.to_s != @current_resource.gid.to_s
- @change_desc << "change gid #{@current_resource.gid} to #{@new_resource.gid}"
+ if new_resource.gid.to_s != current_resource.gid.to_s
+ @change_desc << "change gid #{current_resource.gid} to #{new_resource.gid}"
end
- if @new_resource.append
+ if new_resource.append
missing_members = []
- @new_resource.members.each do |member|
+ new_resource.members.each do |member|
next if has_current_group_member?(member)
validate_member!(member)
missing_members << member
end
- if missing_members.length > 0
- @change_desc << "add missing member(s): #{missing_members.join(", ")}"
+ unless missing_members.empty?
+ @change_desc << "add missing member(s): #{missing_members.join(', ')}"
end
members_to_be_removed = []
- @new_resource.excluded_members.each do |member|
+ new_resource.excluded_members.each do |member|
if has_current_group_member?(member)
members_to_be_removed << member
end
end
- if members_to_be_removed.length > 0
- @change_desc << "remove existing member(s): #{members_to_be_removed.join(", ")}"
- end
- else
- if @new_resource.members != @current_resource.members
- @change_desc << "replace group members with new list of members"
+ unless members_to_be_removed.empty?
+ @change_desc << "remove existing member(s): #{members_to_be_removed.join(', ')}"
end
+ elsif new_resource.members != current_resource.members
+ @change_desc << "replace group members with new list of members"
end
!@change_desc.empty?
end
def has_current_group_member?(member)
- @current_resource.members.include?(member)
+ current_resource.members.include?(member)
end
def validate_member!(member)
@@ -132,44 +130,41 @@ class Chef
def action_create
case @group_exists
when false
- converge_by("create group #{@new_resource.group_name}") do
+ converge_by("create group #{new_resource.group_name}") do
create_group
- Chef::Log.info("#{@new_resource} created")
+ Chef::Log.info("#{new_resource} created")
end
else
if compare_group
- converge_by(["alter group #{@new_resource.group_name}"] + change_desc) do
+ converge_by(["alter group #{new_resource.group_name}"] + change_desc) do
manage_group
- Chef::Log.info("#{@new_resource} altered")
+ Chef::Log.info("#{new_resource} altered")
end
end
end
end
def action_remove
- if @group_exists
- converge_by("remove group #{@new_resource.group_name}") do
- remove_group
- Chef::Log.info("#{@new_resource} removed")
- end
+ return unless @group_exists
+ converge_by("remove group #{new_resource.group_name}") do
+ remove_group
+ Chef::Log.info("#{new_resource} removed")
end
end
def action_manage
- if @group_exists && compare_group
- converge_by(["manage group #{@new_resource.group_name}"] + change_desc) do
- manage_group
- Chef::Log.info("#{@new_resource} managed")
- end
+ return unless @group_exists && compare_group
+ converge_by(["manage group #{new_resource.group_name}"] + change_desc) do
+ manage_group
+ Chef::Log.info("#{new_resource} managed")
end
end
def action_modify
- if compare_group
- converge_by(["modify group #{@new_resource.group_name}"] + change_desc) do
- manage_group
- Chef::Log.info("#{@new_resource} modified")
- end
+ return unless compare_group
+ converge_by(["modify group #{new_resource.group_name}"] + change_desc) do
+ manage_group
+ Chef::Log.info("#{new_resource} modified")
end
end
diff --git a/lib/chef/provider/group/aix.rb b/lib/chef/provider/group/aix.rb
index 4a02d5ef8c..2db6dc32a7 100644
--- a/lib/chef/provider/group/aix.rb
+++ b/lib/chef/provider/group/aix.rb
@@ -17,7 +17,6 @@
#
require "chef/provider/group/groupadd"
-require "chef/mixin/shell_out"
class Chef
class Provider
@@ -33,48 +32,42 @@ class Chef
end
def create_group
- command = "mkgroup"
- command << set_options << " #{@new_resource.group_name}"
- run_command(:command => command)
+ shell_out_compact!("mkgroup", set_options, new_resource.group_name)
modify_group_members
end
def manage_group
- command = "chgroup"
options = set_options
- #Usage: chgroup [-R load_module] "attr=value" ... group
if options.size > 0
- command << options << " #{@new_resource.group_name}"
- run_command(:command => command)
+ shell_out_compact!("chgroup", options, new_resource.group_name)
end
modify_group_members
end
def remove_group
- run_command(:command => "rmgroup #{@new_resource.group_name}")
+ shell_out_compact!("rmgroup", new_resource.group_name)
end
def add_member(member)
- shell_out!("chgrpmem -m + #{member} #{@new_resource.group_name}")
+ shell_out_compact!("chgrpmem", "-m", "+", member, new_resource.group_name)
end
def set_members(members)
return if members.empty?
- shell_out!("chgrpmem -m = #{members.join(',')} #{@new_resource.group_name}")
+ shell_out_compact!("chgrpmem", "-m", "=", members.join(","), new_resource.group_name)
end
def remove_member(member)
- shell_out!("chgrpmem -m - #{member} #{@new_resource.group_name}")
+ shell_out_compact!("chgrpmem", "-m", "-", member, new_resource.group_name)
end
def set_options
- opts = ""
- { :gid => "id" }.sort { |a, b| a[0] <=> b[0] }.each do |field, option|
- if @current_resource.send(field) != @new_resource.send(field)
- if @new_resource.send(field)
- Chef::Log.debug("#{@new_resource} setting #{field} to #{@new_resource.send(field)}")
- opts << " '#{option}=#{@new_resource.send(field)}'"
- end
+ opts = []
+ { gid: "id" }.sort { |a, b| a[0] <=> b[0] }.each do |field, option|
+ next unless current_resource.send(field) != new_resource.send(field)
+ if new_resource.send(field)
+ Chef::Log.debug("#{new_resource} setting #{field} to #{new_resource.send(field)}")
+ opts << "#{option}=#{new_resource.send(field)}"
end
end
opts
diff --git a/lib/chef/provider/group/dscl.rb b/lib/chef/provider/group/dscl.rb
index 00b4ce2b93..71e42b36ba 100644
--- a/lib/chef/provider/group/dscl.rb
+++ b/lib/chef/provider/group/dscl.rb
@@ -24,12 +24,15 @@ class Chef
provides :group, os: "darwin"
def dscl(*args)
- host = "."
- stdout_result = ""; stderr_result = ""; cmd = "dscl #{host} -#{args.join(' ')}"
- status = shell_out(cmd)
+ argdup = args.dup
+ cmd = argdup.shift
+ shellcmd = [ "dscl", ".", "-#{cmd}", argdup ]
+ status = shell_out_compact(shellcmd)
+ stdout_result = ""
+ stderr_result = ""
status.stdout.each_line { |line| stdout_result << line }
status.stderr.each_line { |line| stderr_result << line }
- return [cmd, status, stdout_result, stderr_result]
+ [shellcmd.flatten.compact.join(" "), status, stdout_result, stderr_result]
end
def safe_dscl(*args)
@@ -37,18 +40,18 @@ class Chef
return "" if ( args.first =~ /^delete/ ) && ( result[1].exitstatus != 0 )
raise(Chef::Exceptions::Group, "dscl error: #{result.inspect}") unless result[1].exitstatus == 0
raise(Chef::Exceptions::Group, "dscl error: #{result.inspect}") if result[2] =~ /No such key: /
- return result[2]
+ result[2]
end
def load_current_resource
- @current_resource = Chef::Resource::Group.new(@new_resource.name)
- @current_resource.group_name(@new_resource.group_name)
+ @current_resource = Chef::Resource::Group.new(new_resource.name)
+ current_resource.group_name(new_resource.group_name)
group_info = nil
begin
- group_info = safe_dscl("read /Groups/#{@new_resource.group_name}")
+ group_info = safe_dscl("read", "/Groups/#{new_resource.group_name}")
rescue Chef::Exceptions::Group
@group_exists = false
- Chef::Log.debug("#{@new_resource} group does not exist")
+ Chef::Log.debug("#{new_resource} group does not exist")
end
if group_info
@@ -57,21 +60,21 @@ class Chef
val.strip! if val
case key.downcase
when "primarygroupid"
- @new_resource.gid(val) unless @new_resource.gid
- @current_resource.gid(val)
+ new_resource.gid(val) unless new_resource.gid
+ current_resource.gid(val)
when "groupmembership"
- @current_resource.members(val.split(" "))
+ current_resource.members(val.split(" "))
end
end
end
- @current_resource
+ current_resource
end
# get a free GID greater than 200
def get_free_gid(search_limit = 1000)
gid = nil; next_gid_guess = 200
- groups_gids = safe_dscl("list /Groups gid")
+ groups_gids = safe_dscl("list", "/Groups", "gid")
while next_gid_guess < search_limit + 200
if groups_gids =~ Regexp.new("#{Regexp.escape(next_gid_guess.to_s)}\n")
next_gid_guess += 1
@@ -80,51 +83,51 @@ class Chef
break
end
end
- return gid || raise("gid not found. Exhausted. Searched #{search_limit} times")
+ gid || raise("gid not found. Exhausted. Searched #{search_limit} times")
end
def gid_used?(gid)
return false unless gid
- groups_gids = safe_dscl("list /Groups gid")
- !! ( groups_gids =~ Regexp.new("#{Regexp.escape(gid.to_s)}\n") )
+ groups_gids = safe_dscl("list", "/Groups", "gid")
+ !!( groups_gids =~ Regexp.new("#{Regexp.escape(gid.to_s)}\n") )
end
def set_gid
- @new_resource.gid(get_free_gid) if [nil, ""].include? @new_resource.gid
- raise(Chef::Exceptions::Group, "gid is already in use") if gid_used?(@new_resource.gid)
- safe_dscl("create /Groups/#{@new_resource.group_name} PrimaryGroupID #{@new_resource.gid}")
+ new_resource.gid(get_free_gid) if [nil, ""].include? new_resource.gid
+ raise(Chef::Exceptions::Group, "gid is already in use") if gid_used?(new_resource.gid)
+ safe_dscl("create", "/Groups/#{new_resource.group_name}", "PrimaryGroupID", new_resource.gid)
end
def set_members
# First reset the memberships if the append is not set
- unless @new_resource.append
- Chef::Log.debug("#{@new_resource} removing group members #{@current_resource.members.join(' ')}") unless @current_resource.members.empty?
- safe_dscl("create /Groups/#{@new_resource.group_name} GroupMembers ''") # clear guid list
- safe_dscl("create /Groups/#{@new_resource.group_name} GroupMembership ''") # clear user list
- @current_resource.members([ ])
+ unless new_resource.append
+ Chef::Log.debug("#{new_resource} removing group members #{current_resource.members.join(' ')}") unless current_resource.members.empty?
+ safe_dscl("create", "/Groups/#{new_resource.group_name}", "GroupMembers", "") # clear guid list
+ safe_dscl("create", "/Groups/#{new_resource.group_name}", "GroupMembership", "") # clear user list
+ current_resource.members([ ])
end
# Add any members that need to be added
- if @new_resource.members && !@new_resource.members.empty?
+ if new_resource.members && !new_resource.members.empty?
members_to_be_added = [ ]
- @new_resource.members.each do |member|
- members_to_be_added << member if !@current_resource.members.include?(member)
+ new_resource.members.each do |member|
+ members_to_be_added << member unless current_resource.members.include?(member)
end
unless members_to_be_added.empty?
- Chef::Log.debug("#{@new_resource} setting group members #{members_to_be_added.join(', ')}")
- safe_dscl("append /Groups/#{@new_resource.group_name} GroupMembership #{members_to_be_added.join(' ')}")
+ Chef::Log.debug("#{new_resource} setting group members #{members_to_be_added.join(', ')}")
+ safe_dscl("append", "/Groups/#{new_resource.group_name}", "GroupMembership", *members_to_be_added)
end
end
# Remove any members that need to be removed
- if @new_resource.excluded_members && !@new_resource.excluded_members.empty?
+ if new_resource.excluded_members && !new_resource.excluded_members.empty?
members_to_be_removed = [ ]
- @new_resource.excluded_members.each do |member|
- members_to_be_removed << member if @current_resource.members.include?(member)
+ new_resource.excluded_members.each do |member|
+ members_to_be_removed << member if current_resource.members.include?(member)
end
unless members_to_be_removed.empty?
- Chef::Log.debug("#{@new_resource} removing group members #{members_to_be_removed.join(', ')}")
- safe_dscl("delete /Groups/#{@new_resource.group_name} GroupMembership #{members_to_be_removed.join(' ')}")
+ Chef::Log.debug("#{new_resource} removing group members #{members_to_be_removed.join(', ')}")
+ safe_dscl("delete", "/Groups/#{new_resource.group_name}", "GroupMembership", *members_to_be_removed)
end
end
end
@@ -132,8 +135,8 @@ class Chef
def define_resource_requirements
super
requirements.assert(:all_actions) do |a|
- a.assertion { ::File.exists?("/usr/bin/dscl") }
- a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/bin/dscl for #{@new_resource.name}"
+ a.assertion { ::File.exist?("/usr/bin/dscl") }
+ a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/bin/dscl for #{new_resource.name}"
# No whyrun alternative: this component should be available in the base install of any given system that uses it
end
end
@@ -145,24 +148,24 @@ class Chef
end
def manage_group
- if @new_resource.group_name && (@current_resource.group_name != @new_resource.group_name)
+ if new_resource.group_name && (current_resource.group_name != new_resource.group_name)
dscl_create_group
end
- if @new_resource.gid && (@current_resource.gid != @new_resource.gid)
+ if new_resource.gid && (current_resource.gid != new_resource.gid)
set_gid
end
- if @new_resource.members || @new_resource.excluded_members
+ if new_resource.members || new_resource.excluded_members
set_members
end
end
def dscl_create_group
- safe_dscl("create /Groups/#{@new_resource.group_name}")
- safe_dscl("create /Groups/#{@new_resource.group_name} Password '*'")
+ safe_dscl("create", "/Groups/#{new_resource.group_name}")
+ safe_dscl("create", "/Groups/#{new_resource.group_name}", "Password", "*")
end
def remove_group
- safe_dscl("delete /Groups/#{@new_resource.group_name}")
+ safe_dscl("delete", "/Groups/#{new_resource.group_name}")
end
end
end
diff --git a/lib/chef/provider/group/gpasswd.rb b/lib/chef/provider/group/gpasswd.rb
index dcf526b211..d8aff10d5b 100644
--- a/lib/chef/provider/group/gpasswd.rb
+++ b/lib/chef/provider/group/gpasswd.rb
@@ -31,26 +31,26 @@ class Chef
def define_resource_requirements
super
requirements.assert(:all_actions) do |a|
- a.assertion { ::File.exists?("/usr/bin/gpasswd") }
- a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/bin/gpasswd for #{@new_resource}"
+ a.assertion { ::File.exist?("/usr/bin/gpasswd") }
+ a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/bin/gpasswd for #{new_resource}"
# No whyrun alternative: this component should be available in the base install of any given system that uses it
end
end
def set_members(members)
- unless members.empty?
- shell_out!("gpasswd -M #{members.join(',')} #{@new_resource.group_name}")
+ if members.empty?
+ shell_out_compact!("gpasswd", "-M", "", new_resource.group_name)
else
- shell_out!("gpasswd -M \"\" #{@new_resource.group_name}")
+ shell_out_compact!("gpasswd", "-M", members.join(","), new_resource.group_name)
end
end
def add_member(member)
- shell_out!("gpasswd -a #{member} #{@new_resource.group_name}")
+ shell_out_compact!("gpasswd", "-a", member, new_resource.group_name)
end
def remove_member(member)
- shell_out!("gpasswd -d #{member} #{@new_resource.group_name}")
+ shell_out_compact!("gpasswd", "-d", member, new_resource.group_name)
end
end
end
diff --git a/lib/chef/provider/group/groupadd.rb b/lib/chef/provider/group/groupadd.rb
index 162875f9f1..f73c3b3be9 100644
--- a/lib/chef/provider/group/groupadd.rb
+++ b/lib/chef/provider/group/groupadd.rb
@@ -35,8 +35,8 @@ class Chef
super
required_binaries.each do |required_binary|
requirements.assert(:all_actions) do |a|
- a.assertion { ::File.exists?(required_binary) }
- a.failure_message Chef::Exceptions::Group, "Could not find binary #{required_binary} for #{@new_resource}"
+ a.assertion { ::File.exist?(required_binary) }
+ a.failure_message Chef::Exceptions::Group, "Could not find binary #{required_binary} for #{new_resource}"
# No whyrun alternative: this component should be available in the base install of any given system that uses it
end
end
@@ -44,54 +44,49 @@ class Chef
# Create the group
def create_group
- command = "groupadd"
- command << set_options
- command << groupadd_options
- run_command(:command => command)
+ shell_out_compact!("groupadd", set_options, groupadd_options)
modify_group_members
end
# Manage the group when it already exists
def manage_group
- command = "groupmod"
- command << set_options
- run_command(:command => command)
+ shell_out_compact!("groupmod", set_options)
modify_group_members
end
# Remove the group
def remove_group
- run_command(:command => "groupdel #{@new_resource.group_name}")
+ shell_out_compact!("groupdel", new_resource.group_name)
end
def modify_group_members
- if @new_resource.append
- if @new_resource.members && !@new_resource.members.empty?
+ if new_resource.append
+ if new_resource.members && !new_resource.members.empty?
members_to_be_added = [ ]
- @new_resource.members.each do |member|
- members_to_be_added << member if !@current_resource.members.include?(member)
+ new_resource.members.each do |member|
+ members_to_be_added << member unless current_resource.members.include?(member)
end
members_to_be_added.each do |member|
- Chef::Log.debug("#{@new_resource} appending member #{member} to group #{@new_resource.group_name}")
+ Chef::Log.debug("#{new_resource} appending member #{member} to group #{new_resource.group_name}")
add_member(member)
end
end
- if @new_resource.excluded_members && !@new_resource.excluded_members.empty?
+ if new_resource.excluded_members && !new_resource.excluded_members.empty?
members_to_be_removed = [ ]
- @new_resource.excluded_members.each do |member|
- members_to_be_removed << member if @current_resource.members.include?(member)
+ new_resource.excluded_members.each do |member|
+ members_to_be_removed << member if current_resource.members.include?(member)
end
members_to_be_removed.each do |member|
- Chef::Log.debug("#{@new_resource} removing member #{member} from group #{@new_resource.group_name}")
+ Chef::Log.debug("#{new_resource} removing member #{member} from group #{new_resource.group_name}")
remove_member(member)
end
end
else
- members_description = @new_resource.members.empty? ? "none" : @new_resource.members.join(", ")
- Chef::Log.debug("#{@new_resource} setting group members to: #{members_description}")
- set_members(@new_resource.members)
+ members_description = new_resource.members.empty? ? "none" : new_resource.members.join(", ")
+ Chef::Log.debug("#{new_resource} setting group members to: #{members_description}")
+ set_members(new_resource.members)
end
end
@@ -112,23 +107,23 @@ class Chef
# ==== Returns
# <string>:: A string containing the option and then the quoted value
def set_options
- opts = ""
- { :gid => "-g" }.sort { |a, b| a[0] <=> b[0] }.each do |field, option|
- if @current_resource.send(field) != @new_resource.send(field)
- if @new_resource.send(field)
- opts << " #{option} '#{@new_resource.send(field)}'"
- Chef::Log.debug("#{@new_resource} set #{field} to #{@new_resource.send(field)}")
- end
- end
+ opts = []
+ { gid: "-g" }.sort { |a, b| a[0] <=> b[0] }.each do |field, option|
+ next unless current_resource.send(field) != new_resource.send(field)
+ next unless new_resource.send(field)
+ opts << option
+ opts << new_resource.send(field)
+ Chef::Log.debug("#{new_resource} set #{field} to #{new_resource.send(field)}")
end
- opts << " #{@new_resource.group_name}"
+ opts << new_resource.group_name
+ opts
end
def groupadd_options
- opts = ""
+ opts = []
# Solaris doesn't support system groups.
- opts << " -r" if @new_resource.system && !node.platform?("solaris2")
- opts << " -o" if @new_resource.non_unique
+ opts << "-r" if new_resource.system && !node.platform?("solaris2")
+ opts << "-o" if new_resource.non_unique
opts
end
diff --git a/lib/chef/provider/group/groupmod.rb b/lib/chef/provider/group/groupmod.rb
index 295d3b3425..01581e4863 100644
--- a/lib/chef/provider/group/groupmod.rb
+++ b/lib/chef/provider/group/groupmod.rb
@@ -26,28 +26,26 @@ class Chef
def load_current_resource
super
%w{group user}.each do |binary|
- raise Chef::Exceptions::Group, "Could not find binary /usr/sbin/#{binary} for #{@new_resource}" unless ::File.exists?("/usr/sbin/#{binary}")
+ raise Chef::Exceptions::Group, "Could not find binary /usr/sbin/#{binary} for #{new_resource}" unless ::File.exist?("/usr/sbin/#{binary}")
end
end
# Create the group
def create_group
- command = "group add"
- command << set_options
- shell_out!(command)
+ shell_out_compact!("group", "add", set_options)
- add_group_members(@new_resource.members)
+ add_group_members(new_resource.members)
end
# Manage the group when it already exists
def manage_group
- if @new_resource.append
+ if new_resource.append
members_to_be_added = [ ]
- if @new_resource.excluded_members && !@new_resource.excluded_members.empty?
+ if new_resource.excluded_members && !new_resource.excluded_members.empty?
# First find out if any member needs to be removed
members_to_be_removed = [ ]
- @new_resource.excluded_members.each do |member|
- members_to_be_removed << member if @current_resource.members.include?(member)
+ new_resource.excluded_members.each do |member|
+ members_to_be_removed << member if current_resource.members.include?(member)
end
unless members_to_be_removed.empty?
@@ -56,39 +54,39 @@ class Chef
# Capture the members we need to add in
# members_to_be_added to be added later on.
- @current_resource.members.each do |member|
+ current_resource.members.each do |member|
members_to_be_added << member unless members_to_be_removed.include?(member)
end
end
end
- if @new_resource.members && !@new_resource.members.empty?
- @new_resource.members.each do |member|
- members_to_be_added << member if !@current_resource.members.include?(member)
+ if new_resource.members && !new_resource.members.empty?
+ new_resource.members.each do |member|
+ members_to_be_added << member unless current_resource.members.include?(member)
end
end
- Chef::Log.debug("#{@new_resource} not changing group members, the group has no members to add") if members_to_be_added.empty?
+ Chef::Log.debug("#{new_resource} not changing group members, the group has no members to add") if members_to_be_added.empty?
add_group_members(members_to_be_added)
else
# We are resetting the members of a group so use the same trick
reset_group_membership
- Chef::Log.debug("#{@new_resource} setting group members to: none") if @new_resource.members.empty?
- add_group_members(@new_resource.members)
+ Chef::Log.debug("#{new_resource} setting group members to: none") if new_resource.members.empty?
+ add_group_members(new_resource.members)
end
end
# Remove the group
def remove_group
- shell_out!("group del #{@new_resource.group_name}")
+ shell_out_compact!("group", "del", new_resource.group_name)
end
# Adds a list of usernames to the group using `user mod`
def add_group_members(members)
- Chef::Log.debug("#{@new_resource} adding members #{members.join(', ')}") if !members.empty?
+ Chef::Log.debug("#{new_resource} adding members #{members.join(', ')}") unless members.empty?
members.each do |user|
- shell_out!("user mod -G #{@new_resource.group_name} #{user}")
+ shell_out_compact!("user", "mod", "-G", new_resource.group_name, user)
end
end
@@ -96,15 +94,11 @@ class Chef
# "<name>_bak", create a new group with the same GID and
# "<name>", then set correct members on that group
def reset_group_membership
- rename = "group mod -n #{@new_resource.group_name}_bak #{@new_resource.group_name}"
- shell_out!(rename)
+ shell_out_compact!("group", "mod", "-n", "#{new_resource.group_name}_bak", new_resource.group_name)
- create = "group add"
- create << set_options(:overwrite_gid => true)
- shell_out!(create)
+ shell_out_compact!("group", "add", set_options(overwrite_gid: true))
- remove = "group del #{@new_resource.group_name}_bak"
- shell_out!(remove)
+ shell_out_compact!("group", "del", "#{new_resource.group_name}_bak")
end
# Little bit of magic as per Adam's useradd provider to pull and assign the command line flags
@@ -112,14 +106,15 @@ class Chef
# ==== Returns
# <string>:: A string containing the option and then the quoted value
def set_options(overwrite_gid = false)
- opts = ""
- if overwrite_gid || @new_resource.gid && (@current_resource.gid != @new_resource.gid)
- opts << " -g '#{@new_resource.gid}'"
+ opts = []
+ if overwrite_gid || new_resource.gid && (current_resource.gid != new_resource.gid)
+ opts << "-g"
+ opts << new_resource.gid
end
if overwrite_gid
- opts << " -o"
+ opts << "-o"
end
- opts << " #{@new_resource.group_name}"
+ opts << new_resource.group_name
opts
end
end
diff --git a/lib/chef/provider/group/pw.rb b/lib/chef/provider/group/pw.rb
index 4fd78b6b31..115ccf3714 100644
--- a/lib/chef/provider/group/pw.rb
+++ b/lib/chef/provider/group/pw.rb
@@ -30,46 +30,42 @@ class Chef
super
requirements.assert(:all_actions) do |a|
- a.assertion { ::File.exists?("/usr/sbin/pw") }
- a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/pw for #{@new_resource}"
+ a.assertion { ::File.exist?("/usr/sbin/pw") }
+ a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/pw for #{new_resource}"
# No whyrun alternative: this component should be available in the base install of any given system that uses it
end
end
# Create the group
def create_group
- command = "pw groupadd"
- command << set_options
-
- unless @new_resource.members.empty?
+ command = [ "pw", "groupadd", set_options ]
+ unless new_resource.members.empty?
# pw group[add|mod] -M is used to set the full membership list on a
# new or existing group. Because pw groupadd does not support the -m
# and -d options used by manage_group, we treat group creation as a
# special case and use -M.
- Chef::Log.debug("#{@new_resource} setting group members: #{@new_resource.members.join(',')}")
- command += " -M #{@new_resource.members.join(',')}"
+ Chef::Log.debug("#{new_resource} setting group members: #{new_resource.members.join(',')}")
+ command += [ "-M", new_resource.members.join(",") ]
end
- run_command(:command => command)
+ shell_out_compact!(command)
end
# Manage the group when it already exists
def manage_group
- command = "pw groupmod"
- command << set_options
member_options = set_members_options
if member_options.empty?
- run_command(:command => command)
+ shell_out_compact!("pw", "groupmod", set_options)
else
member_options.each do |option|
- run_command(:command => command + option)
+ shell_out_compact!("pw", "groupmod", set_options, option)
end
end
end
# Remove the group
def remove_group
- run_command(:command => "pw groupdel #{@new_resource.group_name}")
+ shell_out_compact!("pw", "groupdel", new_resource.group_name)
end
# Little bit of magic as per Adam's useradd provider to pull and assign the command line flags
@@ -77,10 +73,11 @@ class Chef
# ==== Returns
# <string>:: A string containing the option and then the quoted value
def set_options
- opts = " #{@new_resource.group_name}"
- if @new_resource.gid && (@current_resource.gid != @new_resource.gid)
- Chef::Log.debug("#{@new_resource}: current gid (#{@current_resource.gid}) doesnt match target gid (#{@new_resource.gid}), changing it")
- opts << " -g '#{@new_resource.gid}'"
+ opts = [ new_resource.group_name ]
+ if new_resource.gid && (current_resource.gid != new_resource.gid)
+ Chef::Log.debug("#{new_resource}: current gid (#{current_resource.gid}) doesnt match target gid (#{new_resource.gid}), changing it")
+ opts << "-g"
+ opts << new_resource.gid
end
opts
end
@@ -91,26 +88,26 @@ class Chef
members_to_be_added = [ ]
members_to_be_removed = [ ]
- if @new_resource.append
+ if new_resource.append
# Append is set so we will only add members given in the
# members list and remove members given in the
# excluded_members list.
- if @new_resource.members && !@new_resource.members.empty?
- @new_resource.members.each do |member|
- members_to_be_added << member if !@current_resource.members.include?(member)
+ if new_resource.members && !new_resource.members.empty?
+ new_resource.members.each do |member|
+ members_to_be_added << member unless current_resource.members.include?(member)
end
end
- if @new_resource.excluded_members && !@new_resource.excluded_members.empty?
- @new_resource.excluded_members.each do |member|
- members_to_be_removed << member if @current_resource.members.include?(member)
+ if new_resource.excluded_members && !new_resource.excluded_members.empty?
+ new_resource.excluded_members.each do |member|
+ members_to_be_removed << member if current_resource.members.include?(member)
end
end
else
# Append is not set so we're resetting the membership of
# the group to the given members.
- members_to_be_added = @new_resource.members.dup
- @current_resource.members.each do |member|
+ members_to_be_added = new_resource.members.dup
+ current_resource.members.each do |member|
# No need to re-add a member if it's present in the new
# list of members
if members_to_be_added.include? member
@@ -122,13 +119,13 @@ class Chef
end
unless members_to_be_added.empty?
- Chef::Log.debug("#{@new_resource} adding group members: #{members_to_be_added.join(',')}")
- opts << " -m #{members_to_be_added.join(',')}"
+ Chef::Log.debug("#{new_resource} adding group members: #{members_to_be_added.join(',')}")
+ opts << [ "-m", members_to_be_added.join(",") ]
end
unless members_to_be_removed.empty?
- Chef::Log.debug("#{@new_resource} removing group members: #{members_to_be_removed.join(',')}")
- opts << " -d #{members_to_be_removed.join(',')}"
+ Chef::Log.debug("#{new_resource} removing group members: #{members_to_be_removed.join(',')}")
+ opts << [ "-d", members_to_be_removed.join(",") ]
end
opts
diff --git a/lib/chef/provider/group/suse.rb b/lib/chef/provider/group/suse.rb
index 71336f9311..0790d2c2d9 100644
--- a/lib/chef/provider/group/suse.rb
+++ b/lib/chef/provider/group/suse.rb
@@ -33,21 +33,21 @@ class Chef
def define_resource_requirements
super
requirements.assert(:all_actions) do |a|
- a.assertion { ::File.exists?("/usr/sbin/groupmod") }
- a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/groupmod for #{@new_resource.name}"
+ a.assertion { ::File.exist?("/usr/sbin/groupmod") }
+ a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/groupmod for #{new_resource.name}"
# No whyrun alternative: this component should be available in the base install of any given system that uses it
end
requirements.assert(:create, :manage, :modify) do |a|
a.assertion do
begin
- to_add(@new_resource.members).all? { |member| Etc.getpwnam(member) }
+ to_add(new_resource.members).all? { |member| Etc.getpwnam(member) }
rescue
false
end
end
- a.failure_message Chef::Exceptions::Group, "Could not add users #{to_add(@new_resource.members).join(", ")} to #{@new_resource.group_name}: one of these users does not exist"
- a.whyrun "Could not find one of these users: #{to_add(@new_resource.members).join(", ")}. Assuming it will be created by a prior step"
+ a.failure_message Chef::Exceptions::Group, "Could not add users #{to_add(new_resource.members).join(', ')} to #{new_resource.group_name}: one of these users does not exist"
+ a.whyrun "Could not find one of these users: #{to_add(new_resource.members).join(', ')}. Assuming it will be created by a prior step"
end
end
@@ -62,19 +62,19 @@ class Chef
end
def to_add(members)
- members - @current_resource.members
+ members - current_resource.members
end
def add_member(member)
- shell_out!("groupmod -A #{member} #{@new_resource.group_name}")
+ shell_out_compact!("groupmod", "-A", member, new_resource.group_name)
end
def to_remove(members)
- @current_resource.members - members
+ current_resource.members - members
end
def remove_member(member)
- shell_out!("groupmod -R #{member} #{@new_resource.group_name}")
+ shell_out_compact!("groupmod", "-R", member, new_resource.group_name)
end
end
diff --git a/lib/chef/provider/group/usermod.rb b/lib/chef/provider/group/usermod.rb
index bef4b667a2..3874f7b4de 100644
--- a/lib/chef/provider/group/usermod.rb
+++ b/lib/chef/provider/group/usermod.rb
@@ -34,19 +34,19 @@ class Chef
super
requirements.assert(:all_actions) do |a|
- a.assertion { ::File.exists?("/usr/sbin/usermod") }
- a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/usermod for #{@new_resource}"
+ a.assertion { ::File.exist?("/usr/sbin/usermod") }
+ a.failure_message Chef::Exceptions::Group, "Could not find binary /usr/sbin/usermod for #{new_resource}"
# No whyrun alternative: this component should be available in the base install of any given system that uses it
end
requirements.assert(:modify, :manage) do |a|
- a.assertion { @new_resource.members.empty? || @new_resource.append }
+ a.assertion { new_resource.members.empty? || new_resource.append }
a.failure_message Chef::Exceptions::Group, "setting group members directly is not supported by #{self}, must set append true in group"
# No whyrun alternative - this action is simply not supported.
end
requirements.assert(:all_actions) do |a|
- a.assertion { @new_resource.excluded_members.empty? }
+ a.assertion { new_resource.excluded_members.empty? }
a.failure_message Chef::Exceptions::Group, "excluded_members is not supported by #{self}"
# No whyrun alternative - this action is simply not supported.
end
@@ -57,17 +57,16 @@ class Chef
# This provider only supports adding members with
# append. Only if the action is create we will go
# ahead and add members.
- if @new_resource.action.include?(:create)
- members.each do |member|
- add_member(member)
- end
- else
+ unless new_resource.action.include?(:create)
raise Chef::Exceptions::UnsupportedAction, "Setting members directly is not supported by #{self}"
end
+ members.each do |member|
+ add_member(member)
+ end
end
def add_member(member)
- shell_out!("usermod #{append_flags} #{@new_resource.group_name} #{member}")
+ shell_out_compact!("usermod", append_flags, new_resource.group_name, member)
end
def remove_member(member)
@@ -81,7 +80,7 @@ class Chef
when "openbsd", "netbsd", "aix", "solaris2", "smartos", "omnios"
"-G"
when "solaris", "suse", "opensuse"
- "-a -G"
+ [ "-a", "-G" ]
end
end
diff --git a/lib/chef/provider/group/windows.rb b/lib/chef/provider/group/windows.rb
index 5873e42a6b..c0026bf368 100644
--- a/lib/chef/provider/group/windows.rb
+++ b/lib/chef/provider/group/windows.rb
@@ -30,26 +30,26 @@ class Chef
def initialize(new_resource, run_context)
super
- @net_group = Chef::Util::Windows::NetGroup.new(@new_resource.group_name)
+ @net_group = Chef::Util::Windows::NetGroup.new(new_resource.group_name)
end
def load_current_resource
- @current_resource = Chef::Resource::Group.new(@new_resource.name)
- @current_resource.group_name(@new_resource.group_name)
+ @current_resource = Chef::Resource::Group.new(new_resource.name)
+ current_resource.group_name(new_resource.group_name)
members = nil
begin
members = @net_group.local_get_members
- rescue => e
+ rescue
@group_exists = false
- Chef::Log.debug("#{@new_resource} group does not exist")
+ Chef::Log.debug("#{new_resource} group does not exist")
end
if members
- @current_resource.members(members)
+ current_resource.members(members)
end
- @current_resource
+ current_resource
end
def create_group
@@ -58,10 +58,10 @@ class Chef
end
def manage_group
- if @new_resource.append
+ if new_resource.append
members_to_be_added = [ ]
- @new_resource.members.each do |member|
- members_to_be_added << member if ! has_current_group_member?(member) && validate_member!(member)
+ new_resource.members.each do |member|
+ members_to_be_added << member if !has_current_group_member?(member) && validate_member!(member)
end
# local_add_members will raise ERROR_MEMBER_IN_ALIAS if a
@@ -69,19 +69,19 @@ class Chef
@net_group.local_add_members(members_to_be_added) unless members_to_be_added.empty?
members_to_be_removed = [ ]
- @new_resource.excluded_members.each do |member|
- member_sid = lookup_account_name(member)
+ new_resource.excluded_members.each do |member|
+ lookup_account_name(member)
members_to_be_removed << member if has_current_group_member?(member)
end
@net_group.local_delete_members(members_to_be_removed) unless members_to_be_removed.empty?
else
- @net_group.local_set_members(@new_resource.members)
+ @net_group.local_set_members(new_resource.members)
end
end
def has_current_group_member?(member)
member_sid = lookup_account_name(member)
- @current_resource.members.include?(member_sid)
+ current_resource.members.include?(member_sid)
end
def remove_group
@@ -97,12 +97,10 @@ class Chef
end
def lookup_account_name(account_name)
- begin
- Chef::ReservedNames::Win32::Security.lookup_account_name(locally_qualified_name(account_name))[1].to_s
- rescue Chef::Exceptions::Win32APIError
- Chef::Log.warn("SID for '#{locally_qualified_name(account_name)}' could not be found")
- ""
- end
+ Chef::ReservedNames::Win32::Security.lookup_account_name(locally_qualified_name(account_name))[1].to_s
+ rescue Chef::Exceptions::Win32APIError
+ Chef::Log.warn("SID for '#{locally_qualified_name(account_name)}' could not be found")
+ ""
end
end
diff --git a/lib/chef/provider/ifconfig.rb b/lib/chef/provider/ifconfig.rb
index 4cfb257bb9..4f32baaadb 100644
--- a/lib/chef/provider/ifconfig.rb
+++ b/lib/chef/provider/ifconfig.rb
@@ -58,7 +58,7 @@ class Chef
end
def load_current_resource
- @current_resource = Chef::Resource::Ifconfig.new(@new_resource.name)
+ @current_resource = Chef::Resource::Ifconfig.new(new_resource.name)
@ifconfig_success = true
@interfaces = {}
@@ -69,27 +69,26 @@ class Chef
@int_name = line[0..9].strip
@interfaces[@int_name] = { "hwaddr" => (line =~ /(HWaddr)/ ? ($') : "nil").strip.chomp }
else
- @interfaces[@int_name]["inet_addr"] = (line =~ /inet addr:(\S+)/ ? ($1) : "nil") if line =~ /inet addr:/
- @interfaces[@int_name]["bcast"] = (line =~ /Bcast:(\S+)/ ? ($1) : "nil") if line =~ /Bcast:/
- @interfaces[@int_name]["mask"] = (line =~ /Mask:(\S+)/ ? ($1) : "nil") if line =~ /Mask:/
- @interfaces[@int_name]["mtu"] = (line =~ /MTU:(\S+)/ ? ($1) : "nil") if line =~ /MTU:/
- @interfaces[@int_name]["metric"] = (line =~ /Metric:(\S+)/ ? ($1) : "nil") if line =~ /Metric:/
+ @interfaces[@int_name]["inet_addr"] = (line =~ /inet addr:(\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /inet addr:/
+ @interfaces[@int_name]["bcast"] = (line =~ /Bcast:(\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /Bcast:/
+ @interfaces[@int_name]["mask"] = (line =~ /Mask:(\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /Mask:/
+ @interfaces[@int_name]["mtu"] = (line =~ /MTU:(\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /MTU:/
+ @interfaces[@int_name]["metric"] = (line =~ /Metric:(\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /Metric:/
end
- if @interfaces.has_key?(@new_resource.device)
- @interface = @interfaces.fetch(@new_resource.device)
-
- @current_resource.target(@new_resource.target)
- @current_resource.device(@new_resource.device)
- @current_resource.inet_addr(@interface["inet_addr"])
- @current_resource.hwaddr(@interface["hwaddr"])
- @current_resource.bcast(@interface["bcast"])
- @current_resource.mask(@interface["mask"])
- @current_resource.mtu(@interface["mtu"])
- @current_resource.metric(@interface["metric"])
- end
+ next unless @interfaces.key?(new_resource.device)
+ @interface = @interfaces.fetch(new_resource.device)
+
+ current_resource.target(new_resource.target)
+ current_resource.device(new_resource.device)
+ current_resource.inet_addr(@interface["inet_addr"])
+ current_resource.hwaddr(@interface["hwaddr"])
+ current_resource.bcast(@interface["bcast"])
+ current_resource.mask(@interface["mask"])
+ current_resource.mtu(@interface["mtu"])
+ current_resource.metric(@interface["metric"])
end
- @current_resource
+ current_resource
end
def define_resource_requirements
@@ -104,14 +103,12 @@ class Chef
def action_add
# check to see if load_current_resource found interface in ifconfig
- unless @current_resource.inet_addr
- unless @new_resource.device == loopback_device
+ unless current_resource.inet_addr
+ unless new_resource.device == loopback_device
command = add_command
- converge_by ("run #{command} to add #{@new_resource}") do
- run_command(
- :command => command
- )
- Chef::Log.info("#{@new_resource} added")
+ converge_by("run #{command.join(' ')} to add #{new_resource}") do
+ shell_out_compact!(command)
+ Chef::Log.info("#{new_resource} added")
end
end
end
@@ -122,31 +119,25 @@ class Chef
def action_enable
# check to see if load_current_resource found ifconfig
# enables, but does not manage config files
- unless @current_resource.inet_addr
- unless @new_resource.device == loopback_device
- command = enable_command
- converge_by ("run #{command} to enable #{@new_resource}") do
- run_command(
- :command => command
- )
- Chef::Log.info("#{@new_resource} enabled")
- end
- end
+ return if current_resource.inet_addr
+ return if new_resource.device == loopback_device
+ command = enable_command
+ converge_by("run #{command.join(' ')} to enable #{new_resource}") do
+ shell_out_compact!(command)
+ Chef::Log.info("#{new_resource} enabled")
end
end
def action_delete
# check to see if load_current_resource found the interface
- if @current_resource.device
+ if current_resource.device
command = delete_command
- converge_by ("run #{command} to delete #{@new_resource}") do
- run_command(
- :command => command
- )
- Chef::Log.info("#{@new_resource} deleted")
+ converge_by("run #{command.join(' ')} to delete #{new_resource}") do
+ shell_out_compact!(command)
+ Chef::Log.info("#{new_resource} deleted")
end
else
- Chef::Log.debug("#{@new_resource} does not exist - nothing to do")
+ Chef::Log.debug("#{new_resource} does not exist - nothing to do")
end
delete_config
end
@@ -154,21 +145,19 @@ class Chef
def action_disable
# check to see if load_current_resource found the interface
# disables, but leaves config files in place.
- if @current_resource.device
+ if current_resource.device
command = disable_command
- converge_by ("run #{command} to disable #{@new_resource}") do
- run_command(
- :command => command
- )
- Chef::Log.info("#{@new_resource} disabled")
+ converge_by("run #{command.join(' ')} to disable #{new_resource}") do
+ shell_out_compact!(command)
+ Chef::Log.info("#{new_resource} disabled")
end
else
- Chef::Log.debug("#{@new_resource} does not exist - nothing to do")
+ Chef::Log.debug("#{new_resource} does not exist - nothing to do")
end
end
def can_generate_config?
- ! @config_template.nil? && ! @config_path.nil?
+ !@config_template.nil? && !@config_path.nil?
end
def resource_for_config(path)
@@ -182,40 +171,40 @@ class Chef
config = resource_for_config(@config_path)
config.content(template.result(b))
config.run_action(:create)
- @new_resource.updated_by_last_action(true) if config.updated?
+ new_resource.updated_by_last_action(true) if config.updated?
end
def delete_config
return unless can_generate_config?
config = resource_for_config(@config_path)
config.run_action(:delete)
- @new_resource.updated_by_last_action(true) if config.updated?
+ new_resource.updated_by_last_action(true) if config.updated?
end
private
def add_command
- command = "ifconfig #{@new_resource.device} #{@new_resource.target}"
- command << " netmask #{@new_resource.mask}" if @new_resource.mask
- command << " metric #{@new_resource.metric}" if @new_resource.metric
- command << " mtu #{@new_resource.mtu}" if @new_resource.mtu
+ command = [ "ifconfig", new_resource.device, new_resource.target ]
+ command += [ "netmask", new_resource.mask ] if new_resource.mask
+ command += [ "metric", new_resource.metric ] if new_resource.metric
+ command += [ "mtu", new_resource.mtu ] if new_resource.mtu
command
end
def enable_command
- command = "ifconfig #{@new_resource.device} #{@new_resource.target}"
- command << " netmask #{@new_resource.mask}" if @new_resource.mask
- command << " metric #{@new_resource.metric}" if @new_resource.metric
- command << " mtu #{@new_resource.mtu}" if @new_resource.mtu
+ command = [ "ifconfig", new_resource.device, new_resource.target ]
+ command += [ "netmask", new_resource.mask ] if new_resource.mask
+ command += [ "metric", new_resource.metric ] if new_resource.metric
+ command += [ "mtu", new_resource.mtu ] if new_resource.mtu
command
end
def disable_command
- "ifconfig #{@new_resource.device} down"
+ [ "ifconfig", new_resource.device, "down" ]
end
def delete_command
- "ifconfig #{@new_resource.device} down"
+ [ "ifconfig", new_resource.device, "down" ]
end
def loopback_device
diff --git a/lib/chef/provider/ifconfig/aix.rb b/lib/chef/provider/ifconfig/aix.rb
index 81164db304..788b609fcf 100644
--- a/lib/chef/provider/ifconfig/aix.rb
+++ b/lib/chef/provider/ifconfig/aix.rb
@@ -25,61 +25,56 @@ class Chef
provides :ifconfig, platform: %w{aix}
def load_current_resource
- @current_resource = Chef::Resource::Ifconfig.new(@new_resource.name)
+ @current_resource = Chef::Resource::Ifconfig.new(new_resource.name)
@interface_exists = false
found_interface = false
interface = {}
- @status = shell_out("ifconfig -a")
+ @status = shell_out_compact("ifconfig", "-a")
@status.stdout.each_line do |line|
if !found_interface
if line =~ /^(\S+):\sflags=(\S+)/
- # We have interface name, if this is the interface for @current_resource, load info else skip till next interface is found.
- if $1 == @new_resource.device
+ # We have interface name, if this is the interface for current_resource, load info else skip till next interface is found.
+ if Regexp.last_match(1) == new_resource.device
# Found interface
found_interface = true
@interface_exists = true
- @current_resource.target(@new_resource.target)
- @current_resource.device($1)
- interface[:flags] = $2
- @current_resource.metric($1) if line =~ /metric\s(\S+)/
- end
- end
- else
- # parse interface related information, stop when next interface is found.
- if line =~ /^(\S+):\sflags=(\S+)/
- # we are done parsing interface info and hit another one, so stop.
- found_interface = false
- break
- else
- if found_interface
- # read up interface info
- @current_resource.inet_addr($1) if line =~ /inet\s(\S+)\s/
- @current_resource.bcast($1) if line =~ /broadcast\s(\S+)/
- @current_resource.mask(hex_to_dec_netmask($1)) if line =~ /netmask\s(\S+)\s/
+ current_resource.target(new_resource.target)
+ current_resource.device(Regexp.last_match(1))
+ interface[:flags] = Regexp.last_match(2)
+ current_resource.metric(Regexp.last_match(1)) if line =~ /metric\s(\S+)/
end
end
+ elsif line =~ /^(\S+):\sflags=(\S+)/
+ # we are done parsing interface info and hit another one, so stop.
+ found_interface = false
+ break
+ elsif found_interface
+ # read up interface info
+ current_resource.inet_addr(Regexp.last_match(1)) if line =~ /inet\s(\S+)\s/
+ current_resource.bcast(Regexp.last_match(1)) if line =~ /broadcast\s(\S+)/
+ current_resource.mask(hex_to_dec_netmask(Regexp.last_match(1))) if line =~ /netmask\s(\S+)\s/
end
end
- @current_resource
+ current_resource
end
private
def add_command
# ifconfig changes are temporary, chdev persist across reboots.
- raise Chef::Exceptions::Ifconfig, "interface metric attribute cannot be set for :add action" if @new_resource.metric
- command = "chdev -l #{@new_resource.device} -a netaddr=#{@new_resource.name}"
- command << " -a netmask=#{@new_resource.mask}" if @new_resource.mask
- command << " -a mtu=#{@new_resource.mtu}" if @new_resource.mtu
+ raise Chef::Exceptions::Ifconfig, "interface metric attribute cannot be set for :add action" if new_resource.metric
+ command = [ "chdev", "-l", new_resource.device, "-a", "netaddr=#{new_resource.name}" ]
+ command += [ "-a", "netmask=#{new_resource.mask}" ] if new_resource.mask
+ command += [ "-a", "mtu=#{new_resource.mtu}" ] if new_resource.mtu
command
end
def delete_command
# ifconfig changes are temporary, chdev persist across reboots.
- "chdev -l #{@new_resource.device} -a state=down"
+ [ "chdev", "-l", new_resource.device, "-a", "state=down" ]
end
def loopback_device
diff --git a/lib/chef/provider/ifconfig/debian.rb b/lib/chef/provider/ifconfig/debian.rb
index 872b0db152..369c222b7a 100644
--- a/lib/chef/provider/ifconfig/debian.rb
+++ b/lib/chef/provider/ifconfig/debian.rb
@@ -26,32 +26,32 @@ class Chef
provides :ifconfig, platform: %w{ubuntu}, platform_version: ">= 11.10"
provides :ifconfig, platform: %w{debian}, platform_version: ">= 7.0"
- INTERFACES_FILE = "/etc/network/interfaces"
- INTERFACES_DOT_D_DIR = "/etc/network/interfaces.d"
+ INTERFACES_FILE = "/etc/network/interfaces".freeze
+ INTERFACES_DOT_D_DIR = "/etc/network/interfaces.d".freeze
def initialize(new_resource, run_context)
super(new_resource, run_context)
@config_template = %{
-<% if @new_resource.device %>
-<% if @new_resource.onboot == "yes" %>auto <%= @new_resource.device %><% end %>
-<% case @new_resource.bootproto
+<% if new_resource.device %>
+<% if new_resource.onboot == "yes" %>auto <%= new_resource.device %><% end %>
+<% case new_resource.bootproto
when "dhcp" %>
-iface <%= @new_resource.device %> inet dhcp
+iface <%= new_resource.device %> inet dhcp
<% when "bootp" %>
-iface <%= @new_resource.device %> inet bootp
+iface <%= new_resource.device %> inet bootp
<% else %>
-iface <%= @new_resource.device %> inet static
- <% if @new_resource.target %>address <%= @new_resource.target %><% end %>
- <% if @new_resource.mask %>netmask <%= @new_resource.mask %><% end %>
- <% if @new_resource.network %>network <%= @new_resource.network %><% end %>
- <% if @new_resource.bcast %>broadcast <%= @new_resource.bcast %><% end %>
- <% if @new_resource.metric %>metric <%= @new_resource.metric %><% end %>
- <% if @new_resource.hwaddr %>hwaddress <%= @new_resource.hwaddr %><% end %>
- <% if @new_resource.mtu %>mtu <%= @new_resource.mtu %><% end %>
+iface <%= new_resource.device %> inet static
+ <% if new_resource.target %>address <%= new_resource.target %><% end %>
+ <% if new_resource.mask %>netmask <%= new_resource.mask %><% end %>
+ <% if new_resource.network %>network <%= new_resource.network %><% end %>
+ <% if new_resource.bcast %>broadcast <%= new_resource.bcast %><% end %>
+ <% if new_resource.metric %>metric <%= new_resource.metric %><% end %>
+ <% if new_resource.hwaddr %>hwaddress <%= new_resource.hwaddr %><% end %>
+ <% if new_resource.mtu %>mtu <%= new_resource.mtu %><% end %>
<% end %>
<% end %>
}
- @config_path = "#{INTERFACES_DOT_D_DIR}/ifcfg-#{@new_resource.device}"
+ @config_path = "#{INTERFACES_DOT_D_DIR}/ifcfg-#{new_resource.device}"
end
def generate_config
@@ -69,12 +69,13 @@ iface <%= @new_resource.device %> inet static
# roll our own file_edit resource, this will not get reported until we have a file_edit resource
interfaces_dot_d_for_regexp = INTERFACES_DOT_D_DIR.gsub(/\./, '\.') # escape dots for the regexp
regexp = %r{^\s*source\s+#{interfaces_dot_d_for_regexp}/\*\s*$}
- unless ::File.exists?(INTERFACES_FILE) && regexp.match(IO.read(INTERFACES_FILE))
- converge_by("modifying #{INTERFACES_FILE} to source #{INTERFACES_DOT_D_DIR}") do
- conf = Chef::Util::FileEdit.new(INTERFACES_FILE)
- conf.insert_line_if_no_match(regexp, "source #{INTERFACES_DOT_D_DIR}/*")
- conf.write_file
- end
+
+ return if ::File.exist?(INTERFACES_FILE) && regexp.match(IO.read(INTERFACES_FILE))
+
+ converge_by("modifying #{INTERFACES_FILE} to source #{INTERFACES_DOT_D_DIR}") do
+ conf = Chef::Util::FileEdit.new(INTERFACES_FILE)
+ conf.insert_line_if_no_match(regexp, "source #{INTERFACES_DOT_D_DIR}/*")
+ conf.write_file
end
end
diff --git a/lib/chef/provider/ifconfig/redhat.rb b/lib/chef/provider/ifconfig/redhat.rb
index 0c28e6407a..841e725b94 100644
--- a/lib/chef/provider/ifconfig/redhat.rb
+++ b/lib/chef/provider/ifconfig/redhat.rb
@@ -27,19 +27,19 @@ class Chef
def initialize(new_resource, run_context)
super(new_resource, run_context)
@config_template = %{
-<% if @new_resource.device %>DEVICE=<%= @new_resource.device %><% end %>
-<% if @new_resource.onboot == "yes" %>ONBOOT=<%= @new_resource.onboot %><% end %>
-<% if @new_resource.bootproto %>BOOTPROTO=<%= @new_resource.bootproto %><% end %>
-<% if @new_resource.target %>IPADDR=<%= @new_resource.target %><% end %>
-<% if @new_resource.mask %>NETMASK=<%= @new_resource.mask %><% end %>
-<% if @new_resource.network %>NETWORK=<%= @new_resource.network %><% end %>
-<% if @new_resource.bcast %>BROADCAST=<%= @new_resource.bcast %><% end %>
-<% if @new_resource.onparent %>ONPARENT=<%= @new_resource.onparent %><% end %>
-<% if @new_resource.hwaddr %>HWADDR=<%= @new_resource.hwaddr %><% end %>
-<% if @new_resource.metric %>METRIC=<%= @new_resource.metric %><% end %>
-<% if @new_resource.mtu %>MTU=<%= @new_resource.mtu %><% end %>
+<% if new_resource.device %>DEVICE=<%= new_resource.device %><% end %>
+<% if new_resource.onboot == "yes" %>ONBOOT=<%= new_resource.onboot %><% end %>
+<% if new_resource.bootproto %>BOOTPROTO=<%= new_resource.bootproto %><% end %>
+<% if new_resource.target %>IPADDR=<%= new_resource.target %><% end %>
+<% if new_resource.mask %>NETMASK=<%= new_resource.mask %><% end %>
+<% if new_resource.network %>NETWORK=<%= new_resource.network %><% end %>
+<% if new_resource.bcast %>BROADCAST=<%= new_resource.bcast %><% end %>
+<% if new_resource.onparent %>ONPARENT=<%= new_resource.onparent %><% end %>
+<% if new_resource.hwaddr %>HWADDR=<%= new_resource.hwaddr %><% end %>
+<% if new_resource.metric %>METRIC=<%= new_resource.metric %><% end %>
+<% if new_resource.mtu %>MTU=<%= new_resource.mtu %><% end %>
}
- @config_path = "/etc/sysconfig/network-scripts/ifcfg-#{@new_resource.device}"
+ @config_path = "/etc/sysconfig/network-scripts/ifcfg-#{new_resource.device}"
end
end
diff --git a/lib/chef/provider/launchd.rb b/lib/chef/provider/launchd.rb
index c58d4bfa34..f3e0a00758 100644
--- a/lib/chef/provider/launchd.rb
+++ b/lib/chef/provider/launchd.rb
@@ -115,7 +115,7 @@ class Chef
res = Chef::Resource::File.new(@path, run_context)
res.name(@path) if @path
res.backup(backup) if backup
- res.content(content) if content
+ res.content(content) if content?
res.group(group) if group
res.mode(mode) if mode
res.owner(owner) if owner
@@ -150,7 +150,7 @@ class Chef
end
def content
- plist_hash = new_resource.hash || gen_hash
+ plist_hash = new_resource.plist_hash || gen_hash
Plist::Emit.dump(plist_hash) unless plist_hash.nil?
end
diff --git a/lib/chef/provider/link.rb b/lib/chef/provider/link.rb
index 16d30319b3..5add453072 100644
--- a/lib/chef/provider/link.rb
+++ b/lib/chef/provider/link.rb
@@ -121,6 +121,12 @@ class Chef
file_class.symlink(canonicalize(@new_resource.to), @new_resource.target_file)
Chef::Log.debug("#{@new_resource} created #{@new_resource.link_type} link from #{@new_resource.target_file} -> #{@new_resource.to}")
Chef::Log.info("#{@new_resource} created")
+ # file_class.symlink will create the link with default access controls.
+ # This means that the access controls of the file could be different
+ # than those captured during the initial evaluation of current_resource.
+ # We need to re-evaluate the current_resource to ensure that the desired
+ # access controls are applied.
+ ScanAccessControl.new(@new_resource, @current_resource).set_all!
end
elsif @new_resource.link_type == :hard
converge_by("create hard link at #{@new_resource.target_file} to #{@new_resource.to}") do
diff --git a/lib/chef/provider/mount.rb b/lib/chef/provider/mount.rb
index 9e9ee29bde..5168c93348 100644
--- a/lib/chef/provider/mount.rb
+++ b/lib/chef/provider/mount.rb
@@ -108,6 +108,8 @@ class Chef
end
end
+ alias :action_unmount :action_umount
+
#
# Abstract Methods to be implemented by subclasses
#
diff --git a/lib/chef/provider/mount/aix.rb b/lib/chef/provider/mount/aix.rb
index 12f0d67e6b..73460e84a1 100644
--- a/lib/chef/provider/mount/aix.rb
+++ b/lib/chef/provider/mount/aix.rb
@@ -116,9 +116,9 @@ class Chef
def remount_command
if !(@new_resource.options.nil? || @new_resource.options.empty?)
- return "mount -o remount,#{@new_resource.options.join(',')} #{@new_resource.device} #{@new_resource.mount_point}"
+ "mount -o remount,#{@new_resource.options.join(',')} #{@new_resource.device} #{@new_resource.mount_point}"
else
- return "mount -o remount #{@new_resource.device} #{@new_resource.mount_point}"
+ "mount -o remount #{@new_resource.device} #{@new_resource.mount_point}"
end
end
diff --git a/lib/chef/provider/mount/mount.rb b/lib/chef/provider/mount/mount.rb
index 07da6ac361..c3b1cc0141 100644
--- a/lib/chef/provider/mount/mount.rb
+++ b/lib/chef/provider/mount/mount.rb
@@ -47,7 +47,7 @@ class Chef
elsif @new_resource.mount_point != "none" && !::File.exists?(@new_resource.mount_point)
raise Chef::Exceptions::Mount, "Mount point #{@new_resource.mount_point} does not exist"
end
- return true
+ true
end
def enabled?
@@ -129,7 +129,7 @@ class Chef
end
def remount_command
- return "mount -o remount,#{@new_resource.options.join(',')} #{@new_resource.mount_point}"
+ "mount -o remount,#{@new_resource.options.join(',')} #{@new_resource.mount_point}"
end
def remount_fs
@@ -193,7 +193,7 @@ class Chef
def device_should_exist?
( @new_resource.device != "none" ) &&
( not network_device? ) &&
- ( not %w{ cgroup tmpfs fuse vboxsf }.include? @new_resource.fstype )
+ ( not %w{ cgroup tmpfs fuse vboxsf zfs }.include? @new_resource.fstype )
end
private
@@ -210,7 +210,7 @@ class Chef
end
def device_real
- if @real_device == nil
+ if @real_device.nil?
if @new_resource.device_type == :device
@real_device = @new_resource.device
else
diff --git a/lib/chef/provider/ohai.rb b/lib/chef/provider/ohai.rb
index 6b5a605ed5..8f1939af6d 100644
--- a/lib/chef/provider/ohai.rb
+++ b/lib/chef/provider/ohai.rb
@@ -21,6 +21,8 @@ require "ohai"
class Chef
class Provider
class Ohai < Chef::Provider
+ use_inline_resources
+
provides :ohai
def whyrun_supported?
@@ -31,7 +33,7 @@ class Chef
true
end
- def action_reload
+ action :reload do
converge_by("re-run ohai and merge results into node attributes") do
ohai = ::Ohai::System.new
@@ -39,9 +41,9 @@ class Chef
# Otherwise it will only reload the specified plugin
# Note that any changes to plugins, or new plugins placed on
# the path are picked up by ohai.
- ohai.all_plugins @new_resource.plugin
+ ohai.all_plugins new_resource.plugin
node.automatic_attrs.merge! ohai.data
- Chef::Log.info("#{@new_resource} reloaded")
+ Chef::Log.info("#{new_resource} reloaded")
end
end
end
diff --git a/lib/chef/provider/osx_profile.rb b/lib/chef/provider/osx_profile.rb
index 07c3e6e318..6939c386a1 100644
--- a/lib/chef/provider/osx_profile.rb
+++ b/lib/chef/provider/osx_profile.rb
@@ -44,8 +44,10 @@ class Chef
)
@new_profile_hash = get_profile_hash(@new_resource.profile)
- @new_profile_hash["PayloadUUID"] =
- config_uuid(@new_profile_hash) if @new_profile_hash
+ if @new_profile_hash
+ @new_profile_hash["PayloadUUID"] =
+ config_uuid(@new_profile_hash)
+ end
if @new_profile_hash
@new_profile_identifier = @new_profile_hash["PayloadIdentifier"]
@@ -126,9 +128,9 @@ class Chef
raise Chef::Exceptions::FileNotFound, error_string
end
cookbook_profile = cache_cookbook_profile(new_profile)
- return read_plist(cookbook_profile)
+ read_plist(cookbook_profile)
else
- return nil
+ nil
end
end
@@ -168,9 +170,9 @@ class Chef
def get_profile_hash(new_profile)
if new_profile.is_a?(Hash)
- return new_profile
+ new_profile
elsif new_profile.is_a?(String)
- return load_profile_hash(new_profile)
+ load_profile_hash(new_profile)
end
end
diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb
index 048807dd05..8f504939fc 100644
--- a/lib/chef/provider/package.rb
+++ b/lib/chef/provider/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");
@@ -37,6 +37,9 @@ class Chef
subclass_directive :use_multipackage_api
# subclasses declare this if they want sources (filenames) pulled from their package names
subclass_directive :use_package_name_for_source
+ # keeps package_names_for_targets and versions_for_targets indexed the same as package_name at
+ # the cost of having the subclass needing to deal with nils
+ subclass_directive :allow_nils
#
# Hook that subclasses use to populate the candidate_version(s)
@@ -49,6 +52,17 @@ class Chef
@candidate_version = nil
end
+ def options
+ if new_resource.options.is_a?(String)
+ # XXX: needs to handle double quotes, single quotes, nested quotes, etc and probably act
+ # more like a space-separated "C"SV file -- although users can fix this just by passing in
+ # a correctly pre-split Array.
+ new_resource.options.split(" ")
+ else
+ new_resource.options
+ end
+ end
+
def whyrun_supported?
true
end
@@ -56,21 +70,20 @@ class Chef
def check_resource_semantics!
# FIXME: this is not universally true and subclasses are needing to override this and no-ops it. It should be turned into
# another "subclass_directive" and the apt and yum providers should declare that they need this behavior.
- if new_resource.package_name.is_a?(Array) && new_resource.source != nil
+ if new_resource.package_name.is_a?(Array) && !new_resource.source.nil?
raise Chef::Exceptions::InvalidResourceSpecification, "You may not specify both multipackage and source"
end
end
- def load_current_resource
- end
+ def load_current_resource; end
def define_resource_requirements
# XXX: upgrade with a specific version doesn't make a whole lot of sense, but why don't we throw this anyway if it happens?
# if not, shouldn't we raise to tell the user to use install instead of upgrade if they want to pin a version?
requirements.assert(:install) do |a|
a.assertion { candidates_exist_for_all_forced_changes? }
- a.failure_message(Chef::Exceptions::Package, "No version specified, and no candidate version available for #{forced_packages_missing_candidates.join(", ")}")
- a.whyrun("Assuming a repository that offers #{forced_packages_missing_candidates.join(", ")} would have been configured")
+ a.failure_message(Chef::Exceptions::Package, "No version specified, and no candidate version available for #{forced_packages_missing_candidates.join(', ')}")
+ a.whyrun("Assuming a repository that offers #{forced_packages_missing_candidates.join(', ')} would have been configured")
end
# XXX: Does it make sense to pass in a source with :upgrade? Probably
@@ -78,19 +91,19 @@ class Chef
# so we'll just leave things as-is for now.
requirements.assert(:upgrade, :install) do |a|
a.assertion { candidates_exist_for_all_uninstalled? || new_resource.source }
- a.failure_message(Chef::Exceptions::Package, "No candidate version available for #{packages_missing_candidates.join(", ")}")
- a.whyrun("Assuming a repository that offers #{packages_missing_candidates.join(", ")} would have been configured")
+ a.failure_message(Chef::Exceptions::Package, "No candidate version available for #{packages_missing_candidates.join(', ')}")
+ a.whyrun("Assuming a repository that offers #{packages_missing_candidates.join(', ')} would have been configured")
end
end
action :install do
unless target_version_array.any?
- Chef::Log.debug("#{@new_resource} is already installed - nothing to do")
+ Chef::Log.debug("#{new_resource} is already installed - nothing to do")
return
end
# @todo: move the preseed code out of the base class (and complete the fix for Array of preseeds? ugh...)
- if @new_resource.response_file
+ if new_resource.response_file
if preseed_file = get_preseed_file(package_names_for_targets, versions_for_targets)
converge_by("preseed package #{package_names_for_targets}") do
preseed_package(preseed_file)
@@ -102,7 +115,7 @@ class Chef
multipackage_api_adapter(package_names_for_targets, versions_for_targets) do |name, version|
install_package(name, version)
end
- Chef::Log.info("#{@new_resource} installed #{package_names_for_targets} at #{versions_for_targets}")
+ Chef::Log.info("#{new_resource} installed #{package_names_for_targets} at #{versions_for_targets}")
end
end
@@ -119,8 +132,8 @@ class Chef
private :install_description
action :upgrade do
- if !target_version_array.any?
- Chef::Log.debug("#{@new_resource} no versions to upgrade - nothing to do")
+ unless target_version_array.any?
+ Chef::Log.debug("#{new_resource} no versions to upgrade - nothing to do")
return
end
@@ -129,7 +142,7 @@ class Chef
upgrade_package(name, version)
end
log_allow_downgrade = allow_downgrade ? "(allow_downgrade)" : ""
- Chef::Log.info("#{@new_resource} upgraded#{log_allow_downgrade} #{package_names_for_targets} to #{versions_for_targets}")
+ Chef::Log.info("#{new_resource} upgraded#{log_allow_downgrade} #{package_names_for_targets} to #{versions_for_targets}")
end
end
@@ -150,15 +163,15 @@ class Chef
action :remove do
if removing_package?
- description = @new_resource.version ? "version #{@new_resource.version} of " : ""
- converge_by("remove #{description}package #{@current_resource.package_name}") do
- multipackage_api_adapter(@current_resource.package_name, @new_resource.version) do |name, version|
+ description = new_resource.version ? "version #{new_resource.version} of " : ""
+ converge_by("remove #{description}package #{current_resource.package_name}") do
+ multipackage_api_adapter(current_resource.package_name, new_resource.version) do |name, version|
remove_package(name, version)
end
- Chef::Log.info("#{@new_resource} removed")
+ Chef::Log.info("#{new_resource} removed")
end
else
- Chef::Log.debug("#{@new_resource} package does not exist - nothing to do")
+ Chef::Log.debug("#{new_resource} package does not exist - nothing to do")
end
end
@@ -185,48 +198,48 @@ class Chef
action :purge do
if removing_package?
- description = @new_resource.version ? "version #{@new_resource.version} of" : ""
- converge_by("purge #{description} package #{@current_resource.package_name}") do
- multipackage_api_adapter(@current_resource.package_name, @new_resource.version) do |name, version|
+ description = new_resource.version ? "version #{new_resource.version} of" : ""
+ converge_by("purge #{description} package #{current_resource.package_name}") do
+ multipackage_api_adapter(current_resource.package_name, new_resource.version) do |name, version|
purge_package(name, version)
end
- Chef::Log.info("#{@new_resource} purged")
+ Chef::Log.info("#{new_resource} purged")
end
end
end
action :reconfig do
- if @current_resource.version == nil
- Chef::Log.debug("#{@new_resource} is NOT installed - nothing to do")
+ if current_resource.version.nil?
+ Chef::Log.debug("#{new_resource} is NOT installed - nothing to do")
return
end
- unless @new_resource.response_file
- Chef::Log.debug("#{@new_resource} no response_file provided - nothing to do")
+ unless new_resource.response_file
+ Chef::Log.debug("#{new_resource} no response_file provided - nothing to do")
return
end
- if preseed_file = get_preseed_file(@new_resource.package_name, @current_resource.version)
- converge_by("reconfigure package #{@new_resource.package_name}") do
+ if preseed_file = get_preseed_file(new_resource.package_name, current_resource.version)
+ converge_by("reconfigure package #{new_resource.package_name}") do
preseed_package(preseed_file)
- multipackage_api_adapter(@new_resource.package_name, @current_resource.version) do |name, version|
+ multipackage_api_adapter(new_resource.package_name, current_resource.version) do |name, version|
reconfig_package(name, version)
end
- Chef::Log.info("#{@new_resource} reconfigured")
+ Chef::Log.info("#{new_resource} reconfigured")
end
else
- Chef::Log.debug("#{@new_resource} preseeding has not changed - nothing to do")
+ Chef::Log.debug("#{new_resource} preseeding has not changed - nothing to do")
end
end
def action_lock
- if package_locked(@new_resource.name, @new_resource.version) == false
- description = @new_resource.version ? "version #{@new_resource.version} of " : ""
- converge_by("lock #{description}package #{@current_resource.package_name}") do
- multipackage_api_adapter(@current_resource.package_name, @new_resource.version) do |name, version|
+ if package_locked(new_resource.name, new_resource.version) == false
+ description = new_resource.version ? "version #{new_resource.version} of " : ""
+ converge_by("lock #{description}package #{current_resource.package_name}") do
+ multipackage_api_adapter(current_resource.package_name, new_resource.version) do |name, version|
lock_package(name, version)
- Chef::Log.info("#{@new_resource} locked")
+ Chef::Log.info("#{new_resource} locked")
end
end
else
@@ -235,12 +248,12 @@ class Chef
end
def action_unlock
- if package_locked(@new_resource.name, @new_resource.version) == true
- description = @new_resource.version ? "version #{@new_resource.version} of " : ""
- converge_by("unlock #{description}package #{@current_resource.package_name}") do
- multipackage_api_adapter(@current_resource.package_name, @new_resource.version) do |name, version|
+ if package_locked(new_resource.name, new_resource.version) == true
+ description = new_resource.version ? "version #{new_resource.version} of " : ""
+ converge_by("unlock #{description}package #{current_resource.package_name}") do
+ multipackage_api_adapter(current_resource.package_name, new_resource.version) do |name, version|
unlock_package(name, version)
- Chef::Log.info("#{@new_resource} unlocked")
+ Chef::Log.info("#{new_resource} unlocked")
end
end
else
@@ -248,6 +261,10 @@ class Chef
end
end
+ def package_locked(name, version)
+ raise Chef::Exceptions::UnsupportedAction, "#{self} has no way to detect if package is locked"
+ end
+
# @todo use composition rather than inheritance
def multipackage_api_adapter(name, version)
@@ -292,6 +309,8 @@ class Chef
# used by subclasses. deprecated. use #a_to_s instead.
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}" : ""
end
@@ -336,7 +355,7 @@ class Chef
def get_preseed_file(name, version)
resource = preseed_resource(name, version)
resource.run_action(:create)
- Chef::Log.debug("#{@new_resource} fetched preseed file to #{resource.path}")
+ Chef::Log.debug("#{new_resource} fetched preseed file to #{resource.path}")
if resource.updated_by_last_action?
resource.path
@@ -348,26 +367,26 @@ class Chef
# @todo: extract apt/dpkg specific preseeding to a helper class
def preseed_resource(name, version)
# A directory in our cache to store this cookbook's preseed files in
- file_cache_dir = Chef::FileCache.create_cache_path("preseed/#{@new_resource.cookbook_name}")
+ file_cache_dir = Chef::FileCache.create_cache_path("preseed/#{new_resource.cookbook_name}")
# The full path where the preseed file will be stored
cache_seed_to = "#{file_cache_dir}/#{name}-#{version}.seed"
- Chef::Log.debug("#{@new_resource} fetching preseed file to #{cache_seed_to}")
+ Chef::Log.debug("#{new_resource} fetching preseed file to #{cache_seed_to}")
- if template_available?(@new_resource.response_file)
- Chef::Log.debug("#{@new_resource} fetching preseed file via Template")
+ if template_available?(new_resource.response_file)
+ Chef::Log.debug("#{new_resource} fetching preseed file via Template")
remote_file = Chef::Resource::Template.new(cache_seed_to, run_context)
- remote_file.variables(@new_resource.response_file_variables)
- elsif cookbook_file_available?(@new_resource.response_file)
- Chef::Log.debug("#{@new_resource} fetching preseed file via cookbook_file")
+ remote_file.variables(new_resource.response_file_variables)
+ elsif cookbook_file_available?(new_resource.response_file)
+ Chef::Log.debug("#{new_resource} fetching preseed file via cookbook_file")
remote_file = Chef::Resource::CookbookFile.new(cache_seed_to, run_context)
else
- message = "No template or cookbook file found for response file #{@new_resource.response_file}"
+ message = "No template or cookbook file found for response file #{new_resource.response_file}"
raise Chef::Exceptions::FileNotFound, message
end
- remote_file.cookbook_name = @new_resource.cookbook_name
- remote_file.source(@new_resource.response_file)
+ remote_file.cookbook_name = new_resource.cookbook_name
+ remote_file.source(new_resource.response_file)
remote_file.backup(false)
remote_file
end
@@ -390,9 +409,12 @@ class Chef
def package_names_for_targets
package_names_for_targets = []
target_version_array.each_with_index do |target_version, i|
- next if target_version.nil?
- package_name = package_name_array[i]
- package_names_for_targets.push(package_name)
+ if !target_version.nil?
+ package_name = package_name_array[i]
+ package_names_for_targets.push(package_name)
+ else
+ package_names_for_targets.push(nil) if allow_nils?
+ end
end
multipackage? ? package_names_for_targets : package_names_for_targets[0]
end
@@ -407,8 +429,11 @@ class Chef
def versions_for_targets
versions_for_targets = []
target_version_array.each_with_index do |target_version, i|
- next if target_version.nil?
- versions_for_targets.push(target_version)
+ if !target_version.nil?
+ versions_for_targets.push(target_version)
+ else
+ versions_for_targets.push(nil) if allow_nils?
+ end
end
multipackage? ? versions_for_targets : versions_for_targets[0]
end
@@ -599,8 +624,8 @@ class Chef
end
def allow_downgrade
- if @new_resource.respond_to?("allow_downgrade")
- @new_resource.allow_downgrade
+ if new_resource.respond_to?("allow_downgrade")
+ new_resource.allow_downgrade
else
false
end
@@ -615,14 +640,16 @@ class Chef
end
def add_timeout_option(command_args)
+ # this is deprecated but its not quite done yet
+ #Chef.deprecated(:package_misc, "shell_out_with_timeout and add_timeout_option are deprecated methods, use shell_out_compact_timeout instead")
args = command_args.dup
if args.last.is_a?(Hash)
options = args.pop.dup
options[:timeout] = new_resource.timeout if new_resource.timeout
- options[:timeout] = 900 unless options.has_key?(:timeout)
+ options[:timeout] = 900 unless options.key?(:timeout)
args << options
else
- args << { :timeout => new_resource.timeout ? new_resource.timeout : 900 }
+ args << { timeout: new_resource.timeout ? new_resource.timeout : 900 }
end
args
end
diff --git a/lib/chef/provider/package/aix.rb b/lib/chef/provider/package/aix.rb
index 728f181055..5af5f5afad 100644
--- a/lib/chef/provider/package/aix.rb
+++ b/lib/chef/provider/package/aix.rb
@@ -34,48 +34,45 @@ class Chef
def define_resource_requirements
super
requirements.assert(:install) do |a|
- a.assertion { @new_resource.source }
- a.failure_message Chef::Exceptions::Package, "Source for package #{@new_resource.name} required for action install"
+ a.assertion { new_resource.source }
+ a.failure_message Chef::Exceptions::Package, "Source for package #{new_resource.name} required for action install"
end
requirements.assert(:all_actions) do |a|
- a.assertion { !@new_resource.source || @package_source_found }
- a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}"
- a.whyrun "would assume #{@new_resource.source} would be have previously been made available"
+ a.assertion { !new_resource.source || package_source_found? }
+ a.failure_message Chef::Exceptions::Package, "Package #{new_resource.name} not found: #{new_resource.source}"
+ a.whyrun "would assume #{new_resource.source} would be have previously been made available"
end
end
def load_current_resource
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
- if @new_resource.source
- @package_source_found = ::File.exists?(@new_resource.source)
- if @package_source_found
- Chef::Log.debug("#{@new_resource} checking pkg status")
- ret = shell_out_with_timeout("installp -L -d #{@new_resource.source}")
- ret.stdout.each_line do |line|
- case line
- when /:#{@new_resource.package_name}:/
- fields = line.split(":")
- @new_resource.version(fields[2])
- when /^#{@new_resource.package_name}:/
- Chef::Log.warn("You are installing a bff package by product name. For idempotent installs, please install individual filesets")
- fields = line.split(":")
- @new_resource.version(fields[2])
- end
+ if package_source_found?
+ Chef::Log.debug("#{new_resource} checking pkg status")
+ ret = shell_out_compact_timeout("installp", "-L", "-d", new_resource.source)
+ ret.stdout.each_line do |line|
+ case line
+ when /:#{new_resource.package_name}:/
+ fields = line.split(":")
+ new_resource.version(fields[2])
+ when /^#{new_resource.package_name}:/
+ Chef::Log.warn("You are installing a bff package by product name. For idempotent installs, please install individual filesets")
+ fields = line.split(":")
+ new_resource.version(fields[2])
end
- raise Chef::Exceptions::Package, "package source #{@new_resource.source} does not provide package #{@new_resource.package_name}" unless @new_resource.version
end
+ raise Chef::Exceptions::Package, "package source #{new_resource.source} does not provide package #{new_resource.package_name}" unless new_resource.version
end
- Chef::Log.debug("#{@new_resource} checking install state")
- ret = shell_out_with_timeout("lslpp -lcq #{@current_resource.package_name}")
+ Chef::Log.debug("#{new_resource} checking install state")
+ ret = shell_out_compact_timeout("lslpp", "-lcq", current_resource.package_name)
ret.stdout.each_line do |line|
case line
- when /#{@current_resource.package_name}/
+ when /#{current_resource.package_name}/
fields = line.split(":")
- Chef::Log.debug("#{@new_resource} version #{fields[2]} is already installed")
- @current_resource.version(fields[2])
+ Chef::Log.debug("#{new_resource} version #{fields[2]} is already installed")
+ current_resource.version(fields[2])
end
end
@@ -83,23 +80,25 @@ class Chef
raise Chef::Exceptions::Package, "lslpp failed - #{ret.format_for_exception}!"
end
- @current_resource
+ current_resource
end
def candidate_version
return @candidate_version if @candidate_version
- ret = shell_out_with_timeout("installp -L -d #{@new_resource.source}")
- ret.stdout.each_line do |line|
- case line
- when /\w:#{Regexp.escape(@new_resource.package_name)}:(.*)/
- fields = line.split(":")
- @candidate_version = fields[2]
- @new_resource.version(fields[2])
- Chef::Log.debug("#{@new_resource} setting install candidate version to #{@candidate_version}")
+ if package_source_found?
+ ret = shell_out_compact_timeout("installp", "-L", "-d", new_resource.source)
+ ret.stdout.each_line do |line|
+ case line
+ when /\w:#{Regexp.escape(new_resource.package_name)}:(.*)/
+ fields = line.split(":")
+ @candidate_version = fields[2]
+ new_resource.version(fields[2])
+ Chef::Log.debug("#{new_resource} setting install candidate version to #{@candidate_version}")
+ end
+ end
+ unless ret.exitstatus == 0
+ raise Chef::Exceptions::Package, "installp -L -d #{new_resource.source} - #{ret.format_for_exception}!"
end
- end
- unless ret.exitstatus == 0
- raise Chef::Exceptions::Package, "installp -L -d #{@new_resource.source} - #{ret.format_for_exception}!"
end
@candidate_version
end
@@ -112,28 +111,32 @@ class Chef
# So far, the code has been tested only with standalone packages.
#
def install_package(name, version)
- Chef::Log.debug("#{@new_resource} package install options: #{@new_resource.options}")
- if @new_resource.options.nil?
- shell_out_with_timeout!( "installp -aYF -d #{@new_resource.source} #{@new_resource.package_name}" )
- Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}")
+ Chef::Log.debug("#{new_resource} package install options: #{options}")
+ if options.nil?
+ shell_out_compact_timeout!("installp", "-aYF", "-d", new_resource.source, new_resource.package_name)
+ Chef::Log.debug("#{new_resource} installed version #{new_resource.version} from: #{new_resource.source}")
else
- shell_out_with_timeout!( "installp -aYF #{expand_options(@new_resource.options)} -d #{@new_resource.source} #{@new_resource.package_name}" )
- Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}")
+ shell_out_compact_timeout!("installp", "-aYF", options, "-d", new_resource.source, new_resource.package_name)
+ Chef::Log.debug("#{new_resource} installed version #{new_resource.version} from: #{new_resource.source}")
end
end
- alias_method :upgrade_package, :install_package
+ alias upgrade_package install_package
def remove_package(name, version)
- if @new_resource.options.nil?
- shell_out_with_timeout!( "installp -u #{name}" )
- Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}")
+ if options.nil?
+ shell_out_compact_timeout!("installp", "-u", name)
+ Chef::Log.debug("#{new_resource} removed version #{new_resource.version}")
else
- shell_out_with_timeout!( "installp -u #{expand_options(@new_resource.options)} #{name}" )
- Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}")
+ shell_out_compact_timeout!("installp", "-u", options, name)
+ Chef::Log.debug("#{new_resource} removed version #{new_resource.version}")
end
end
+ def package_source_found?
+ @package_source_found ||= new_resource.source && ::File.exist?(new_resource.source)
+ end
+
end
end
end
diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb
index 1c8ed8bc94..3f8c34f50c 100644
--- a/lib/chef/provider/package/apt.rb
+++ b/lib/chef/provider/package/apt.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");
@@ -72,21 +72,21 @@ class Chef
def package_locked(name, version)
islocked = false
- locked = shell_out_with_timeout!("apt-mark showhold")
+ locked = shell_out_compact_timeout!("apt-mark", "showhold")
locked.stdout.each_line do |line|
line_package = line.strip
if line_package == name
islocked = true
end
end
- return islocked
+ islocked
end
def install_package(name, version)
package_name = name.zip(version).map do |n, v|
package_data[n][:virtual] ? n : "#{n}=#{v}"
end
- run_noninteractive("apt-get -q -y", default_release_options, new_resource.options, "install", package_name)
+ run_noninteractive("apt-get", "-q", "-y", default_release_options, options, "install", package_name)
end
def upgrade_package(name, version)
@@ -97,14 +97,14 @@ class Chef
package_name = name.map do |n|
package_data[n][:virtual] ? resolve_virtual_package_name(n) : n
end
- run_noninteractive("apt-get -q -y", new_resource.options, "remove", package_name)
+ run_noninteractive("apt-get", "-q", "-y", options, "remove", package_name)
end
def purge_package(name, version)
package_name = name.map do |n|
package_data[n][:virtual] ? resolve_virtual_package_name(n) : n
end
- run_noninteractive("apt-get -q -y", new_resource.options, "purge", package_name)
+ run_noninteractive("apt-get", "-q", "-y", options, "purge", package_name)
end
def preseed_package(preseed_file)
@@ -118,11 +118,11 @@ class Chef
end
def lock_package(name, version)
- run_noninteractive("apt-mark", new_resource.options, "hold", name)
+ run_noninteractive("apt-mark", options, "hold", name)
end
def unlock_package(name, version)
- run_noninteractive("apt-mark", new_resource.options, "unhold", name)
+ run_noninteractive("apt-mark", options, "unhold", name)
end
private
@@ -131,12 +131,14 @@ class Chef
# interactive prompts. Command is run with default localization rather
# than forcing locale to "C", so command output may not be stable.
def run_noninteractive(*args)
- shell_out_with_timeout!(a_to_s(*args), :env => { "DEBIAN_FRONTEND" => "noninteractive" })
+ shell_out_compact_timeout!(*args, env: { "DEBIAN_FRONTEND" => "noninteractive" })
end
def default_release_options
# Use apt::Default-Release option only if provider supports it
- "-o APT::Default-Release=#{new_resource.default_release}" if new_resource.respond_to?(:default_release) && new_resource.default_release
+ if new_resource.respond_to?(:default_release) && new_resource.default_release
+ [ "-o", "APT::Default-Release=#{new_resource.default_release}" ]
+ end
end
def resolve_package_versions(pkg)
@@ -156,7 +158,7 @@ class Chef
end
def resolve_virtual_package_name(pkg)
- showpkg = run_noninteractive("apt-cache showpkg", pkg).stdout
+ showpkg = run_noninteractive("apt-cache", "showpkg", pkg).stdout
partitions = showpkg.rpartition(/Reverse Provides: ?#{$/}/)
return nil if partitions[0] == "" && partitions[1] == "" # not found in output
set = partitions[2].lines.each_with_object(Set.new) do |line, acc|
@@ -166,7 +168,7 @@ class Chef
if set.size > 1
raise Chef::Exceptions::Package, "#{new_resource.package_name} is a virtual package provided by multiple packages, you must explicitly select one"
end
- return set.to_a.first
+ set.to_a.first
end
def package_data_for(pkg)
@@ -186,7 +188,7 @@ class Chef
end
end
- return {
+ {
current_version: current_version,
candidate_version: candidate_version,
virtual: virtual,
diff --git a/lib/chef/provider/package/cab.rb b/lib/chef/provider/package/cab.rb
index 4e2054fbc2..d6e989eb72 100644
--- a/lib/chef/provider/package/cab.rb
+++ b/lib/chef/provider/package/cab.rb
@@ -19,50 +19,80 @@
require "chef/provider/package"
require "chef/resource/cab_package"
require "chef/mixin/shell_out"
+require "chef/mixin/uris"
+require "chef/mixin/checksum"
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
provides :cab_package, os: "windows"
def load_current_resource
@current_resource = Chef::Resource::CabPackage.new(new_resource.name)
- current_resource.source(new_resource.source)
+ current_resource.source(cab_file_source)
new_resource.version(package_version)
current_resource.version(installed_version)
current_resource
end
+ def cab_file_source
+ @cab_file_source ||= uri_scheme?(new_resource.source) ? download_source_file : new_resource.source
+ end
+
+ def download_source_file
+ source_resource.run_action(:create)
+ Chef::Log.debug("#{new_resource} fetched source file to #{source_resource.path}")
+ source_resource.path
+ end
+
+ def source_resource
+ @source_resource ||= declare_resource(:remote_file, new_resource.name) do
+ path default_download_cache_path
+ source new_resource.source
+ backup false
+ end
+ end
+
+ def default_download_cache_path
+ uri = ::URI.parse(new_resource.source)
+ filename = ::File.basename(::URI.unescape(uri.path))
+ file_cache_dir = Chef::FileCache.create_cache_path("package/")
+ Chef::Util::PathHelper.cleanpath("#{file_cache_dir}/#{filename}")
+ end
+
def install_package(name, version)
- dism_command("/Add-Package /PackagePath:\"#{@new_resource.source}\"")
+ dism_command("/Add-Package /PackagePath:\"#{cab_file_source}\"")
end
def remove_package(name, version)
- dism_command("/Remove-Package /PackagePath:\"#{@new_resource.source}\"")
+ dism_command("/Remove-Package /PackagePath:\"#{cab_file_source}\"")
end
def dism_command(command)
- shellout = Mixlib::ShellOut.new("dism.exe /Online #{command} /NoRestart", { :timeout => @new_resource.timeout })
+ shellout = Mixlib::ShellOut.new("dism.exe /Online /English #{command} /NoRestart", timeout: new_resource.timeout)
with_os_architecture(nil) do
shellout.run_command
end
end
def installed_version
- stdout = dism_command("/Get-PackageInfo /PackagePath:\"#{@new_resource.source}\"").stdout
+ stdout = dism_command("/Get-PackageInfo /PackagePath:\"#{cab_file_source}\"").stdout
package_info = parse_dism_get_package_info(stdout)
# e.g. Package_for_KB2975719~31bf3856ad364e35~amd64~~6.3.1.8
package = split_package_identity(package_info["package_information"]["package_identity"])
# Search for just the package name to catch a different version being installed
- Chef::Log.debug("#{@new_resource} searching for installed package #{package['name']}")
+ Chef::Log.debug("#{new_resource} searching for installed package #{package['name']}")
found_packages = installed_packages.select { |p| p["package_identity"] =~ /^#{package['name']}~/ }
- if found_packages.length == 0
+ if found_packages.empty?
nil
elsif found_packages.length == 1
- stdout = dism_command("/Get-PackageInfo /PackageName:\"#{found_packages.first["package_identity"]}\"").stdout
+ stdout = dism_command("/Get-PackageInfo /PackageName:\"#{found_packages.first['package_identity']}\"").stdout
find_version(stdout)
else
# Presuming this won't happen, otherwise we need to handle it
@@ -71,8 +101,8 @@ class Chef
end
def package_version
- Chef::Log.debug("#{@new_resource} getting product version for package at #{@new_resource.source}")
- stdout = dism_command("/Get-PackageInfo /PackagePath:\"#{@new_resource.source}\"").stdout
+ Chef::Log.debug("#{new_resource} getting product version for package at #{cab_file_source}")
+ stdout = dism_command("/Get-PackageInfo /PackagePath:\"#{cab_file_source}\"").stdout
find_version(stdout)
end
@@ -85,22 +115,21 @@ class Chef
# returns a hash of package state information given the output of dism /get-packages
# expected keys: package_identity
def parse_dism_get_packages(text)
- packages = Array.new
+ packages = []
text.each_line do |line|
key, value = line.split(":") if line.start_with?("Package Identity")
- unless key.nil? || value.nil?
- package = Hash.new
- package[key.downcase.strip.tr(" ", "_")] = value.strip.chomp
- packages << package
- end
+ next if key.nil? || value.nil?
+ package = {}
+ package[key.downcase.strip.tr(" ", "_")] = value.strip.chomp
+ packages << package
end
packages
end
# returns a hash of package information given the output of dism /get-packageinfo
def parse_dism_get_package_info(text)
- package_data = Hash.new
- errors = Array.new
+ package_data = {}
+ errors = []
in_section = false
section_headers = [ "Package information", "Custom Properties", "Features" ]
text.each_line do |line|
@@ -112,7 +141,7 @@ class Chef
v = $2 # has to be first or the gsub below replaces this variable
k = $1.downcase.strip.tr(" ", "_")
if in_section
- package_data[in_section] = Hash.new unless package_data[in_section]
+ package_data[in_section] = {} unless package_data[in_section]
package_data[in_section][k] = v
else
package_data[k] = v
@@ -132,7 +161,7 @@ class Chef
end
def split_package_identity(identity)
- data = Hash.new
+ data = {}
data["name"], data["publisher"], data["arch"], data["resource_id"], data["version"] = identity.split("~")
data
end
diff --git a/lib/chef/provider/package/chocolatey.rb b/lib/chef/provider/package/chocolatey.rb
index 36bc170590..29b9f0d322 100644
--- a/lib/chef/provider/package/chocolatey.rb
+++ b/lib/chef/provider/package/chocolatey.rb
@@ -30,8 +30,8 @@ class Chef
# Declare that our arguments should be arrays
use_multipackage_api
- PATHFINDING_POWERSHELL_COMMAND = "[System.Environment]::GetEnvironmentVariable('ChocolateyInstall', 'MACHINE')"
- CHOCO_MISSING_MSG = <<-EOS
+ PATHFINDING_POWERSHELL_COMMAND = "[System.Environment]::GetEnvironmentVariable('ChocolateyInstall', 'MACHINE')".freeze
+ CHOCO_MISSING_MSG = <<-EOS.freeze
Could not locate your Chocolatey install. To install chocolatey, we recommend
the 'chocolatey' cookbook (https://github.com/chocolatey/chocolatey-cookbook).
If Chocolatey is installed, ensure that the 'ChocolateyInstall' environment
@@ -59,8 +59,8 @@ EOS
# so we want to assert candidates exist for the alternate source
requirements.assert(:upgrade, :install) do |a|
a.assertion { candidates_exist_for_all_uninstalled? }
- a.failure_message(Chef::Exceptions::Package, "No candidate version available for #{packages_missing_candidates.join(", ")}")
- a.whyrun("Assuming a repository that offers #{packages_missing_candidates.join(", ")} would have been configured")
+ a.failure_message(Chef::Exceptions::Package, "No candidate version available for #{packages_missing_candidates.join(', ')}")
+ a.whyrun("Assuming a repository that offers #{packages_missing_candidates.join(', ')} would have been configured")
end
end
@@ -84,7 +84,7 @@ EOS
# choco does not support installing multiple packages with version pins
name_has_versions.each do |name, version|
- choco_command("install -y -version", version, cmd_args, name)
+ choco_command("install -y --version", version, cmd_args, name)
end
# but we can do all the ones without version pins at once
@@ -106,7 +106,7 @@ EOS
# choco does not support installing multiple packages with version pins
name_has_versions.each do |name, version|
- choco_command("upgrade -y -version", version, cmd_args, name)
+ choco_command("upgrade -y --version", version, cmd_args, name)
end
# but we can do all the ones without version pins at once
@@ -133,12 +133,11 @@ EOS
end
# Choco does not have dpkg's distinction between purge and remove
- alias_method :purge_package, :remove_package
+ alias purge_package remove_package
# Override the superclass check. The semantics for our new_resource.source is not files to
# install from, but like the rubygem provider's sources which are more like repos.
- def check_resource_semantics!
- end
+ def check_resource_semantics!; end
private
@@ -160,7 +159,7 @@ EOS
def choco_install_path
@choco_install_path ||= powershell_out!(
PATHFINDING_POWERSHELL_COMMAND
- ).stdout.chomp
+ ).stdout.chomp
end
# Helper to dispatch a choco command through shell_out using the timeout
@@ -169,7 +168,7 @@ EOS
# @param args [String] variable number of string arguments
# @return [Mixlib::ShellOut] object returned from shell_out!
def choco_command(*args)
- shell_out_with_timeout!(args_to_string(choco_exe, *args))
+ shell_out_with_timeout!(args_to_string(choco_exe, *args), returns: new_resource.returns)
end
# Use the available_packages Hash helper to create an array suitable for
@@ -236,6 +235,7 @@ EOS
available[name] = desired_name_versions[name] || raw[name]
end
end
+ @available_packages
end
# Installed packages in chocolatey as a Hash of names mapped to versions
@@ -244,6 +244,7 @@ EOS
# @return [Hash] name-to-version mapping of installed packages
def installed_packages
@installed_packages ||= Hash[*parse_list_output("list -l -r").flatten]
+ @installed_packages
end
# Helper to convert choco.exe list output to a Hash
@@ -266,7 +267,7 @@ EOS
# @param names [Array] original mixed case names
# @return [Array] same names in lower case
def lowercase_names(names)
- names.map { |name| name.downcase }
+ names.map(&:downcase)
end
end
end
diff --git a/lib/chef/provider/package/dnf.rb b/lib/chef/provider/package/dnf.rb
new file mode 100644
index 0000000000..c551ae7cb0
--- /dev/null
+++ b/lib/chef/provider/package/dnf.rb
@@ -0,0 +1,185 @@
+#
+# Copyright:: Copyright 2016-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 "chef/provider/package"
+require "chef/resource/dnf_package"
+require "chef/mixin/which"
+require "chef/mixin/shell_out"
+require "chef/mixin/get_source_from_package"
+require "chef/provider/package/dnf/python_helper"
+require "chef/provider/package/dnf/version"
+
+class Chef
+ class Provider
+ class Package
+ class Dnf < Chef::Provider::Package
+ extend Chef::Mixin::Which
+ extend Chef::Mixin::ShellOut
+ include Chef::Mixin::GetSourceFromPackage
+
+ allow_nils
+ use_multipackage_api
+ use_package_name_for_source
+
+ provides :package, platform_family: %w{rhel fedora} do
+ which("dnf") && shell_out("rpm -q dnf").stdout =~ /^dnf-[1-9]/
+ end
+
+ provides :dnf_package, os: "linux"
+
+ #
+ # Most of the magic in this class happens in the python helper script. The ruby side of this
+ # provider knows only enough to translate Chef-style new_resource name+package+version into
+ # a request to the python side. The python side is then responsible for knowing everything
+ # about RPMs and what is installed and what is available. The ruby side of this class should
+ # remain a lightweight translation layer to translate Chef requests into RPC requests to
+ # python. This class knows nothing about how to compare RPM versions, and does not maintain
+ # any cached state of installed/available versions and should be kept that way.
+ #
+ def python_helper
+ @python_helper ||= PythonHelper.instance
+ end
+
+ def load_current_resource
+ flushcache if new_resource.flush_cache[:before]
+
+ @current_resource = Chef::Resource::DnfPackage.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
+ current_resource.version(get_current_versions)
+
+ current_resource
+ end
+
+ def define_resource_requirements
+ requirements.assert(:install, :upgrade, :remove, :purge) do |a|
+ a.assertion { !new_resource.source || ::File.exist?(new_resource.source) }
+ a.failure_message Chef::Exceptions::Package, "Package #{new_resource.package_name} not found: #{new_resource.source}"
+ a.whyrun "assuming #{new_resource.source} would have previously been created"
+ end
+
+ super
+ end
+
+ def candidate_version
+ package_name_array.each_with_index.map do |pkg, i|
+ available_version(i).version_with_arch
+ end
+ end
+
+ def get_current_versions
+ package_name_array.each_with_index.map do |pkg, i|
+ installed_version(i).version_with_arch
+ end
+ end
+
+ def install_package(names, versions)
+ if new_resource.source
+ dnf(options, "-y install", new_resource.source)
+ else
+ resolved_names = names.each_with_index.map { |name, i| available_version(i).to_s unless name.nil? }
+ dnf(options, "-y install", resolved_names)
+ end
+ flushcache
+ end
+
+ # dnf upgrade does not work on uninstalled packaged, while install will upgrade
+ alias upgrade_package install_package
+
+ def remove_package(names, versions)
+ resolved_names = names.each_with_index.map { |name, i| installed_version(i).to_s unless name.nil? }
+ dnf(options, "-y remove", resolved_names)
+ flushcache
+ end
+
+ alias purge_package remove_package
+
+ action :flush_cache do
+ flushcache
+ end
+
+ private
+
+ def resolve_source_to_version_obj
+ shell_out_with_timeout!("rpm -qp --queryformat '%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n' #{new_resource.source}").stdout.each_line do |line|
+ # this is another case of committing the sin of doing some lightweight mangling of RPM versions in ruby -- but the output of the rpm command
+ # does not match what the dnf library accepts.
+ case line
+ when /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/
+ return Version.new($1, "#{$2 == '(none)' ? '0' : $2}:#{$3}-#{$4}", $5)
+ end
+ end
+ end
+
+ # @returns Array<Version>
+ def available_version(index)
+ @available_version ||= []
+
+ @available_version[index] ||= if new_resource.source
+ resolve_source_to_version_obj
+ else
+ python_helper.query(:whatavailable, package_name_array[index], safe_version_array[index], safe_arch_array[index])
+ end
+
+ @available_version[index]
+ end
+
+ # @returns Array<Version>
+ def installed_version(index)
+ @installed_version ||= []
+ @installed_version[index] ||= if new_resource.source
+ python_helper.query(:whatinstalled, available_version(index).name, safe_version_array[index], safe_arch_array[index])
+ else
+ python_helper.query(:whatinstalled, package_name_array[index], safe_version_array[index], safe_arch_array[index])
+ end
+ @installed_version[index]
+ end
+
+ # cache flushing is accomplished by simply restarting the python helper. this produces a roughly
+ # 15% hit to the runtime of installing/removing/upgrading packages. correctly using multipackage
+ # array installs (and the multipackage cookbook) can produce 600% improvements in runtime.
+ def flushcache
+ python_helper.restart
+ end
+
+ def dnf(*args)
+ shell_out_with_timeout!(a_to_s("dnf", *args))
+ end
+
+ def safe_version_array
+ if new_resource.version.is_a?(Array)
+ new_resource.version
+ elsif new_resource.version.nil?
+ package_name_array.map { nil }
+ else
+ [ new_resource.version ]
+ end
+ end
+
+ def safe_arch_array
+ if new_resource.arch.is_a?(Array)
+ new_resource.arch
+ elsif new_resource.arch.nil?
+ package_name_array.map { nil }
+ else
+ [ new_resource.arch ]
+ end
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/dnf/dnf_helper.py b/lib/chef/provider/package/dnf/dnf_helper.py
new file mode 100644
index 0000000000..ef08bb54c2
--- /dev/null
+++ b/lib/chef/provider/package/dnf/dnf_helper.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
+
+import sys
+import dnf
+import hawkey
+import signal
+import os
+import json
+
+base = None
+
+def get_sack():
+ global base
+ if base is None:
+ base = dnf.Base()
+ base.read_all_repos()
+ base.fill_sack()
+ return base.sack
+
+# FIXME: leaks memory and does not work
+def flushcache():
+ try:
+ os.remove('/var/cache/dnf/@System.solv')
+ except OSError:
+ pass
+ get_sack().load_system_repo(build_cache=True)
+
+def query(command):
+ sack = get_sack()
+
+ subj = dnf.subject.Subject(command['provides'])
+ q = subj.get_best_query(sack, with_provides=True)
+
+ if command['action'] == "whatinstalled":
+ q = q.installed()
+
+ if command['action'] == "whatavailable":
+ q = q.available()
+
+ if 'epoch' in command:
+ q = q.filterm(epoch=int(command['epoch']))
+ if 'version' in command:
+ q = q.filterm(version__glob=command['version'])
+ if 'release' in command:
+ q = q.filterm(release__glob=command['release'])
+
+ if 'arch' in command:
+ q = q.filterm(arch__glob=command['arch'])
+
+ # only apply the default arch query filter if it returns something
+ archq = q.filter(arch=[ 'noarch', hawkey.detect_arch() ])
+ if len(archq.run()) > 0:
+ q = archq
+
+ pkgs = q.latest(1).run()
+
+ if not pkgs:
+ sys.stdout.write('{} nil nil\n'.format(command['provides'].split().pop(0)))
+ else:
+ # make sure we picked the package with the highest version
+ pkgs.sort
+ pkg = pkgs.pop()
+ sys.stdout.write('{} {}:{}-{} {}\n'.format(pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch))
+
+# the design of this helper is that it should try to be 'brittle' and fail hard and exit in order
+# to keep process tables clean. additional error handling should probably be added to the retry loop
+# on the ruby side.
+def exit_handler(signal, frame):
+ sys.exit(0)
+
+signal.signal(signal.SIGINT, exit_handler)
+signal.signal(signal.SIGHUP, exit_handler)
+signal.signal(signal.SIGPIPE, exit_handler)
+signal.signal(signal.SIGCHLD, exit_handler)
+
+while 1:
+ # kill self if we get orphaned (tragic)
+ ppid = os.getppid()
+ if ppid == 1:
+ sys.exit(0)
+ line = sys.stdin.readline()
+ command = json.loads(line)
+ if command['action'] == "whatinstalled":
+ query(command)
+ elif command['action'] == "whatavailable":
+ query(command)
+ elif command['action'] == "flushcache":
+ flushcache()
+ else:
+ raise RuntimeError("bad command")
diff --git a/lib/chef/provider/package/dnf/python_helper.rb b/lib/chef/provider/package/dnf/python_helper.rb
new file mode 100644
index 0000000000..04f0298861
--- /dev/null
+++ b/lib/chef/provider/package/dnf/python_helper.rb
@@ -0,0 +1,157 @@
+#
+# Copyright:: Copyright 2016-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 "chef/mixin/which"
+require "chef/mixin/shell_out"
+require "chef/provider/package/dnf/version"
+require "timeout"
+
+class Chef
+ class Provider
+ class Package
+ class Dnf < Chef::Provider::Package
+ class PythonHelper
+ include Singleton
+ include Chef::Mixin::Which
+ include Chef::Mixin::ShellOut
+
+ attr_accessor :stdin
+ attr_accessor :stdout
+ attr_accessor :stderr
+ attr_accessor :wait_thr
+
+ DNF_HELPER = ::File.expand_path(::File.join(::File.dirname(__FILE__), "dnf_helper.py")).freeze
+
+ def dnf_command
+ @dnf_command ||= which("python", "python3", "python2", "python2.7") do |f|
+ shell_out("#{f} -c 'import dnf'").exitstatus == 0
+ end + " #{DNF_HELPER}"
+ end
+
+ def start
+ ENV["PYTHONUNBUFFERED"] = "1"
+ @stdin, @stdout, @stderr, @wait_thr = Open3.popen3(dnf_command)
+ end
+
+ def reap
+ unless wait_thr.nil?
+ Process.kill("KILL", wait_thr.pid) rescue nil
+ stdin.close unless stdin.nil?
+ stdout.close unless stdout.nil?
+ stderr.close unless stderr.nil?
+ wait_thr.value # this calls waitpit()
+ end
+ end
+
+ def check
+ start if stdin.nil?
+ end
+
+ # @returns Array<Version>
+ def query(action, provides, version = nil, arch = nil)
+ with_helper do
+ json = build_query(action, provides, version, arch)
+ Chef::Log.debug "sending '#{json}' to python helper"
+ stdin.syswrite json + "\n"
+ output = stdout.sysread(4096).chomp
+ Chef::Log.debug "got '#{output}' from python helper"
+ version = parse_response(output)
+ Chef::Log.debug "parsed #{version} from python helper"
+ version
+ end
+ end
+
+ def restart
+ reap
+ start
+ end
+
+ private
+
+ # i couldn't figure out how to decompose an evr on the python side, it seems reasonably
+ # painless to do it in ruby (generally massaging nevras in the ruby side is HIGHLY
+ # discouraged -- this is an "every rule has an exception" exception -- any additional
+ # functionality should probably trigger moving this regexp logic into python)
+ def add_version(hash, version)
+ epoch = nil
+ if version =~ /(\S+):(\S+)/
+ epoch = $1
+ version = $2
+ end
+ if version =~ /(\S+)-(\S+)/
+ version = $1
+ release = $2
+ end
+ hash["epoch"] = epoch unless epoch.nil?
+ hash["release"] = release unless release.nil?
+ hash["version"] = version
+ end
+
+ def build_query(action, provides, version, arch)
+ hash = { "action" => action }
+ hash["provides"] = provides
+ add_version(hash, version) unless version.nil?
+ hash["arch" ] = arch unless arch.nil?
+ FFI_Yajl::Encoder.encode(hash)
+ end
+
+ def parse_response(output)
+ array = output.split.map { |x| x == "nil" ? nil : x }
+ array.each_slice(3).map { |x| Version.new(*x) }.first
+ end
+
+ def drain_stderr
+ output = ""
+ until IO.select([stderr], nil, nil, 0).nil?
+ output += stderr.sysread(4096).chomp
+ end
+ output
+ rescue
+ # we must rescue EOFError, and we don't much care about errors on stderr anyway
+ output
+ end
+
+ def with_helper
+ max_retries ||= 5
+ ret = nil
+ Timeout.timeout(600) do
+ check
+ ret = yield
+ end
+ output = drain_stderr
+ unless output.empty?
+ Chef::Log.debug "discarding output on stderr from python helper: #{output}"
+ end
+ ret
+ rescue EOFError, Errno::EPIPE, Timeout::Error, Errno::ESRCH => e
+ output = drain_stderr
+ if ( max_retries -= 1 ) > 0
+ unless output.empty?
+ Chef::Log.debug "discarding output on stderr from python helper: #{output}"
+ end
+ restart
+ retry
+ else
+ raise e if output.empty?
+ raise "dnf-helper.py had stderr output:\n\n#{output}"
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/dnf/version.rb b/lib/chef/provider/package/dnf/version.rb
new file mode 100644
index 0000000000..3cff5b0437
--- /dev/null
+++ b/lib/chef/provider/package/dnf/version.rb
@@ -0,0 +1,56 @@
+#
+# Copyright:: Copyright 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
+ class Provider
+ class Package
+ class Dnf < Chef::Provider::Package
+
+ # helper class to assist in passing around name/version/arch triples
+ class Version
+ attr_accessor :name
+ attr_accessor :version
+ attr_accessor :arch
+
+ def initialize(name, version, arch)
+ @name = name
+ @version = version
+ @arch = arch
+ end
+
+ def to_s
+ "#{name}-#{version}.#{arch}"
+ end
+
+ def version_with_arch
+ "#{version}.#{arch}" unless version.nil?
+ end
+
+ def matches_name_and_arch?(other)
+ other.version == version && other.arch == arch
+ end
+
+ def ==(other)
+ name == other.name && version == other.version && arch == other.arch
+ end
+
+ alias eql? ==
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/dpkg.rb b/lib/chef/provider/package/dpkg.rb
index e57f58e052..89a57affac 100644
--- a/lib/chef/provider/package/dpkg.rb
+++ b/lib/chef/provider/package/dpkg.rb
@@ -74,17 +74,17 @@ class Chef
def install_package(name, version)
sources = name.map { |n| name_sources[n] }
Chef::Log.info("#{new_resource} installing package(s): #{name.join(' ')}")
- run_noninteractive("dpkg -i", new_resource.options, *sources)
+ run_noninteractive("dpkg", "-i", *options, *sources)
end
def remove_package(name, version)
Chef::Log.info("#{new_resource} removing package(s): #{name.join(' ')}")
- run_noninteractive("dpkg -r", new_resource.options, *name)
+ run_noninteractive("dpkg", "-r", *options, *name)
end
def purge_package(name, version)
Chef::Log.info("#{new_resource} purging packages(s): #{name.join(' ')}")
- run_noninteractive("dpkg -P", new_resource.options, *name)
+ run_noninteractive("dpkg", "-P", *options, *name)
end
def upgrade_package(name, version)
@@ -102,14 +102,13 @@ class Chef
end
# Override the superclass check. Multiple sources are required here.
- def check_resource_semantics!
- end
+ def check_resource_semantics!; end
private
def read_current_version_of_package(package_name)
Chef::Log.debug("#{new_resource} checking install state of #{package_name}")
- status = shell_out_with_timeout!("dpkg -s #{package_name}", returns: [0, 1])
+ status = shell_out_compact_timeout!("dpkg", "-s", package_name, returns: [0, 1])
package_installed = false
status.stdout.each_line do |line|
case line
@@ -125,7 +124,7 @@ class Chef
end
end
end
- return nil
+ nil
end
def get_current_version_from(array)
@@ -137,7 +136,7 @@ class Chef
# Runs command via shell_out_with_timeout with magic environment to disable
# interactive prompts.
def run_noninteractive(*command)
- shell_out_with_timeout!(a_to_s(*command), :env => { "DEBIAN_FRONTEND" => "noninteractive" })
+ shell_out_compact_timeout!(*command, env: { "DEBIAN_FRONTEND" => "noninteractive" })
end
# Returns true if all sources exist. Returns false if any do not, or if no
@@ -177,7 +176,7 @@ class Chef
begin
pkginfos = resolved_source_array.map do |src|
Chef::Log.debug("#{new_resource} checking #{src} dpkg status")
- status = shell_out_with_timeout!("dpkg-deb -W #{src}")
+ status = shell_out_compact_timeout!("dpkg-deb", "-W", src)
status.stdout
end
Hash[*package_name_array.zip(pkginfos).flatten]
diff --git a/lib/chef/provider/package/easy_install.rb b/lib/chef/provider/package/easy_install.rb
index 989f2ab9d2..cc915e606c 100644
--- a/lib/chef/provider/package/easy_install.rb
+++ b/lib/chef/provider/package/easy_install.rb
@@ -32,11 +32,11 @@ class Chef
begin
# first check to see if we can import it
- output = shell_out_with_timeout!("#{python_binary_path} -c \"import #{name}\"", :returns => [0, 1]).stderr
+ output = shell_out_compact_timeout!(python_binary_path, "-c", "import #{name}", returns: [0, 1]).stderr
if output.include? "ImportError"
# then check to see if its on the path
- output = shell_out_with_timeout!("#{python_binary_path} -c \"import sys; print sys.path\"", :returns => [0, 1]).stdout
- if output.downcase.include? "#{name.downcase}"
+ output = shell_out_compact_timeout!(python_binary_path, "-c", "import sys; print sys.path", returns: [0, 1]).stdout
+ if output.downcase.include? name.downcase.to_s
check = true
end
else
@@ -50,38 +50,38 @@ class Chef
end
def easy_install_binary_path
- path = @new_resource.easy_install_binary
+ path = new_resource.easy_install_binary
path ? path : "easy_install"
end
def python_binary_path
- path = @new_resource.python_binary
+ path = new_resource.python_binary
path ? path : "python"
end
def module_name
- m = @new_resource.module_name
- m ? m : @new_resource.name
+ m = new_resource.module_name
+ m ? m : new_resource.name
end
def load_current_resource
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
# get the currently installed version if installed
package_version = nil
if install_check(module_name)
begin
- output = shell_out_with_timeout!("#{python_binary_path} -c \"import #{module_name}; print #{module_name}.__version__\"").stdout
+ output = shell_out_compact_timeout!("#{python_binary_path} -c \"import #{module_name}; print #{module_name}.__version__\"").stdout
package_version = output.strip
rescue
- output = shell_out_with_timeout!("#{python_binary_path} -c \"import sys; print sys.path\"", :returns => [0, 1]).stdout
+ output = shell_out_compact_timeout!("#{python_binary_path} -c \"import sys; print sys.path\"", returns: [0, 1]).stdout
output_array = output.gsub(/[\[\]]/, "").split(/\s*,\s*/)
package_path = ""
output_array.each do |entry|
- if entry.downcase.include?(@new_resource.package_name)
+ if entry.downcase.include?(new_resource.package_name)
package_path = entry
end
end
@@ -91,29 +91,29 @@ class Chef
end
end
- if package_version == @new_resource.version
- Chef::Log.debug("#{@new_resource} at version #{@new_resource.version}")
- @current_resource.version(@new_resource.version)
+ if package_version == new_resource.version
+ Chef::Log.debug("#{new_resource} at version #{new_resource.version}")
+ current_resource.version(new_resource.version)
else
- Chef::Log.debug("#{@new_resource} at version #{package_version}")
- @current_resource.version(package_version)
+ Chef::Log.debug("#{new_resource} at version #{package_version}")
+ current_resource.version(package_version)
end
- @current_resource
+ current_resource
end
def candidate_version
return @candidate_version if @candidate_version
- # do a dry run to get the latest version
- result = shell_out_with_timeout!("#{easy_install_binary_path} -n #{@new_resource.package_name}", :returns => [0, 1])
+ # do a dry run to get the latest version
+ result = shell_out_compact_timeout!("#{easy_install_binary_path} -n #{new_resource.package_name}", returns: [0, 1])
@candidate_version = result.stdout[/(.*)Best match: (.*) (.*)$/, 3]
@candidate_version
end
def install_package(name, version)
- Chef.log_deprecation("The easy_install package provider is deprecated and will be removed in Chef 13.")
- run_command(:command => "#{easy_install_binary_path}#{expand_options(@new_resource.options)} \"#{name}==#{version}\"")
+ Chef.deprecated(:easy_install, "The easy_install package provider is deprecated and will be removed in Chef 13.")
+ shell_out_compact_timeout!(easy_install_binary_path, options, "#{name}==#{version}")
end
def upgrade_package(name, version)
@@ -121,8 +121,8 @@ class Chef
end
def remove_package(name, version)
- Chef.log_deprecation("The easy_install package provider is deprecated and will be removed in Chef 13.")
- run_command(:command => "#{easy_install_binary_path }#{expand_options(@new_resource.options)} -m #{name}")
+ Chef.deprecated(:easy_install, "The easy_install package provider is deprecated and will be removed in Chef 13.")
+ shell_out_compact_timeout!(easy_install_binary_path, options, "-m", name)
end
def purge_package(name, version)
diff --git a/lib/chef/provider/package/freebsd/base.rb b/lib/chef/provider/package/freebsd/base.rb
index 7104a71f70..64efe61bfb 100644
--- a/lib/chef/provider/package/freebsd/base.rb
+++ b/lib/chef/provider/package/freebsd/base.rb
@@ -47,7 +47,7 @@ class Chef
# Otherwise look up the path to the ports directory using 'whereis'
else
- whereis = shell_out_with_timeout!("whereis -s #{port}", :env => nil)
+ whereis = shell_out_compact_timeout!("whereis", "-s", port, env: nil)
unless path = whereis.stdout[/^#{Regexp.escape(port)}:\s+(.+)$/, 1]
raise Chef::Exceptions::Package, "Could not find port with the name #{port}"
end
@@ -56,9 +56,9 @@ class Chef
end
def makefile_variable_value(variable, dir = nil)
- options = dir ? { :cwd => dir } : {}
- make_v = shell_out_with_timeout!("make -V #{variable}", options.merge!(:env => nil, :returns => [0, 1]))
- make_v.exitstatus.zero? ? make_v.stdout.strip.split($\).first : nil # $\ is the line separator, i.e. newline.
+ options = dir ? { cwd: dir } : {}
+ make_v = shell_out_compact_timeout!("make", "-V", variable, options.merge!(env: nil, returns: [0, 1]))
+ make_v.exitstatus == 0 ? make_v.stdout.strip.split($OUTPUT_RECORD_SEPARATOR).first : nil # $\ is the line separator, i.e. newline.
end
end
@@ -67,19 +67,19 @@ class Chef
def initialize(*args)
super
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
end
def load_current_resource
- @current_resource.package_name(@new_resource.package_name)
+ current_resource.package_name(new_resource.package_name)
- @current_resource.version(current_installed_version)
- Chef::Log.debug("#{@new_resource} current version is #{@current_resource.version}") if @current_resource.version
+ current_resource.version(current_installed_version)
+ Chef::Log.debug("#{new_resource} current version is #{current_resource.version}") if current_resource.version
@candidate_version = candidate_version
- Chef::Log.debug("#{@new_resource} candidate version is #{@candidate_version}") if @candidate_version
+ Chef::Log.debug("#{new_resource} candidate version is #{@candidate_version}") if @candidate_version
- @current_resource
+ current_resource
end
end
diff --git a/lib/chef/provider/package/freebsd/pkg.rb b/lib/chef/provider/package/freebsd/pkg.rb
index 78d9449454..1d66d29be6 100644
--- a/lib/chef/provider/package/freebsd/pkg.rb
+++ b/lib/chef/provider/package/freebsd/pkg.rb
@@ -30,28 +30,28 @@ class Chef
include PortsHelper
def install_package(name, version)
- unless @current_resource.version
- case @new_resource.source
+ unless current_resource.version
+ case new_resource.source
when /^http/, /^ftp/
- if @new_resource.source =~ /\/$/
- shell_out_with_timeout!("pkg_add -r #{package_name}", :env => { "PACKAGESITE" => @new_resource.source, "LC_ALL" => nil }).status
+ if new_resource.source =~ /\/$/
+ shell_out_compact_timeout!("pkg_add", "-r", package_name, env: { "PACKAGESITE" => new_resource.source, "LC_ALL" => nil }).status
else
- shell_out_with_timeout!("pkg_add -r #{package_name}", :env => { "PACKAGEROOT" => @new_resource.source, "LC_ALL" => nil }).status
+ shell_out_compact_timeout!("pkg_add", "-r", package_name, env: { "PACKAGEROOT" => new_resource.source, "LC_ALL" => nil }).status
end
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
+ Chef::Log.debug("#{new_resource} installed from: #{new_resource.source}")
when /^\//
- shell_out_with_timeout!("pkg_add #{file_candidate_version_path}", :env => { "PKG_PATH" => @new_resource.source , "LC_ALL" => nil }).status
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
+ shell_out_compact_timeout!("pkg_add", file_candidate_version_path, env: { "PKG_PATH" => new_resource.source, "LC_ALL" => nil }).status
+ Chef::Log.debug("#{new_resource} installed from: #{new_resource.source}")
else
- shell_out_with_timeout!("pkg_add -r #{latest_link_name}", :env => nil).status
+ shell_out_compact_timeout!("pkg_add", "-r", latest_link_name, env: nil).status
end
end
end
def remove_package(name, version)
- shell_out_with_timeout!("pkg_delete #{package_name}-#{version || @current_resource.version}", :env => nil).status
+ shell_out_compact_timeout!("pkg_delete", "#{package_name}-#{version || current_resource.version}", env: nil).status
end
# The name of the package (without the version number) as understood by pkg_add and pkg_info.
@@ -63,7 +63,7 @@ class Chef
raise Chef::Exceptions::Package, "Unexpected form for PKGNAME variable in #{port_path}/Makefile"
end
else
- @new_resource.package_name
+ new_resource.package_name
end
end
@@ -72,12 +72,12 @@ class Chef
end
def current_installed_version
- pkg_info = shell_out_with_timeout!("pkg_info -E \"#{package_name}*\"", :env => nil, :returns => [0, 1])
+ pkg_info = shell_out_compact_timeout!("pkg_info", "-E", "#{package_name}*", env: nil, returns: [0, 1])
pkg_info.stdout[/^#{Regexp.escape(package_name)}-(.+)/, 1]
end
def candidate_version
- case @new_resource.source
+ case new_resource.source
when /^http/, /^ftp/
repo_candidate_version
when /^\//
@@ -88,7 +88,7 @@ class Chef
end
def file_candidate_version_path
- Dir[Chef::Util::PathHelper.escape_glob_dir("#{@new_resource.source}/#{@current_resource.package_name}") + "*"][-1].to_s
+ Dir[Chef::Util::PathHelper.escape_glob_dir("#{new_resource.source}/#{current_resource.package_name}") + "*"][-1].to_s
end
def file_candidate_version
@@ -104,7 +104,7 @@ class Chef
end
def port_path
- port_dir @new_resource.package_name
+ port_dir new_resource.package_name
end
end
diff --git a/lib/chef/provider/package/freebsd/pkgng.rb b/lib/chef/provider/package/freebsd/pkgng.rb
index de7bea6387..9a5f0e9472 100644
--- a/lib/chef/provider/package/freebsd/pkgng.rb
+++ b/lib/chef/provider/package/freebsd/pkgng.rb
@@ -25,46 +25,44 @@ class Chef
class Pkgng < Base
def install_package(name, version)
- unless @current_resource.version
- case @new_resource.source
+ unless current_resource.version
+ case new_resource.source
when /^(http|ftp|\/)/
- shell_out_with_timeout!("pkg add#{expand_options(@new_resource.options)} #{@new_resource.source}", :env => { "LC_ALL" => nil }).status
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
-
+ shell_out_compact_timeout!("pkg", "add", options, new_resource.source, env: { "LC_ALL" => nil }).status
+ Chef::Log.debug("#{new_resource} installed from: #{new_resource.source}")
else
- shell_out_with_timeout!("pkg install -y#{expand_options(@new_resource.options)} #{name}", :env => { "LC_ALL" => nil }).status
+ shell_out_compact_timeout!("pkg", "install", "-y", options, name, env: { "LC_ALL" => nil }).status
end
end
end
def remove_package(name, version)
- options = @new_resource.options && @new_resource.options.sub(repo_regex, "")
- options && !options.empty? || options = nil
- shell_out_with_timeout!("pkg delete -y#{expand_options(options)} #{name}#{version ? '-' + version : ''}", :env => nil).status
+ options_dup = options && options.map { |str| str.sub(repo_regex, "") }.reject!(&:empty?)
+ shell_out_compact_timeout!("pkg", "delete", "-y", options_dup, "#{name}#{version ? '-' + version : ''}", env: nil).status
end
def current_installed_version
- pkg_info = shell_out_with_timeout!("pkg info \"#{@new_resource.package_name}\"", :env => nil, :returns => [0, 70])
+ pkg_info = shell_out_compact_timeout!("pkg", "info", new_resource.package_name, env: nil, returns: [0, 70])
pkg_info.stdout[/^Version +: (.+)$/, 1]
end
def candidate_version
- @new_resource.source ? file_candidate_version : repo_candidate_version
+ new_resource.source ? file_candidate_version : repo_candidate_version
end
private
def file_candidate_version
- @new_resource.source[/#{Regexp.escape(@new_resource.package_name)}-(.+)\.txz/, 1]
+ new_resource.source[/#{Regexp.escape(new_resource.package_name)}-(.+)\.txz/, 1]
end
def repo_candidate_version
- if @new_resource.options && @new_resource.options.match(repo_regex)
- options = $1
+ if options && options.join(" ").match(repo_regex)
+ options = $1.split(" ")
end
- pkg_query = shell_out_with_timeout!("pkg rquery#{expand_options(options)} '%v' #{@new_resource.package_name}", :env => nil)
- pkg_query.exitstatus.zero? ? pkg_query.stdout.strip.split(/\n/).last : nil
+ pkg_query = shell_out_compact_timeout!("pkg", "rquery", options, "%v", new_resource.package_name, env: nil)
+ pkg_query.exitstatus == 0 ? pkg_query.stdout.strip.split(/\n/).last : nil
end
def repo_regex
diff --git a/lib/chef/provider/package/freebsd/port.rb b/lib/chef/provider/package/freebsd/port.rb
index 3eb3c5ab01..e87be4d304 100644
--- a/lib/chef/provider/package/freebsd/port.rb
+++ b/lib/chef/provider/package/freebsd/port.rb
@@ -26,20 +26,20 @@ class Chef
include PortsHelper
def install_package(name, version)
- shell_out_with_timeout!("make -DBATCH install clean", :timeout => 1800, :env => nil, :cwd => port_dir).status
+ shell_out_compact_timeout!("make", "-DBATCH", "install", "clean", timeout: 1800, env: nil, cwd: port_dir).status
end
def remove_package(name, version)
- shell_out_with_timeout!("make deinstall", :timeout => 300, :env => nil, :cwd => port_dir).status
+ shell_out_compact_timeout!("make", "deinstall", timeout: 300, env: nil, cwd: port_dir).status
end
def current_installed_version
- pkg_info = if @new_resource.supports_pkgng?
- shell_out_with_timeout!("pkg info \"#{@new_resource.package_name}\"", :env => nil, :returns => [0, 70])
+ pkg_info = if new_resource.supports_pkgng?
+ shell_out_compact_timeout!("pkg", "info", new_resource.package_name, env: nil, returns: [0, 70])
else
- shell_out_with_timeout!("pkg_info -E \"#{@new_resource.package_name}*\"", :env => nil, :returns => [0, 1])
+ shell_out_compact_timeout!("pkg_info", "-E", "#{new_resource.package_name}*", env: nil, returns: [0, 1])
end
- pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+)/, 1]
+ pkg_info.stdout[/^#{Regexp.escape(new_resource.package_name)}-(.+)/, 1]
end
def candidate_version
@@ -51,7 +51,7 @@ class Chef
end
def port_dir
- super(@new_resource.package_name)
+ super(new_resource.package_name)
end
end
end
diff --git a/lib/chef/provider/package/homebrew.rb b/lib/chef/provider/package/homebrew.rb
index a105f6d7d0..f4e19bc857 100644
--- a/lib/chef/provider/package/homebrew.rb
+++ b/lib/chef/provider/package/homebrew.rb
@@ -32,7 +32,7 @@ class Chef
include Chef::Mixin::HomebrewUser
def load_current_resource
- self.current_resource = Chef::Resource::Package.new(new_resource.name)
+ self.current_resource = Chef::Resource::HomebrewPackage.new(new_resource.name)
current_resource.package_name(new_resource.package_name)
current_resource.version(current_installed_version)
Chef::Log.debug("#{new_resource} current version is #{current_resource.version}") if current_resource.version
@@ -46,7 +46,7 @@ class Chef
def install_package(name, version)
unless current_resource.version == version
- brew("install", new_resource.options, name)
+ brew("install", options, name)
end
end
@@ -56,24 +56,25 @@ class Chef
if current_version.nil? || current_version.empty?
install_package(name, version)
elsif current_version != version
- brew("upgrade", new_resource.options, name)
+ brew("upgrade", options, name)
end
end
def remove_package(name, version)
if current_resource.version
- brew("uninstall", new_resource.options, name)
+ brew("uninstall", options, name)
end
end
# Homebrew doesn't really have a notion of purging, do a "force remove"
def purge_package(name, version)
- new_resource.options((new_resource.options || "") << " --force").strip
- remove_package(name, version)
+ if current_resource.version
+ brew("uninstall", "--force", options, name)
+ end
end
def brew(*args)
- get_response_from_command("brew #{args.join(' ')}")
+ get_response_from_command("brew", *args)
end
# We implement a querying method that returns the JSON-as-Hash
@@ -121,13 +122,13 @@ class Chef
private
- def get_response_from_command(command)
+ def get_response_from_command(*command)
homebrew_uid = find_homebrew_uid(new_resource.respond_to?(:homebrew_user) && new_resource.homebrew_user)
homebrew_user = Etc.getpwuid(homebrew_uid)
- Chef::Log.debug "Executing '#{command}' as user '#{homebrew_user.name}'"
+ Chef::Log.debug "Executing '#{command.join(' ')}' as user '#{homebrew_user.name}'"
# FIXME: this 1800 second default timeout should be deprecated
- output = shell_out_with_timeout!(command, :timeout => 1800, :user => homebrew_uid, :environment => { "HOME" => homebrew_user.dir, "RUBYOPT" => nil, "TMPDIR" => nil })
+ output = shell_out_compact_timeout!(*command, timeout: 1800, user: homebrew_uid, environment: { "HOME" => homebrew_user.dir, "RUBYOPT" => nil, "TMPDIR" => nil })
output.stdout.chomp
end
diff --git a/lib/chef/provider/package/ips.rb b/lib/chef/provider/package/ips.rb
index 85053d47f2..9666013cc3 100644
--- a/lib/chef/provider/package/ips.rb
+++ b/lib/chef/provider/package/ips.rb
@@ -1,7 +1,7 @@
#
# Author:: Jason J. W. Williams (<williamsjj@digitar.com>)
# Author:: Stephen Nelson-Smith (<sns@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");
@@ -36,45 +36,40 @@ class Chef
super
requirements.assert(:all_actions) do |a|
- a.assertion { ! @candidate_version.nil? }
- a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.package_name} not found"
- a.whyrun "Assuming package #{@new_resource.package_name} would have been made available."
+ a.assertion { !@candidate_version.nil? }
+ a.failure_message Chef::Exceptions::Package, "Package #{new_resource.package_name} not found"
+ a.whyrun "Assuming package #{new_resource.package_name} would have been made available."
end
end
def get_current_version
- shell_out_with_timeout("pkg info #{@new_resource.package_name}").stdout.each_line do |line|
+ shell_out_compact_timeout("pkg", "info", new_resource.package_name).stdout.each_line do |line|
return $1.split[0] if line =~ /^\s+Version: (.*)/
end
- return nil
+ nil
end
def get_candidate_version
- shell_out_with_timeout!("pkg info -r #{new_resource.package_name}").stdout.each_line do |line|
+ shell_out_compact_timeout!("pkg", "info", "-r", new_resource.package_name).stdout.each_line do |line|
return $1.split[0] if line =~ /Version: (.*)/
end
- return nil
+ nil
end
def load_current_resource
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
- Chef::Log.debug("Checking package status for #{@new_resource.name}")
- @current_resource.version(get_current_version)
+ @current_resource = Chef::Resource::IpsPackage.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
+ Chef::Log.debug("Checking package status for #{new_resource.name}")
+ current_resource.version(get_current_version)
@candidate_version = get_candidate_version
- @current_resource
+ current_resource
end
def install_package(name, version)
- package_name = "#{name}@#{version}"
- normal_command = "pkg#{expand_options(@new_resource.options)} install -q #{package_name}"
- command =
- if @new_resource.respond_to?(:accept_license) && @new_resource.accept_license
- normal_command.gsub("-q", "-q --accept")
- else
- normal_command
- end
- shell_out_with_timeout(command)
+ command = [ "pkg", options, "install", "-q" ]
+ command << "--accept" if new_resource.accept_license
+ command << "#{name}@#{version}"
+ shell_out_compact_timeout!(command)
end
def upgrade_package(name, version)
@@ -83,7 +78,7 @@ class Chef
def remove_package(name, version)
package_name = "#{name}@#{version}"
- shell_out_with_timeout!( "pkg#{expand_options(@new_resource.options)} uninstall -q #{package_name}" )
+ shell_out_compact_timeout!( "pkg", options, "uninstall", "-q", package_name )
end
end
end
diff --git a/lib/chef/provider/package/macports.rb b/lib/chef/provider/package/macports.rb
index 7bbc68aba8..ad4be00477 100644
--- a/lib/chef/provider/package/macports.rb
+++ b/lib/chef/provider/package/macports.rb
@@ -7,25 +7,25 @@ class Chef
provides :macports_package
def load_current_resource
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
- @current_resource.version(current_installed_version)
- Chef::Log.debug("#{@new_resource} current version is #{@current_resource.version}") if @current_resource.version
+ current_resource.version(current_installed_version)
+ Chef::Log.debug("#{new_resource} current version is #{current_resource.version}") if current_resource.version
@candidate_version = macports_candidate_version
- if !@new_resource.version && !@candidate_version
- raise Chef::Exceptions::Package, "Could not get a candidate version for this package -- #{@new_resource.name} does not seem to be a valid package!"
+ if !new_resource.version && !@candidate_version
+ raise Chef::Exceptions::Package, "Could not get a candidate version for this package -- #{new_resource.name} does not seem to be a valid package!"
end
- Chef::Log.debug("#{@new_resource} candidate version is #{@candidate_version}") if @candidate_version
+ Chef::Log.debug("#{new_resource} candidate version is #{@candidate_version}") if @candidate_version
- @current_resource
+ current_resource
end
def current_installed_version
- command = "port installed #{@new_resource.package_name}"
+ command = [ "port", "installed", new_resource.package_name ]
output = get_response_from_command(command)
response = nil
@@ -37,7 +37,7 @@ class Chef
end
def macports_candidate_version
- command = "port info --version #{@new_resource.package_name}"
+ command = [ "port", "info", "--version", new_resource.package_name ]
output = get_response_from_command(command)
match = output.match(/^version: (.+)$/)
@@ -46,37 +46,37 @@ class Chef
end
def install_package(name, version)
- unless @current_resource.version == version
- command = "port#{expand_options(@new_resource.options)} install #{name}"
- command << " @#{version}" if version && !version.empty?
- shell_out_with_timeout!(command)
+ unless current_resource.version == version
+ command = [ "port", options, "install", name ]
+ command << "@#{version}" if version && !version.empty?
+ shell_out_compact_timeout!(command)
end
end
def purge_package(name, version)
- command = "port#{expand_options(@new_resource.options)} uninstall #{name}"
- command << " @#{version}" if version && !version.empty?
- shell_out_with_timeout!(command)
+ command = [ "port", options, "uninstall", name ]
+ command << "@#{version}" if version && !version.empty?
+ shell_out_compact_timeout!(command)
end
def remove_package(name, version)
- command = "port#{expand_options(@new_resource.options)} deactivate #{name}"
- command << " @#{version}" if version && !version.empty?
+ command = [ "port", options, "deactivate", name ]
+ command << "@#{version}" if version && !version.empty?
- shell_out_with_timeout!(command)
+ shell_out_compact_timeout!(command)
end
def upgrade_package(name, version)
# Saving this to a variable -- weird rSpec behavior
# happens otherwise...
- current_version = @current_resource.version
+ current_version = current_resource.version
if current_version.nil? || current_version.empty?
# Macports doesn't like when you upgrade a package
# that hasn't been installed.
install_package(name, version)
elsif current_version != version
- shell_out_with_timeout!( "port#{expand_options(@new_resource.options)} upgrade #{name} @#{version}" )
+ shell_out_compact_timeout!( "port", options, "upgrade", name, "@#{version}" )
end
end
@@ -84,7 +84,7 @@ class Chef
def get_response_from_command(command)
output = nil
- status = shell_out_with_timeout(command)
+ status = shell_out_compact_timeout(command)
begin
output = status.stdout
rescue Exception
diff --git a/lib/chef/provider/package/msu.rb b/lib/chef/provider/package/msu.rb
new file mode 100644
index 0000000000..fe4a11461f
--- /dev/null
+++ b/lib/chef/provider/package/msu.rb
@@ -0,0 +1,162 @@
+#
+# Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
+# 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.
+#
+
+# msu_package leverages cab_package
+# The contents of msu file are extracted, which contains one or more cab files.
+# The extracted cab files are installed using Chef::Resource::Package::CabPackage
+# Reference: https://support.microsoft.com/en-in/kb/934307
+require "chef/provider/package"
+require "chef/resource/msu_package"
+require "chef/mixin/shell_out"
+require "chef/provider/package/cab"
+require "chef/util/path_helper"
+require "chef/mixin/uris"
+require "chef/mixin/checksum"
+
+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
+
+ provides :msu_package, os: "windows"
+
+ def load_current_resource
+ @current_resource = Chef::Resource::MsuPackage.new(new_resource.name)
+
+ # download file if source is a url
+ msu_file = uri_scheme?(new_resource.source) ? download_source_file : new_resource.source
+
+ # temp directory where the contents of msu file get extracted
+ @temp_directory = Dir.mktmpdir("chef")
+ extract_msu_contents(msu_file, @temp_directory)
+ @cab_files = read_cab_files_from_xml(@temp_directory)
+
+ if @cab_files.empty?
+ raise Chef::Exceptions::Package, "Corrupt MSU package: MSU package XML does not contain any cab file"
+ else
+ current_resource.version(get_current_versions)
+ end
+ current_resource
+ end
+
+ def get_current_versions
+ @cab_files.map do |cabfile|
+ cab_pkg = get_cab_package(cabfile)
+ cab_pkg.installed_version
+ end
+ end
+
+ def get_candidate_versions
+ @cab_files.map do |cabfile|
+ cab_pkg = get_cab_package(cabfile)
+ cab_pkg.package_version
+ end
+ end
+
+ def candidate_version
+ @candidate_version ||= get_candidate_versions
+ end
+
+ def get_cab_package(cab_file)
+ cab_resource = new_resource
+ cab_resource.source = cab_file
+ cab_pkg = Chef::Provider::Package::Cab.new(cab_resource, nil)
+ end
+
+ def download_source_file
+ source_resource.run_action(:create)
+ Chef::Log.debug("#{new_resource} fetched source file to #{source_resource.path}")
+ source_resource.path
+ end
+
+ def source_resource
+ @source_resource ||= declare_resource(:remote_file, new_resource.name) do
+ path default_download_cache_path
+ source new_resource.source
+ checksum new_resource.checksum
+ backup false
+ end
+ end
+
+ def default_download_cache_path
+ uri = ::URI.parse(new_resource.source)
+ filename = ::File.basename(::URI.unescape(uri.path))
+ file_cache_dir = Chef::FileCache.create_cache_path("package/")
+ Chef::Util::PathHelper.cleanpath("#{file_cache_dir}/#{filename}")
+ end
+
+ def install_package(name, version)
+ # use cab_package resource to install the extracted cab packages
+ @cab_files.each do |cab_file|
+ declare_resource(:cab_package, new_resource.name) do
+ source cab_file
+ action :install
+ end
+ end
+ end
+
+ def remove_package(name, version)
+ # use cab_package provider to remove the extracted cab packages
+ @cab_files.each do |cab_file|
+ declare_resource(:cab_package, new_resource.name) do
+ source cab_file
+ action :remove
+ end
+ end
+ end
+
+ def extract_msu_contents(msu_file, destination)
+ with_os_architecture(nil) do
+ shell_out_with_timeout!("#{ENV['SYSTEMROOT']}\\system32\\expand.exe -f:* #{msu_file} #{destination}")
+ end
+ end
+
+ # msu package can contain multiple cab files
+ # Reading cab files from xml to ensure the order of installation in case of multiple cab files
+ def read_cab_files_from_xml(msu_dir)
+ # get the file with .xml extension
+ xml_files = Dir.glob("#{msu_dir}/*.xml")
+ cab_files = []
+
+ if xml_files.empty?
+ raise Chef::Exceptions::Package, "Corrupt MSU package: MSU package doesn't contain any xml file"
+ else
+ # msu package contains only single xml file. So using xml_files.first is sufficient
+ doc = ::File.open(xml_files.first.to_s) { |f| REXML::Document.new f }
+ locations = doc.elements.each("unattend/servicing/package/source") { |element| puts element.attributes["location"] }
+ locations.each do |loc|
+ cab_files << msu_dir + "/" + loc.attribute("location").value.split("\\")[1]
+ end
+
+ cab_files
+ end
+ cab_files
+ end
+
+ def cleanup_after_converge
+ # delete the temp directory where the contents of msu file are extracted
+ FileUtils.rm_rf(@temp_directory) if Dir.exist?(@temp_directory)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/openbsd.rb b/lib/chef/provider/package/openbsd.rb
index 8043c01693..2614683fba 100644
--- a/lib/chef/provider/package/openbsd.rb
+++ b/lib/chef/provider/package/openbsd.rb
@@ -42,9 +42,9 @@ class Chef
end
def load_current_resource
- @current_resource.package_name(new_resource.package_name)
- @current_resource.version(installed_version)
- @current_resource
+ current_resource.package_name(new_resource.package_name)
+ current_resource.version(installed_version)
+ current_resource
end
def define_resource_requirements
@@ -68,11 +68,11 @@ class Chef
end
def install_package(name, version)
- unless @current_resource.version
+ unless current_resource.version
if parts = name.match(/^(.+?)--(.+)/) # use double-dash for stems with flavors, see man page for pkg_add
name = parts[1]
end
- shell_out_with_timeout!("pkg_add -r #{name}#{version_string(version)}", :env => { "PKG_PATH" => pkg_path }).status
+ shell_out_compact_timeout!("pkg_add", "-r", package_string(name, version), env: { "PKG_PATH" => pkg_path }).status
Chef::Log.debug("#{new_resource.package_name} installed")
end
end
@@ -81,18 +81,18 @@ class Chef
if parts = name.match(/^(.+?)--(.+)/)
name = parts[1]
end
- shell_out_with_timeout!("pkg_delete #{name}#{version_string(version)}", :env => nil).status
+ shell_out_compact_timeout!("pkg_delete", package_string(name, version), env: nil).status
end
private
def installed_version
- if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
- name = parts[1]
- else
- name = new_resource.package_name
- end
- pkg_info = shell_out_with_timeout!("pkg_info -e \"#{name}->0\"", :env => nil, :returns => [0, 1])
+ name = if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
+ parts[1]
+ else
+ new_resource.package_name
+ end
+ pkg_info = shell_out_compact_timeout!("pkg_info", "-e", "#{name}->0", env: nil, returns: [0, 1])
result = pkg_info.stdout[/^inst:#{Regexp.escape(name)}-(.+?)\s/, 1]
Chef::Log.debug("installed_version of '#{new_resource.package_name}' is '#{result}'")
result
@@ -101,12 +101,12 @@ class Chef
def candidate_version
@candidate_version ||= begin
results = []
- shell_out_with_timeout!("pkg_info -I \"#{new_resource.package_name}#{version_string(new_resource.version)}\"", :env => nil, :returns => [0, 1]).stdout.each_line do |line|
- if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
- results << line[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1]
- else
- results << line[/^#{Regexp.escape(new_resource.package_name)}-(.+?)\s/, 1]
- end
+ shell_out_compact_timeout!("pkg_info", "-I", package_string(new_resource.package_name, new_resource.version), env: nil, returns: [0, 1]).stdout.each_line do |line|
+ results << if parts = new_resource.package_name.match(/^(.+?)--(.+)/)
+ line[/^#{Regexp.escape(parts[1])}-(.+?)\s/, 1]
+ else
+ line[/^#{Regexp.escape(new_resource.package_name)}-(.+?)\s/, 1]
+ end
end
results = results.reject(&:nil?)
Chef::Log.debug("Candidate versions of '#{new_resource.package_name}' are '#{results}'")
@@ -121,13 +121,16 @@ class Chef
end
end
- def version_string(version)
- ver = ""
- ver += "-#{version}" if version
+ def package_string(name, version)
+ if version
+ "#{name}-#{version}"
+ else
+ name
+ end
end
def pkg_path
- ENV["PKG_PATH"] || "http://ftp.OpenBSD.org/pub/#{node["kernel"]["name"]}/#{node["kernel"]["release"]}/packages/#{node["kernel"]["machine"]}/"
+ ENV["PKG_PATH"] || "http://ftp.OpenBSD.org/pub/#{node['kernel']['name']}/#{node['kernel']['release']}/packages/#{node['kernel']['machine']}/"
end
end
diff --git a/lib/chef/provider/package/pacman.rb b/lib/chef/provider/package/pacman.rb
index bd8028d881..25683687b2 100644
--- a/lib/chef/provider/package/pacman.rb
+++ b/lib/chef/provider/package/pacman.rb
@@ -29,16 +29,16 @@ class Chef
provides :pacman_package, os: "linux"
def load_current_resource
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
- Chef::Log.debug("#{@new_resource} checking pacman for #{@new_resource.package_name}")
- status = shell_out_with_timeout("pacman -Qi #{@new_resource.package_name}")
+ Chef::Log.debug("#{new_resource} checking pacman for #{new_resource.package_name}")
+ status = shell_out_compact_timeout("pacman", "-Qi", new_resource.package_name)
status.stdout.each_line do |line|
case line
when /^Version(\s?)*: (.+)$/
- Chef::Log.debug("#{@new_resource} current version is #{$2}")
- @current_resource.version($2)
+ Chef::Log.debug("#{new_resource} current version is #{$2}")
+ current_resource.version($2)
end
end
@@ -46,7 +46,7 @@ class Chef
raise Chef::Exceptions::Package, "pacman failed - #{status.inspect}!"
end
- @current_resource
+ current_resource
end
def candidate_version
@@ -54,20 +54,20 @@ class Chef
repos = %w{extra core community}
- if ::File.exists?("/etc/pacman.conf")
+ if ::File.exist?("/etc/pacman.conf")
pacman = ::File.read("/etc/pacman.conf")
repos = pacman.scan(/\[(.+)\]/).flatten
end
package_repos = repos.map { |r| Regexp.escape(r) }.join("|")
- status = shell_out_with_timeout("pacman -Sl")
+ status = shell_out_compact_timeout("pacman", "-Sl")
status.stdout.each_line do |line|
case line
- when /^(#{package_repos}) #{Regexp.escape(@new_resource.package_name)} (.+)$/
- # $2 contains a string like "4.4.0-1" or "3.10-4 [installed]"
- # simply split by space and use first token
- @candidate_version = $2.split(" ").first
+ when /^(#{package_repos}) #{Regexp.escape(new_resource.package_name)} (.+)$/
+ # $2 contains a string like "4.4.0-1" or "3.10-4 [installed]"
+ # simply split by space and use first token
+ @candidate_version = $2.split(" ").first
end
end
@@ -76,14 +76,14 @@ class Chef
end
unless @candidate_version
- raise Chef::Exceptions::Package, "pacman does not have a version of package #{@new_resource.package_name}"
+ raise Chef::Exceptions::Package, "pacman does not have a version of package #{new_resource.package_name}"
end
@candidate_version
end
def install_package(name, version)
- shell_out_with_timeout!( "pacman --sync --noconfirm --noprogressbar#{expand_options(@new_resource.options)} #{name}" )
+ shell_out_compact_timeout!( "pacman", "--sync", "--noconfirm", "--noprogressbar", options, name)
end
def upgrade_package(name, version)
@@ -91,7 +91,7 @@ class Chef
end
def remove_package(name, version)
- shell_out_with_timeout!( "pacman --remove --noconfirm --noprogressbar#{expand_options(@new_resource.options)} #{name}" )
+ shell_out_compact_timeout!( "pacman", "--remove", "--noconfirm", "--noprogressbar", options, name )
end
def purge_package(name, version)
diff --git a/lib/chef/provider/package/paludis.rb b/lib/chef/provider/package/paludis.rb
index 557e7ebc22..0b57d05adf 100644
--- a/lib/chef/provider/package/paludis.rb
+++ b/lib/chef/provider/package/paludis.rb
@@ -28,38 +28,37 @@ class Chef
provides :paludis_package, os: "linux"
def load_current_resource
- @current_resource = Chef::Resource::Package.new(@new_resource.package_name)
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource = Chef::Resource::Package.new(new_resource.package_name)
+ current_resource.package_name(new_resource.package_name)
- Chef::Log.debug("Checking package status for #{@new_resource.package_name}")
+ Chef::Log.debug("Checking package status for #{new_resource.package_name}")
installed = false
re = Regexp.new("(.*)[[:blank:]](.*)[[:blank:]](.*)$")
- shell_out!("cave -L warning print-ids -M none -m \"#{@new_resource.package_name}\" -f \"%c/%p %v %r\n\"").stdout.each_line do |line|
+ shell_out_compact!("cave", "-L", "warning", "print-ids", "-M", "none", "-m", new_resource.package_name, "-f", "%c/%p %v %r\n").stdout.each_line do |line|
res = re.match(line)
- unless res.nil?
- case res[3]
- when "accounts", "installed-accounts"
- next
- when "installed"
- installed = true
- @current_resource.version(res[2])
- else
- @candidate_version = res[2]
- end
+ next if res.nil?
+ case res[3]
+ when "accounts", "installed-accounts"
+ next
+ when "installed"
+ installed = true
+ current_resource.version(res[2])
+ else
+ @candidate_version = res[2]
end
end
- @current_resource
+ current_resource
end
def install_package(name, version)
- if version
- pkg = "=#{name}-#{version}"
- else
- pkg = "#{@new_resource.package_name}"
- end
- shell_out!("cave -L warning resolve -x#{expand_options(@new_resource.options)} \"#{pkg}\"", :timeout => @new_resource.timeout)
+ pkg = if version
+ "=#{name}-#{version}"
+ else
+ new_resource.package_name.to_s
+ end
+ shell_out_compact_timeout!("cave", "-L", "warning", "resolve", "-x", options, pkg)
end
def upgrade_package(name, version)
@@ -67,13 +66,13 @@ class Chef
end
def remove_package(name, version)
- if version
- pkg = "=#{@new_resource.package_name}-#{version}"
- else
- pkg = "#{@new_resource.package_name}"
- end
+ pkg = if version
+ "=#{new_resource.package_name}-#{version}"
+ else
+ new_resource.package_name.to_s
+ end
- shell_out!("cave -L warning uninstall -x#{expand_options(@new_resource.options)} \"#{pkg}\"")
+ shell_out_compact!("cave", "-L", "warning", "uninstall", "-x", options, pkg)
end
def purge_package(name, version)
diff --git a/lib/chef/provider/package/portage.rb b/lib/chef/provider/package/portage.rb
index 52b46b04b4..fd96dfa47f 100644
--- a/lib/chef/provider/package/portage.rb
+++ b/lib/chef/provider/package/portage.rb
@@ -32,14 +32,14 @@ class Chef
PACKAGE_NAME_PATTERN = %r{(?:([^/]+)/)?([^/]+)}
def load_current_resource
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
- category, pkg = %r{^#{PACKAGE_NAME_PATTERN}$}.match(@new_resource.package_name)[1, 2]
+ category, pkg = /^#{PACKAGE_NAME_PATTERN}$/.match(new_resource.package_name)[1, 2]
globsafe_category = category ? Chef::Util::PathHelper.escape_glob_dir(category) : nil
globsafe_pkg = Chef::Util::PathHelper.escape_glob_dir(pkg)
- possibilities = Dir["/var/db/pkg/#{globsafe_category || "*"}/#{globsafe_pkg}-*"].map { |d| d.sub(%r{/var/db/pkg/}, "") }
+ possibilities = Dir["/var/db/pkg/#{globsafe_category || '*'}/#{globsafe_pkg}-*"].map { |d| d.sub(%r{/var/db/pkg/}, "") }
versions = possibilities.map do |entry|
if entry =~ %r{[^/]+/#{Regexp.escape(pkg)}\-(\d[\.\d]*[a-z]?((_(alpha|beta|pre|rc|p)\d*)*)?(-r\d+)?)}
[$&, $1]
@@ -47,17 +47,17 @@ class Chef
end.compact
if versions.size > 1
- atoms = versions.map { |v| v.first }.sort
+ atoms = versions.map(&:first).sort
categories = atoms.map { |v| v.split("/")[0] }.uniq
if !category && categories.size > 1
- raise Chef::Exceptions::Package, "Multiple packages found for #{@new_resource.package_name}: #{atoms.join(" ")}. Specify a category."
+ raise Chef::Exceptions::Package, "Multiple packages found for #{new_resource.package_name}: #{atoms.join(' ')}. Specify a category."
end
elsif versions.size == 1
- @current_resource.version(versions.first.last)
- Chef::Log.debug("#{@new_resource} current version #{$1}")
+ current_resource.version(versions.first.last)
+ Chef::Log.debug("#{new_resource} current version #{$1}")
end
- @current_resource
+ current_resource
end
def parse_emerge(package, txt)
@@ -67,25 +67,25 @@ class Chef
txt.each_line do |line|
if line =~ /\*\s+#{PACKAGE_NAME_PATTERN}/
found_package_name = $&.delete("*").strip
- if package =~ /\// #the category is specified
+ if package =~ /\// # the category is specified
if found_package_name == package
availables[found_package_name] = nil
end
- else #the category is not specified
+ else # the category is not specified
if found_package_name.split("/").last == package
availables[found_package_name] = nil
end
end
end
- if line =~ /Latest version available: (.*)/ && availables.has_key?(found_package_name)
+ if line =~ /Latest version available: (.*)/ && availables.key?(found_package_name)
availables[found_package_name] = $1.strip
end
end
if availables.size > 1
# shouldn't happen if a category is specified so just use `package`
- raise Chef::Exceptions::Package, "Multiple emerge results found for #{package}: #{availables.keys.join(" ")}. Specify a category."
+ raise Chef::Exceptions::Package, "Multiple emerge results found for #{package}: #{availables.keys.join(' ')}. Specify a category."
end
availables.values.first
@@ -94,8 +94,8 @@ class Chef
def candidate_version
return @candidate_version if @candidate_version
- status = shell_out("emerge --color n --nospinner --search #{@new_resource.package_name.split('/').last}")
- available, installed = parse_emerge(@new_resource.package_name, status.stdout)
+ status = shell_out_compact("emerge", "--color", "n", "--nospinner", "--search", new_resource.package_name.split("/").last)
+ available, installed = parse_emerge(new_resource.package_name, status.stdout)
@candidate_version = available
unless status.exitstatus == 0
@@ -113,7 +113,7 @@ class Chef
pkg = "~#{name}-#{$1}"
end
- shell_out!( "emerge -g --color n --nospinner --quiet#{expand_options(@new_resource.options)} #{pkg}" )
+ shell_out_compact!( "emerge", "-g", "--color", "n", "--nospinner", "--quiet", options, pkg )
end
def upgrade_package(name, version)
@@ -121,13 +121,13 @@ class Chef
end
def remove_package(name, version)
- if version
- pkg = "=#{@new_resource.package_name}-#{version}"
- else
- pkg = "#{@new_resource.package_name}"
- end
+ pkg = if version
+ "=#{new_resource.package_name}-#{version}"
+ else
+ new_resource.package_name.to_s
+ end
- shell_out!( "emerge --unmerge --color n --nospinner --quiet#{expand_options(@new_resource.options)} #{pkg}" )
+ shell_out_compact!( "emerge", "--unmerge", "--color", "n", "--nospinner", "--quiet", options, pkg )
end
def purge_package(name, version)
diff --git a/lib/chef/provider/package/powershell.rb b/lib/chef/provider/package/powershell.rb
new file mode 100644
index 0000000000..3912dd23af
--- /dev/null
+++ b/lib/chef/provider/package/powershell.rb
@@ -0,0 +1,114 @@
+# Author:: Dheeraj Dubey(dheeraj.dubey@msystechnologies.com)
+# 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/provider/package"
+require "chef/resource/powershell_package"
+require "chef/mixin/powershell_out"
+
+class Chef
+ class Provider
+ class Package
+ class Powershell < Chef::Provider::Package
+ include Chef::Mixin::PowershellOut
+
+ provides :powershell_package, os: "windows"
+
+ def load_current_resource
+ @current_resource = Chef::Resource::PowershellPackage.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
+ current_resource.version(build_current_versions)
+ current_resource
+ end
+
+ def define_resource_requirements
+ super
+ if powershell_out("$PSVersionTable.PSVersion.Major").stdout.strip.to_i < 5
+ raise "Minimum installed Powershell Version required is 5"
+ end
+ requirements.assert(:install) do |a|
+ a.assertion { candidates_exist_for_all_uninstalled? }
+ a.failure_message(Chef::Exceptions::Package, "No candidate version available for #{packages_missing_candidates.join(', ')}")
+ a.whyrun("Assuming a repository that offers #{packages_missing_candidates.join(', ')} would have been configured")
+ end
+ end
+
+ def candidate_version
+ @candidate_version ||= build_candidate_versions
+ end
+
+ # Installs the package specified with the version passed else latest version will be installed
+ def install_package(names, versions)
+ names.each_with_index do |name, index|
+ powershell_out("Install-Package '#{name}' -Force -ForceBootstrap -RequiredVersion #{versions[index]}", timeout: new_resource.timeout)
+ end
+ end
+
+ # Removes the package for the version passed and if no version is passed, then all installed versions of the package are removed
+ def remove_package(names, versions)
+ names.each_with_index do |name, index|
+ if versions && !versions[index].nil?
+ powershell_out( "Uninstall-Package '#{name}' -Force -ForceBootstrap -RequiredVersion #{versions[index]}", timeout: new_resource.timeout)
+ else
+ version = "0"
+ until version.empty?
+ version = powershell_out( "(Uninstall-Package '#{name}' -Force -ForceBootstrap | select version | Format-Table -HideTableHeaders | Out-String).Trim()", timeout: new_resource.timeout).stdout.strip
+ unless version.empty?
+ Chef::Log.info("Removed package '#{name}' with version #{version}")
+ end
+ end
+ end
+ end
+ end
+
+ # Returns array of available available online
+ def build_candidate_versions
+ versions = []
+ new_resource.package_name.each_with_index do |name, index|
+ version = if new_resource.version && !new_resource.version[index].nil?
+ powershell_out("(Find-Package '#{name}' -RequiredVersion #{new_resource.version[index]} -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", timeout: new_resource.timeout).stdout.strip
+ else
+ powershell_out("(Find-Package '#{name}' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", timeout: new_resource.timeout).stdout.strip
+ end
+ if version.empty?
+ version = nil
+ end
+ versions.push(version)
+ end
+ versions
+ end
+
+ # Returns version array of installed version on the system
+ def build_current_versions
+ version_list = []
+ new_resource.package_name.each_with_index do |name, index|
+ version = if new_resource.version && !new_resource.version[index].nil?
+ powershell_out("(Get-Package -Name '#{name}' -RequiredVersion #{new_resource.version[index]} -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", timeout: new_resource.timeout).stdout.strip
+ else
+ powershell_out("(Get-Package -Name '#{name}' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", timeout: new_resource.timeout).stdout.strip
+ end
+ if version.empty?
+ version = nil
+ end
+ version_list.push(version)
+ end
+ version_list
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/rpm.rb b/lib/chef/provider/package/rpm.rb
index 777cc6d209..1701886191 100644
--- a/lib/chef/provider/package/rpm.rb
+++ b/lib/chef/provider/package/rpm.rb
@@ -34,13 +34,13 @@ class Chef
requirements.assert(:all_actions) do |a|
a.assertion { @package_source_exists }
- a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}"
- a.whyrun "Assuming package #{@new_resource.name} would have been made available."
+ a.failure_message Chef::Exceptions::Package, "Package #{new_resource.name} not found: #{new_resource.source}"
+ a.whyrun "Assuming package #{new_resource.name} would have been made available."
end
requirements.assert(:all_actions) do |a|
a.assertion { !@rpm_status.nil? && (@rpm_status.exitstatus == 0 || @rpm_status.exitstatus == 1) }
a.failure_message Chef::Exceptions::Package, "Unable to determine current version due to RPM failure. Detail: #{@rpm_status.inspect}"
- a.whyrun "Assuming current version would have been determined for package#{@new_resource.name}."
+ a.whyrun "Assuming current version would have been determined for package#{new_resource.name}."
end
end
@@ -48,63 +48,63 @@ class Chef
@package_source_provided = true
@package_source_exists = true
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
- if @new_resource.source
- unless uri_scheme?(@new_resource.source) || ::File.exists?(@new_resource.source)
+ if new_resource.source
+ unless uri_scheme?(new_resource.source) || ::File.exist?(new_resource.source)
@package_source_exists = false
return
end
- Chef::Log.debug("#{@new_resource} checking rpm status")
- shell_out_with_timeout!("rpm -qp --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{@new_resource.source}").stdout.each_line do |line|
+ Chef::Log.debug("#{new_resource} checking rpm status")
+ shell_out_compact_timeout!("rpm", "-qp", "--queryformat", "%{NAME} %{VERSION}-%{RELEASE}\n", new_resource.source).stdout.each_line do |line|
case line
when /^(\S+)\s(\S+)$/
- @current_resource.package_name($1)
- @new_resource.version($2)
+ current_resource.package_name($1)
+ new_resource.version($2)
@candidate_version = $2
end
end
else
- if Array(@new_resource.action).include?(:install)
+ if Array(new_resource.action).include?(:install)
@package_source_exists = false
return
end
end
- Chef::Log.debug("#{@new_resource} checking install state")
- @rpm_status = shell_out_with_timeout("rpm -q --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{@current_resource.package_name}")
+ Chef::Log.debug("#{new_resource} checking install state")
+ @rpm_status = shell_out_compact_timeout("rpm", "-q", "--queryformat", "%{NAME} %{VERSION}-%{RELEASE}\n", current_resource.package_name)
@rpm_status.stdout.each_line do |line|
case line
when /^(\S+)\s(\S+)$/
- Chef::Log.debug("#{@new_resource} current version is #{$2}")
- @current_resource.version($2)
+ Chef::Log.debug("#{new_resource} current version is #{$2}")
+ current_resource.version($2)
end
end
- @current_resource
+ current_resource
end
def install_package(name, version)
- unless @current_resource.version
- shell_out_with_timeout!( "rpm #{@new_resource.options} -i #{@new_resource.source}" )
- else
+ if current_resource.version
if allow_downgrade
- shell_out_with_timeout!( "rpm #{@new_resource.options} -U --oldpackage #{@new_resource.source}" )
+ shell_out_compact_timeout!("rpm", options, "-U", "--oldpackage", new_resource.source)
else
- shell_out_with_timeout!( "rpm #{@new_resource.options} -U #{@new_resource.source}" )
+ shell_out_compact_timeout!("rpm", options, "-U", new_resource.source)
end
+ else
+ shell_out_compact_timeout!("rpm", options, "-i", new_resource.source)
end
end
- alias_method :upgrade_package, :install_package
+ alias upgrade_package install_package
def remove_package(name, version)
if version
- shell_out_with_timeout!( "rpm #{@new_resource.options} -e #{name}-#{version}" )
+ shell_out_compact_timeout!("rpm", options, "-e", "#{name}-#{version}")
else
- shell_out_with_timeout!( "rpm #{@new_resource.options} -e #{name}" )
+ shell_out_compact_timeout!("rpm", options, "-e", name)
end
end
diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb
index 7b9ae909c0..1019b8d3fa 100644
--- a/lib/chef/provider/package/rubygems.rb
+++ b/lib/chef/provider/package/rubygems.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2008-2016, 2010-2016 Chef Software, Inc.
+# Copyright:: Copyright 2008-2016, 2010-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -47,7 +47,7 @@ class Chef
# alternate value and overwrite it with the defaults.
Gem.configuration
- DEFAULT_UNINSTALLER_OPTS = { :ignore => true, :executables => true }
+ DEFAULT_UNINSTALLER_OPTS = { ignore: true, executables: true }.freeze
##
# The paths where rubygems should search for installed gems.
@@ -133,11 +133,11 @@ class Chef
def candidate_version_from_file(gem_dependency, source)
spec = spec_from_file(source)
if spec.satisfies_requirement?(gem_dependency)
- logger.debug { "#{@new_resource} found candidate gem version #{spec.version} from local gem package #{source}" }
+ logger.debug { "found candidate gem version #{spec.version} from local gem package #{source}" }
spec.version
else
# This is probably going to end badly...
- logger.warn { "#{@new_resource} gem package #{source} does not satisfy the requirements #{gem_dependency}" }
+ logger.warn { "gem package #{source} does not satisfy the requirements #{gem_dependency}" }
nil
end
end
@@ -178,11 +178,11 @@ class Chef
version = spec && spec.version
if version
- logger.debug { "#{@new_resource} found gem #{spec.name} version #{version} for platform #{spec.platform} from #{source}" }
+ logger.debug { "found gem #{spec.name} version #{version} for platform #{spec.platform} from #{source}" }
version
else
source_list = sources.compact.empty? ? "[#{Gem.sources.to_a.join(', ')}]" : "[#{sources.join(', ')}]"
- logger.warn { "#{@new_resource} failed to find gem #{gem_dependency} from #{source_list}" }
+ logger.warn { "failed to find gem #{gem_dependency} from #{source_list}" }
nil
end
end
@@ -285,7 +285,7 @@ class Chef
# shellout! is a fork/exec which won't work on windows
shell_style_paths = shell_out!("#{@gem_binary_location} env gempath").stdout
# on windows, the path separator is (usually? always?) semicolon
- paths = shell_style_paths.split(::File::PATH_SEPARATOR).map { |path| path.strip }
+ paths = shell_style_paths.split(::File::PATH_SEPARATOR).map(&:strip)
self.class.gempath_cache[@gem_binary_location] = paths
end
end
@@ -322,11 +322,11 @@ class Chef
self.class.platform_cache[@gem_binary_location]
else
gem_environment = shell_out!("#{@gem_binary_location} env").stdout
- if jruby = gem_environment[JRUBY_PLATFORM]
- self.class.platform_cache[@gem_binary_location] = ["ruby", Gem::Platform.new(jruby)]
- else
- self.class.platform_cache[@gem_binary_location] = Gem.platforms
- end
+ self.class.platform_cache[@gem_binary_location] = if jruby = gem_environment[JRUBY_PLATFORM]
+ ["ruby", Gem::Platform.new(jruby)]
+ else
+ Gem.platforms
+ end
end
end
@@ -365,17 +365,17 @@ class Chef
super
@cleanup_gem_env = true
if new_resource.gem_binary
- if new_resource.options && new_resource.options.kind_of?(Hash)
+ if new_resource.options && new_resource.options.is_a?(Hash)
msg = "options cannot be given as a hash when using an explicit gem_binary\n"
msg << "in #{new_resource} from #{new_resource.source_line}"
raise ArgumentError, msg
end
@gem_env = AlternateGemEnvironment.new(new_resource.gem_binary)
- Chef::Log.debug("#{@new_resource} using gem '#{new_resource.gem_binary}'")
- elsif is_omnibus? && (!@new_resource.instance_of? Chef::Resource::ChefGem)
+ Chef::Log.debug("#{new_resource} using gem '#{new_resource.gem_binary}'")
+ elsif is_omnibus? && (!new_resource.instance_of? Chef::Resource::ChefGem)
# Opscode Omnibus - The ruby that ships inside omnibus is only used for Chef
# Default to installing somewhere more functional
- if new_resource.options && new_resource.options.kind_of?(Hash)
+ if new_resource.options && new_resource.options.is_a?(Hash)
msg = [
"Gem options must be passed to gem_package as a string instead of a hash when",
"using this installation of Chef because it runs with its own packaged Ruby. A hash",
@@ -386,23 +386,23 @@ class Chef
raise ArgumentError, msg
end
gem_location = find_gem_by_path
- @new_resource.gem_binary gem_location
+ new_resource.gem_binary gem_location
@gem_env = AlternateGemEnvironment.new(gem_location)
- Chef::Log.debug("#{@new_resource} using gem '#{gem_location}'")
+ Chef::Log.debug("#{new_resource} using gem '#{gem_location}'")
else
@gem_env = CurrentGemEnvironment.new
@cleanup_gem_env = false
- Chef::Log.debug("#{@new_resource} using gem from running ruby environment")
+ Chef::Log.debug("#{new_resource} using gem from running ruby environment")
end
end
def is_omnibus?
if RbConfig::CONFIG["bindir"] =~ %r{/(opscode|chef|chefdk)/embedded/bin}
- Chef::Log.debug("#{@new_resource} detected omnibus installation in #{RbConfig::CONFIG['bindir']}")
+ Chef::Log.debug("#{new_resource} detected omnibus installation in #{RbConfig::CONFIG['bindir']}")
# Omnibus installs to a static path because of linking on unix, find it.
true
elsif RbConfig::CONFIG["bindir"].sub(/^[\w]:/, "") == "/opscode/chef/embedded/bin"
- Chef::Log.debug("#{@new_resource} detected omnibus installation in #{RbConfig::CONFIG['bindir']}")
+ Chef::Log.debug("#{new_resource} detected omnibus installation in #{RbConfig::CONFIG['bindir']}")
# windows, with the drive letter removed
true
else
@@ -411,25 +411,25 @@ class Chef
end
def find_gem_by_path
- Chef::Log.debug("#{@new_resource} searching for 'gem' binary in path: #{ENV['PATH']}")
+ Chef::Log.debug("#{new_resource} searching for 'gem' binary in path: #{ENV['PATH']}")
separator = ::File::ALT_SEPARATOR ? ::File::ALT_SEPARATOR : ::File::SEPARATOR
- path_to_first_gem = ENV["PATH"].split(::File::PATH_SEPARATOR).find { |path| ::File.exists?(path + separator + "gem") }
+ path_to_first_gem = ENV["PATH"].split(::File::PATH_SEPARATOR).find { |path| ::File.exist?(path + separator + "gem") }
raise Chef::Exceptions::FileNotFound, "Unable to find 'gem' binary in path: #{ENV['PATH']}" if path_to_first_gem.nil?
path_to_first_gem + separator + "gem"
end
def gem_dependency
- Gem::Dependency.new(@new_resource.package_name, @new_resource.version)
+ Gem::Dependency.new(new_resource.package_name, new_resource.version)
end
def source_is_remote?
- return true if @new_resource.source.nil?
- scheme = URI.parse(@new_resource.source).scheme
+ return true if new_resource.source.nil?
+ scheme = URI.parse(new_resource.source).scheme
# URI.parse gets confused by MS Windows paths with forward slashes.
scheme = nil if scheme =~ /^[a-z]$/
%w{http https}.include?(scheme)
rescue URI::InvalidURIError
- Chef::Log.debug("#{@new_resource} failed to parse source '#{@new_resource.source}' as a URI, assuming a local path")
+ Chef::Log.debug("#{new_resource} failed to parse source '#{new_resource.source}' as a URI, assuming a local path")
false
end
@@ -445,16 +445,16 @@ class Chef
# is the current version
if !matching_installed_versions.empty?
gemspec = matching_installed_versions.send(pos)
- logger.debug { "#{@new_resource} found installed gem #{gemspec.name} version #{gemspec.version} matching #{gem_dependency}" }
+ logger.debug { "#{new_resource} found installed gem #{gemspec.name} version #{gemspec.version} matching #{gem_dependency}" }
gemspec
# If no version matching the requirements exists, the latest installed
# version is the current version.
elsif !all_installed_versions.empty?
gemspec = all_installed_versions.send(pos)
- logger.debug { "#{@new_resource} newest installed version of gem #{gemspec.name} is #{gemspec.version}" }
+ logger.debug { "#{new_resource} newest installed version of gem #{gemspec.name} is #{gemspec.version}" }
gemspec
else
- logger.debug { "#{@new_resource} no installed version found for #{gem_dependency}" }
+ logger.debug { "#{new_resource} no installed version found for #{gem_dependency}" }
nil
end
end
@@ -470,21 +470,21 @@ class Chef
end
def gem_sources
- @new_resource.source ? Array(@new_resource.source) : nil
+ new_resource.source ? Array(new_resource.source) : nil
end
def load_current_resource
- @current_resource = Chef::Resource::Package::GemPackage.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource = Chef::Resource::Package::GemPackage.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
if current_spec = current_version
- @current_resource.version(current_spec.version.to_s)
+ current_resource.version(current_spec.version.to_s)
end
- @current_resource
+ current_resource
end
def cleanup_after_converge
if @cleanup_gem_env
- logger.debug { "#{@new_resource} resetting gem environment to default" }
+ logger.debug { "#{new_resource} resetting gem environment to default" }
Gem.clear_paths
end
end
@@ -494,7 +494,7 @@ class Chef
if source_is_remote?
@gem_env.candidate_version_from_remote(gem_dependency, *gem_sources).to_s
else
- @gem_env.candidate_version_from_file(gem_dependency, @new_resource.source).to_s
+ @gem_env.candidate_version_from_file(gem_dependency, new_resource.source).to_s
end
end
end
@@ -511,18 +511,18 @@ class Chef
# 2. shell out to `gem install` when a String of options is given
# 3. use gems API with options if a hash of options is given
def install_package(name, version)
- if source_is_remote? && @new_resource.gem_binary.nil?
- if @new_resource.options.nil?
- @gem_env.install(gem_dependency, :sources => gem_sources)
- elsif @new_resource.options.kind_of?(Hash)
- options = @new_resource.options
+ if source_is_remote? && new_resource.gem_binary.nil?
+ if new_resource.options.nil?
+ @gem_env.install(gem_dependency, sources: gem_sources)
+ elsif new_resource.options.is_a?(Hash)
+ options = new_resource.options
options[:sources] = gem_sources
@gem_env.install(gem_dependency, options)
else
install_via_gem_command(name, version)
end
- elsif @new_resource.gem_binary.nil?
- @gem_env.install(@new_resource.source)
+ elsif new_resource.gem_binary.nil?
+ @gem_env.install(new_resource.source)
else
install_via_gem_command(name, version)
end
@@ -530,22 +530,22 @@ class Chef
end
def gem_binary_path
- @new_resource.gem_binary || "gem"
+ new_resource.gem_binary || "gem"
end
def install_via_gem_command(name, version)
- if @new_resource.source =~ /\.gem$/i
- name = @new_resource.source
- elsif @new_resource.clear_sources
+ if 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}" || "")
+ src << (new_resource.source && " --source=#{new_resource.source}" || "")
else
- src = @new_resource.source && " --source=#{@new_resource.source} --source=#{Chef::Config[:rubygems_url]}"
+ src = new_resource.source && " --source=#{new_resource.source} --source=#{Chef::Config[:rubygems_url]}"
end
- if !version.nil? && version.length > 0
- shell_out_with_timeout!("#{gem_binary_path} install #{name} -q --no-rdoc --no-ri -v \"#{version}\"#{src}#{opts}", :env => nil)
+ 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)
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}#{opts}", env: nil)
end
end
@@ -554,11 +554,11 @@ class Chef
end
def remove_package(name, version)
- if @new_resource.gem_binary.nil?
- if @new_resource.options.nil?
+ if new_resource.gem_binary.nil?
+ if new_resource.options.nil?
@gem_env.uninstall(name, version)
- elsif @new_resource.options.kind_of?(Hash)
- @gem_env.uninstall(name, version, @new_resource.options)
+ elsif new_resource.options.is_a?(Hash)
+ @gem_env.uninstall(name, version, new_resource.options)
else
uninstall_via_gem_command(name, version)
end
@@ -569,9 +569,9 @@ class Chef
def uninstall_via_gem_command(name, version)
if version
- shell_out_with_timeout!("#{gem_binary_path} uninstall #{name} -q -x -I -v \"#{version}\"#{opts}", :env => nil)
+ shell_out_with_timeout!("#{gem_binary_path} uninstall #{name} -q -x -I -v \"#{version}\"#{opts}", env: nil)
else
- shell_out_with_timeout!("#{gem_binary_path} uninstall #{name} -q -x -I -a#{opts}", :env => nil)
+ shell_out_with_timeout!("#{gem_binary_path} uninstall #{name} -q -x -I -a#{opts}", env: nil)
end
end
@@ -582,7 +582,7 @@ class Chef
private
def opts
- expand_options(@new_resource.options)
+ expand_options(new_resource.options)
end
end
diff --git a/lib/chef/provider/package/smartos.rb b/lib/chef/provider/package/smartos.rb
index 3f09bef212..8e4368f7c1 100644
--- a/lib/chef/provider/package/smartos.rb
+++ b/lib/chef/provider/package/smartos.rb
@@ -33,24 +33,24 @@ class Chef
provides :smartos_package, os: "solaris2", platform_family: "smartos"
def load_current_resource
- Chef::Log.debug("#{@new_resource} loading current resource")
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
- check_package_state(@new_resource.package_name)
- @current_resource # modified by check_package_state
+ Chef::Log.debug("#{new_resource} loading current resource")
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
+ check_package_state(new_resource.package_name)
+ current_resource # modified by check_package_state
end
def check_package_state(name)
- Chef::Log.debug("#{@new_resource} checking package #{name}")
+ Chef::Log.debug("#{new_resource} checking package #{name}")
version = nil
- info = shell_out_with_timeout!("/opt/local/sbin/pkg_info", "-E", "#{name}*", :env => nil, :returns => [0, 1])
+ info = shell_out_compact_timeout!("/opt/local/sbin/pkg_info", "-E", "#{name}*", env: nil, returns: [0, 1])
if info.stdout
- version = info.stdout[/^#{@new_resource.package_name}-(.+)/, 1]
+ version = info.stdout[/^#{new_resource.package_name}-(.+)/, 1]
end
if version
- @current_resource.version(version)
+ current_resource.version(version)
end
end
@@ -58,7 +58,7 @@ class Chef
return @candidate_version if @candidate_version
name = nil
version = nil
- pkg = shell_out_with_timeout!("/opt/local/bin/pkgin", "se", new_resource.package_name, :env => nil, :returns => [0, 1])
+ pkg = shell_out_compact_timeout!("/opt/local/bin/pkgin", "se", new_resource.package_name, env: nil, returns: [0, 1])
pkg.stdout.each_line do |line|
case line
when /^#{new_resource.package_name}/
@@ -70,20 +70,20 @@ class Chef
end
def install_package(name, version)
- Chef::Log.debug("#{@new_resource} installing package #{name} version #{version}")
+ Chef::Log.debug("#{new_resource} installing package #{name} version #{version}")
package = "#{name}-#{version}"
- out = shell_out_with_timeout!("/opt/local/bin/pkgin", "-y", "install", package, :env => nil)
+ out = shell_out_compact_timeout!("/opt/local/bin/pkgin", "-y", "install", package, env: nil)
end
def upgrade_package(name, version)
- Chef::Log.debug("#{@new_resource} upgrading package #{name} version #{version}")
+ Chef::Log.debug("#{new_resource} upgrading package #{name} version #{version}")
install_package(name, version)
end
def remove_package(name, version)
- Chef::Log.debug("#{@new_resource} removing package #{name} version #{version}")
- package = "#{name}"
- out = shell_out_with_timeout!("/opt/local/bin/pkgin", "-y", "remove", package, :env => nil)
+ Chef::Log.debug("#{new_resource} removing package #{name} version #{version}")
+ package = name.to_s
+ out = shell_out_compact_timeout!("/opt/local/bin/pkgin", "-y", "remove", package, env: nil)
end
end
diff --git a/lib/chef/provider/package/solaris.rb b/lib/chef/provider/package/solaris.rb
index 1c393e6a20..5537127310 100644
--- a/lib/chef/provider/package/solaris.rb
+++ b/lib/chef/provider/package/solaris.rb
@@ -33,45 +33,45 @@ class Chef
# def initialize(*args)
# super
- # @current_resource = Chef::Resource::Package.new(@new_resource.name)
+ # @current_resource = Chef::Resource::Package.new(new_resource.name)
# end
def define_resource_requirements
super
requirements.assert(:install) do |a|
- a.assertion { @new_resource.source }
- a.failure_message Chef::Exceptions::Package, "Source for package #{@new_resource.name} required for action install"
+ a.assertion { new_resource.source }
+ a.failure_message Chef::Exceptions::Package, "Source for package #{new_resource.name} required for action install"
end
requirements.assert(:all_actions) do |a|
- a.assertion { !@new_resource.source || @package_source_found }
- a.failure_message Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}"
- a.whyrun "would assume #{@new_resource.source} would be have previously been made available"
+ a.assertion { !new_resource.source || @package_source_found }
+ a.failure_message Chef::Exceptions::Package, "Package #{new_resource.name} not found: #{new_resource.source}"
+ a.whyrun "would assume #{new_resource.source} would be have previously been made available"
end
end
def load_current_resource
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
+ @current_resource = Chef::Resource::Package.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
- if @new_resource.source
- @package_source_found = ::File.exists?(@new_resource.source)
+ if new_resource.source
+ @package_source_found = ::File.exist?(new_resource.source)
if @package_source_found
- Chef::Log.debug("#{@new_resource} checking pkg status")
- shell_out_with_timeout("pkginfo -l -d #{@new_resource.source} #{@new_resource.package_name}").stdout.each_line do |line|
+ Chef::Log.debug("#{new_resource} checking pkg status")
+ shell_out_compact_timeout("pkginfo", "-l", "-d", new_resource.source, new_resource.package_name).stdout.each_line do |line|
case line
when /VERSION:\s+(.+)/
- @new_resource.version($1)
+ new_resource.version($1)
end
end
end
end
- Chef::Log.debug("#{@new_resource} checking install state")
- status = shell_out_with_timeout("pkginfo -l #{@current_resource.package_name}")
+ Chef::Log.debug("#{new_resource} checking install state")
+ status = shell_out_compact_timeout("pkginfo", "-l", current_resource.package_name)
status.stdout.each_line do |line|
case line
when /VERSION:\s+(.+)/
- Chef::Log.debug("#{@new_resource} version #{$1} is already installed")
- @current_resource.version($1)
+ Chef::Log.debug("#{new_resource} version #{$1} is already installed")
+ current_resource.version($1)
end
end
@@ -79,56 +79,56 @@ class Chef
raise Chef::Exceptions::Package, "pkginfo failed - #{status.inspect}!"
end
- @current_resource
+ current_resource
end
def candidate_version
return @candidate_version if @candidate_version
- status = shell_out_with_timeout("pkginfo -l -d #{@new_resource.source} #{new_resource.package_name}")
+ status = shell_out_compact_timeout("pkginfo", "-l", "-d", new_resource.source, new_resource.package_name)
status.stdout.each_line do |line|
case line
when /VERSION:\s+(.+)/
@candidate_version = $1
- @new_resource.version($1)
- Chef::Log.debug("#{@new_resource} setting install candidate version to #{@candidate_version}")
+ new_resource.version($1)
+ Chef::Log.debug("#{new_resource} setting install candidate version to #{@candidate_version}")
end
end
unless status.exitstatus == 0
- raise Chef::Exceptions::Package, "pkginfo -l -d #{@new_resource.source} - #{status.inspect}!"
+ raise Chef::Exceptions::Package, "pkginfo -l -d #{new_resource.source} - #{status.inspect}!"
end
@candidate_version
end
def install_package(name, version)
- Chef::Log.debug("#{@new_resource} package install options: #{@new_resource.options}")
- if @new_resource.options.nil?
- if ::File.directory?(@new_resource.source) # CHEF-4469
- command = "pkgadd -n -d #{@new_resource.source} #{@new_resource.package_name}"
- else
- command = "pkgadd -n -d #{@new_resource.source} all"
- end
- shell_out_with_timeout!(command)
- Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}")
+ Chef::Log.debug("#{new_resource} package install options: #{options}")
+ if options.nil?
+ command = if ::File.directory?(new_resource.source) # CHEF-4469
+ [ "pkgadd", "-n", "-d", new_resource.source, new_resource.package_name ]
+ else
+ [ "pkgadd", "-n", "-d", new_resource.source, "all" ]
+ end
+ shell_out_compact_timeout!(command)
+ Chef::Log.debug("#{new_resource} installed version #{new_resource.version} from: #{new_resource.source}")
else
- if ::File.directory?(@new_resource.source) # CHEF-4469
- command = "pkgadd -n#{expand_options(@new_resource.options)} -d #{@new_resource.source} #{@new_resource.package_name}"
- else
- command = "pkgadd -n#{expand_options(@new_resource.options)} -d #{@new_resource.source} all"
- end
- shell_out_with_timeout!(command)
- Chef::Log.debug("#{@new_resource} installed version #{@new_resource.version} from: #{@new_resource.source}")
+ command = if ::File.directory?(new_resource.source) # CHEF-4469
+ [ "pkgadd", "-n", options, "-d", new_resource.source, new_resource.package_name ]
+ else
+ [ "pkgadd", "-n", options, "-d", new_resource.source, "all" ]
+ end
+ shell_out_compact_timeout!(*command)
+ Chef::Log.debug("#{new_resource} installed version #{new_resource.version} from: #{new_resource.source}")
end
end
- alias_method :upgrade_package, :install_package
+ alias upgrade_package install_package
def remove_package(name, version)
- if @new_resource.options.nil?
- shell_out_with_timeout!( "pkgrm -n #{name}" )
- Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}")
+ if options.nil?
+ shell_out_compact_timeout!( "pkgrm", "-n", name )
+ Chef::Log.debug("#{new_resource} removed version #{new_resource.version}")
else
- shell_out_with_timeout!( "pkgrm -n#{expand_options(@new_resource.options)} #{name}" )
- Chef::Log.debug("#{@new_resource} removed version #{@new_resource.version}")
+ shell_out_compact_timeout!( "pkgrm", "-n", options, name )
+ Chef::Log.debug("#{new_resource} removed version #{new_resource.version}")
end
end
diff --git a/lib/chef/provider/package/windows.rb b/lib/chef/provider/package/windows.rb
index b11bcf5192..ca9d1e813a 100644
--- a/lib/chef/provider/package/windows.rb
+++ b/lib/chef/provider/package/windows.rb
@@ -104,8 +104,8 @@ class Chef
return :nsis
end
- if io.tell() < filesize
- io.seek(io.tell() - overlap)
+ if io.tell < filesize
+ io.seek(io.tell - overlap)
end
end
@@ -195,7 +195,7 @@ class Chef
end
def downloadable_file_missing?
- !new_resource.source.nil? && uri_scheme?(new_resource.source) && !::File.exists?(source_location)
+ !new_resource.source.nil? && uri_scheme?(new_resource.source) && !::File.exist?(source_location)
end
def resource_for_provider
@@ -262,7 +262,7 @@ class Chef
if source_location.nil?
inferred_registry_type == :msi
else
- ::File.extname(source_location).casecmp(".msi").zero?
+ ::File.extname(source_location).casecmp(".msi") == 0
end
end
end
diff --git a/lib/chef/provider/package/windows/exe.rb b/lib/chef/provider/package/windows/exe.rb
index 60065d9019..0baea6bccd 100644
--- a/lib/chef/provider/package/windows/exe.rb
+++ b/lib/chef/provider/package/windows/exe.rb
@@ -69,10 +69,10 @@ class Chef
def remove_package
uninstall_version = new_resource.version || current_installed_version
uninstall_entries.select { |entry| [uninstall_version].flatten.include?(entry.display_version) }
- .map { |version| version.uninstall_string }.uniq.each do |uninstall_string|
- Chef::Log.debug("Registry provided uninstall string for #{new_resource} is '#{uninstall_string}'")
- shell_out!(uninstall_command(uninstall_string), { :timeout => new_resource.timeout, :returns => new_resource.returns })
- end
+ .map(&:uninstall_string).uniq.each do |uninstall_string|
+ Chef::Log.debug("Registry provided uninstall string for #{new_resource} is '#{uninstall_string}'")
+ shell_out!(uninstall_command(uninstall_string), timeout: new_resource.timeout, returns: new_resource.returns)
+ end
end
private
@@ -85,13 +85,13 @@ class Chef
" ",
unattended_flags,
].join
- %Q{start "" /wait #{uninstall_string} & exit %%%%ERRORLEVEL%%%%}
+ %{start "" /wait #{uninstall_string} & exit %%%%ERRORLEVEL%%%%}
end
def current_installed_version
@current_installed_version ||=
if uninstall_entries.count != 0
- uninstall_entries.map { |entry| entry.display_version }.uniq
+ uninstall_entries.map(&:display_version).uniq
end
end
diff --git a/lib/chef/provider/package/windows/msi.rb b/lib/chef/provider/package/windows/msi.rb
index ee3b2f7e8e..7e6048ce49 100644
--- a/lib/chef/provider/package/windows/msi.rb
+++ b/lib/chef/provider/package/windows/msi.rb
@@ -16,7 +16,7 @@
# limitations under the License.
#
-# TODO: Allow @new_resource.source to be a Product Code as a GUID for uninstall / network install
+# TODO: Allow new_resource.source to be a Product Code as a GUID for uninstall / network install
require "chef/win32/api/installer" if (RUBY_PLATFORM =~ /mswin|mingw32|windows/) && Chef::Platform.supports_msi?
require "chef/mixin/shell_out"
@@ -51,7 +51,7 @@ class Chef
get_installed_version(product_code)
else
if uninstall_entries.count != 0
- uninstall_entries.map { |entry| entry.display_version }.uniq
+ uninstall_entries.map(&:display_version).uniq
end
end
end
@@ -67,23 +67,23 @@ class Chef
def install_package
# We could use MsiConfigureProduct here, but we'll start off with msiexec
Chef::Log.debug("#{new_resource} installing MSI package '#{new_resource.source}'")
- shell_out!("msiexec /qn /i \"#{new_resource.source}\" #{expand_options(new_resource.options)}", { :timeout => new_resource.timeout, :returns => new_resource.returns })
+ shell_out!("msiexec /qn /i \"#{new_resource.source}\" #{expand_options(new_resource.options)}", timeout: new_resource.timeout, returns: new_resource.returns)
end
def remove_package
# We could use MsiConfigureProduct here, but we'll start off with msiexec
if !new_resource.source.nil? && ::File.exist?(new_resource.source)
Chef::Log.debug("#{new_resource} removing MSI package '#{new_resource.source}'")
- shell_out!("msiexec /qn /x \"#{new_resource.source}\" #{expand_options(new_resource.options)}", { :timeout => new_resource.timeout, :returns => new_resource.returns })
+ shell_out!("msiexec /qn /x \"#{new_resource.source}\" #{expand_options(new_resource.options)}", timeout: new_resource.timeout, returns: new_resource.returns)
else
uninstall_version = new_resource.version || installed_version
uninstall_entries.select { |entry| [uninstall_version].flatten.include?(entry.display_version) }
- .map { |version| version.uninstall_string }.uniq.each do |uninstall_string|
+ .map(&:uninstall_string).uniq.each do |uninstall_string|
uninstall_string = "msiexec /x #{uninstall_string.match(/{.*}/)}"
uninstall_string += expand_options(new_resource.options)
uninstall_string += " /q" unless uninstall_string.downcase =~ / \/q/
Chef::Log.debug("#{new_resource} removing MSI package version using '#{uninstall_string}'")
- shell_out!(uninstall_string, { :timeout => new_resource.timeout, :returns => new_resource.returns })
+ shell_out!(uninstall_string, timeout: new_resource.timeout, returns: new_resource.returns)
end
end
end
diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb
index 022fdcae09..d37aa1fb73 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-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");
@@ -27,12 +27,17 @@ class Chef
class Provider
class Package
class Yum < Chef::Provider::Package
+ include Chef::Mixin::GetSourceFromPackage
provides :package, platform_family: %w{rhel fedora}
provides :yum_package, os: "linux"
- include Chef::Mixin::GetSourceFromPackage
+ # Multipackage API
+ allow_nils
+ use_multipackage_api
+ use_package_name_for_source
+ # Overload the Package provider to keep track of the YumCache
def initialize(new_resource, run_context)
super
@@ -40,89 +45,60 @@ class Chef
@yum.yum_binary = yum_binary
end
- def yum_binary
- @yum_binary ||=
- begin
- yum_binary = new_resource.yum_binary if new_resource.is_a?(Chef::Resource::YumPackage)
- yum_binary ||= ::File.exist?("/usr/bin/yum-deprecated") ? "yum-deprecated" : "yum"
- end
- end
-
- # Extra attributes
- #
+ # @see Chef::Provider::Package#check_resource_semantics!
+ def check_resource_semantics!
+ super
- def arch_for_name(n)
- if @new_resource.respond_to?("arch")
- @new_resource.arch
- elsif @arch
- idx = package_name_array.index(n)
- as_array(@arch)[idx]
- else
- nil
+ if !new_resource.version.nil? && package_name_array.length != new_version_array.length
+ raise Chef::Exceptions::InvalidResourceSpecification, "Please provide a version for each package. Use `nil` for default version."
end
- end
- def arch
- if @new_resource.respond_to?("arch")
- @new_resource.arch
- else
- nil
+ if !new_resource.arch.nil? && package_name_array.length != safe_arch_array.length
+ raise Chef::Exceptions::InvalidResourceSpecification, "Please provide an architecture for each package. Use `nil` for default architecture."
end
end
- def set_arch(arch)
- if @new_resource.respond_to?("arch")
- @new_resource.arch(arch)
- end
- end
+ # @see Chef::Provider#define_resource_requirements
+ def define_resource_requirements
+ super
- def flush_cache
- if @new_resource.respond_to?("flush_cache")
- @new_resource.flush_cache
- else
- { :before => false, :after => false }
+ # Ensure that the source file (if specified) is present on the file system
+ requirements.assert(:install, :upgrade, :remove, :purge) do |a|
+ a.assertion { !new_resource.source || ::File.exist?(new_resource.source) }
+ a.failure_message Chef::Exceptions::Package, "Package #{new_resource.package_name} not found: #{new_resource.source}"
+ a.whyrun "assuming #{new_resource.source} would have previously been created"
end
end
- # Helpers
- #
-
- def yum_arch(arch)
- arch ? ".#{arch}" : nil
- end
+ # @see Chef::Provider#load_current_resource
+ def load_current_resource
+ @yum.reload if flush_cache[:before]
+ manage_extra_repo_control
- def yum_command(command)
- command = "#{yum_binary} #{command}"
- Chef::Log.debug("#{@new_resource}: yum command: \"#{command}\"")
- status = shell_out_with_timeout(command, { :timeout => Chef::Config[:yum_timeout] })
+ if new_resource.source
+ query_source_file
+ else
+ # At this point package_name could be:
+ #
+ # 1) a package name, eg: "foo"
+ # 2) a package name.arch, eg: "foo.i386"
+ # 3) or a dependency, eg: "foo >= 1.1"
+ #
+ # In the third case, we want to convert those dependency strings into
+ # packages that we can actually install
+ convert_dependency_strings_into_packages
- # This is fun: rpm can encounter errors in the %post/%postun scripts which aren't
- # considered fatal - meaning the rpm is still successfully installed. These issue
- # cause yum to emit a non fatal warning but still exit(1). As there's currently no
- # way to suppress this behavior and an exit(1) will break a Chef run we make an
- # effort to trap these and re-run the same install command - it will either fail a
- # second time or succeed.
- #
- # A cleaner solution would have to be done in python and better hook into
- # yum/rpm to handle exceptions as we see fit.
- if status.exitstatus == 1
- status.stdout.each_line do |l|
- # rpm-4.4.2.3 lib/psm.c line 2182
- if l =~ %r{^error: %(post|postun)\(.*\) scriptlet failed, exit status \d+$}
- Chef::Log.warn("#{@new_resource} caught non-fatal scriptlet issue: \"#{l}\". Can't trust yum exit status " +
- "so running install again to verify.")
- status = shell_out_with_timeout(command, { :timeout => Chef::Config[:yum_timeout] })
- break
- end
- end
+ # Fill out the rest of the details by querying the Yum Cache
+ query_yum_cache
end
- if status.exitstatus > 0
- command_output = "STDOUT: #{status.stdout}\nSTDERR: #{status.stderr}"
- raise Chef::Exceptions::Exec, "#{command} returned #{status.exitstatus}:\n#{command_output}"
- end
+ @current_resource = Chef::Resource::YumPackage.new(new_resource.name)
+ current_resource.package_name(new_resource.package_name)
+ current_resource.version(@installed_version)
+ current_resource
end
+ # @see Chef::Provider::Package#package_locked
def package_locked(name, version)
islocked = false
locked = shell_out_with_timeout!("yum versionlock")
@@ -132,26 +108,97 @@ class Chef
islocked = true
end
end
- return islocked
+ islocked
end
- # Standard Provider methods for Parent
+ #
+ # Package Action Classes
#
- def load_current_resource
- if flush_cache[:before]
- @yum.reload
+ # @see Chef::Provider::Package#install_package
+ def install_package(name, version)
+ if new_resource.source
+ yum_command("-d0 -e0 -y#{expand_options(new_resource.options)} localinstall #{new_resource.source}")
+ else
+ install_remote_package(name, version)
+ end
+
+ flush_cache[:after] ? @yum.reload : @yum.reload_installed
+ end
+
+ # @see Chef::Provider::Package#upgrade_package
+ def upgrade_package(name, version)
+ install_package(name, version)
+ end
+
+ # @see Chef::Provider::Package#remove_package
+ def remove_package(name, version)
+ remove_str = full_package_name(name, version).join(" ")
+ yum_command("-d0 -e0 -y#{expand_options(new_resource.options)} remove #{remove_str}")
+
+ flush_cache[:after] ? @yum.reload : @yum.reload_installed
+ end
+
+ # @see Chef::Provider::Package#purge_package
+ def purge_package(name, version)
+ remove_package(name, version)
+ end
+
+ # @see Chef::Provider::Package#lock_package
+ def lock_package(name, version)
+ lock_str = full_package_name(name, as_array(name).map { nil }).join(" ")
+ yum_command("-d0 -e0 -y#{expand_options(new_resource.options)} versionlock add #{lock_str}")
+ end
+
+ # @see Chef::Provider::Package#unlock_package
+ def unlock_package(name, version)
+ unlock_str = full_package_name(name, as_array(name).map { nil }).join(" ")
+ yum_command("-d0 -e0 -y#{expand_options(new_resource.options)} versionlock delete #{unlock_str}")
+ end
+
+ # Keep upgrades from trying to install an older candidate version. Can happen when a new
+ # version is installed then removed from a repository, now the older available version
+ # shows up as a viable install candidate.
+ #
+ # Can be done in upgrade_package but an upgraded from->to log message slips out
+ #
+ # Hacky - better overall solution? Custom compare in Package provider?
+ def action_upgrade
+ # Could be uninstalled or have no candidate
+ if current_resource.version.nil? || !candidate_version_array.any?
+ super
+ elsif candidate_version_array.zip(current_version_array).any? do |c, i|
+ RPMVersion.parse(c) > RPMVersion.parse(i)
+ end
+ super
+ else
+ Chef::Log.debug("#{new_resource} is at the latest version - nothing to do")
end
+ end
- if @new_resource.options
+ private
+
+ #
+ # System Level Yum Operations
+ #
+
+ def yum_binary
+ @yum_binary ||=
+ begin
+ yum_binary = new_resource.yum_binary if new_resource.is_a?(Chef::Resource::YumPackage)
+ yum_binary ||= ::File.exist?("/usr/bin/yum-deprecated") ? "yum-deprecated" : "yum"
+ end
+ end
+
+ # Enable or disable YumCache extra_repo_control
+ def manage_extra_repo_control
+ if new_resource.options
repo_control = []
- @new_resource.options.split.each do |opt|
- if opt =~ %r{--(enable|disable)repo=.+}
- repo_control << opt
- end
+ new_resource.options.split.each do |opt|
+ repo_control << opt if opt =~ /--(enable|disable)repo=.+/
end
- if repo_control.size > 0
+ if !repo_control.empty?
@yum.enable_extra_repo_control(repo_control.join(" "))
else
@yum.disable_extra_repo_control
@@ -159,105 +206,100 @@ class Chef
else
@yum.disable_extra_repo_control
end
+ end
- # At this point package_name could be:
- #
- # 1) a package name, eg: "foo"
- # 2) a package name.arch, eg: "foo.i386"
- # 3) or a dependency, eg: "foo >= 1.1"
+ # Query the Yum cache for information about potential packages
+ def query_yum_cache
+ installed_versions = []
+ candidate_versions = []
- # Check if we have name or name+arch which has a priority over a dependency
- package_name_array.each_with_index do |n, index|
- unless @yum.package_available?(n)
- # If they aren't in the installed packages they could be a dependency
- dep = parse_dependency(n, new_version_array[index])
- if dep
- if @new_resource.package_name.is_a?(Array)
- @new_resource.package_name(package_name_array - [n] + [dep.first])
- @new_resource.version(new_version_array - [new_version_array[index]] + [dep.last]) if dep.last
- else
- @new_resource.package_name(dep.first)
- @new_resource.version(dep.last) if dep.last
- end
- end
- end
- end
+ package_name_array.each_with_index do |n, idx|
+ pkg_name, eval_pkg_arch = parse_arch(n)
- @current_resource = Chef::Resource::YumPackage.new(@new_resource.name)
- @current_resource.package_name(@new_resource.package_name)
+ # Defer to the arch property for the desired package architecture
+ pkg_arch = safe_arch_array[idx] || eval_pkg_arch
+ set_package_name(idx, pkg_name)
+ set_package_arch(idx, pkg_arch)
- installed_version = []
- @candidate_version = []
- @arch = []
- if @new_resource.source
- unless ::File.exists?(@new_resource.source)
- raise Chef::Exceptions::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}"
- end
+ Chef::Log.debug("#{new_resource} checking yum info for #{yum_syntax(n, nil, pkg_arch)}")
+ installed_versions << iv = @yum.installed_version(pkg_name, pkg_arch)
+ candidate_versions << cv = @yum.candidate_version(pkg_name, pkg_arch)
- Chef::Log.debug("#{@new_resource} checking rpm status")
- shell_out_with_timeout!("rpm -qp --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{@new_resource.source}", :timeout => Chef::Config[:yum_timeout]).stdout.each_line do |line|
- case line
- when /([\w\d_.-]+)\s([\w\d_.-]+)/
- @current_resource.package_name($1)
- @new_resource.version($2)
+ Chef::Log.debug("Found Yum package: #{pkg_name} installed version: #{iv || '(none)'} candidate version: #{cv || '(none)'}")
+ end
+
+ @installed_version = installed_versions.length > 1 ? installed_versions : installed_versions[0]
+ @candidate_version = candidate_versions.length > 1 ? candidate_versions : candidate_versions[0]
+ end
+
+ # Query the provided source file for the package name and version
+ def query_source_file
+ Chef::Log.debug("#{new_resource} checking rpm status")
+ shell_out_with_timeout!("rpm -qp --queryformat '%{NAME} %{VERSION}-%{RELEASE} %{ARCH}\n' #{new_resource.source}", timeout: Chef::Config[:yum_timeout]).stdout.each_line do |line|
+ case line
+ when /^(\S+)\s(\S+)\s(\S+)$/
+ n = $1
+ v = $2
+ a = $3
+
+ unless new_resource.package_name == n
+ Chef::Log.debug("#{new_resource} updating package_name from #{new_resource.package_name} to #{n} (per #{new_resource.source})")
+ new_resource.package_name(n)
end
- end
- @candidate_version << @new_resource.version
- installed_version << @yum.installed_version(@current_resource.package_name, arch)
- else
- package_name_array.each_with_index do |pkg, idx|
- # Don't overwrite an existing arch
- if arch
- name, parch = pkg, arch
- else
- name, parch = parse_arch(pkg)
- # if we parsed an arch from the name, update the name
- # to be just the package name.
- if parch
- if @new_resource.package_name.is_a?(Array)
- @new_resource.package_name[idx] = name
- else
- @new_resource.package_name(name)
- # only set the arch if it's a single package
- set_arch(parch)
- end
- end
+ unless new_resource.version == v
+ Chef::Log.debug("#{new_resource} updating version from #{new_resource.version} to #{v} (per #{new_resource.source})")
+ new_resource.version(v)
end
- if @new_resource.version
- new_resource =
- "#{@new_resource.package_name}-#{@new_resource.version}#{yum_arch(parch)}"
- else
- new_resource = "#{@new_resource.package_name}#{yum_arch(parch)}"
+ unless new_resource.arch == a
+ Chef::Log.debug("#{new_resource} updating architecture from #{new_resource.arch} to #{a} (per #{new_resource.source})")
+ new_resource.arch(a)
end
- Chef::Log.debug("#{@new_resource} checking yum info for #{new_resource}")
- installed_version << @yum.installed_version(name, parch)
- @candidate_version << @yum.candidate_version(name, parch)
- @arch << parch
end
end
- if installed_version.size == 1
- @current_resource.version(installed_version[0])
- @candidate_version = @candidate_version[0]
- @arch = @arch[0]
- else
- @current_resource.version(installed_version)
- end
+ @installed_version = @yum.installed_version(new_resource.package_name, new_resource.arch)
+ @candidate_version = new_resource.version
+ end
- Chef::Log.debug("#{@new_resource} installed version: #{installed_version || "(none)"} candidate version: " +
- "#{@candidate_version || "(none)"}")
+ def yum_command(command)
+ command = "#{yum_binary} #{command}"
+ Chef::Log.debug("#{new_resource}: yum command: \"#{command}\"")
+ status = shell_out_with_timeout(command, timeout: Chef::Config[:yum_timeout])
+
+ # This is fun: rpm can encounter errors in the %post/%postun scripts which aren't
+ # considered fatal - meaning the rpm is still successfully installed. These issue
+ # cause yum to emit a non fatal warning but still exit(1). As there's currently no
+ # way to suppress this behavior and an exit(1) will break a Chef run we make an
+ # effort to trap these and re-run the same install command - it will either fail a
+ # second time or succeed.
+ #
+ # A cleaner solution would have to be done in python and better hook into
+ # yum/rpm to handle exceptions as we see fit.
+ if status.exitstatus == 1
+ status.stdout.each_line do |l|
+ # rpm-4.4.2.3 lib/psm.c line 2182
+ next unless l =~ /^error: %(post|postun)\(.*\) scriptlet failed, exit status \d+$/
+ Chef::Log.warn("#{new_resource} caught non-fatal scriptlet issue: \"#{l}\". Can't trust yum exit status " \
+ "so running install again to verify.")
+ status = shell_out_with_timeout(command, timeout: Chef::Config[:yum_timeout])
+ break
+ end
+ end
- @current_resource
+ if status.exitstatus > 0
+ command_output = "STDOUT: #{status.stdout}\nSTDERR: #{status.stderr}"
+ raise Chef::Exceptions::Exec, "#{command} returned #{status.exitstatus}:\n#{command_output}"
+ end
end
def install_remote_package(name, version)
- # Work around yum not exiting with an error if a package doesn't exist
- # for CHEF-2062
- all_avail = as_array(name).zip(as_array(version)).any? do |n, v|
- @yum.version_available?(n, v, arch_for_name(n))
+ # Work around yum not exiting with an error if a package doesn't exist for CHEF-2062.
+ all_avail = as_array(name).zip(as_array(version), safe_arch_array).any? do |n, v, a|
+ @yum.version_available?(n, v, a)
end
+
method = log_method = nil
methods = []
if all_avail
@@ -267,12 +309,14 @@ class Chef
# yum install of an old name+version+arch will exit(0) for some reason
#
# Some packages can be installed multiple times like the kernel
- as_array(name).zip(as_array(version)).each do |n, v|
+ as_array(name).zip(current_version_array, as_array(version), safe_arch_array).each do |n, cv, v, a|
+ next if n.nil?
+
method = "install"
log_method = "installing"
- idx = package_name_array.index(n)
+
unless @yum.allow_multi_install.include?(n)
- if RPMVersion.parse(current_version_array[idx]) > RPMVersion.parse(v)
+ if RPMVersion.parse(cv) > RPMVersion.parse(v)
# We allow downgrading only in the evenit of single-package
# rules where the user explicitly allowed it
if allow_downgrade
@@ -280,13 +324,13 @@ class Chef
log_method = "downgrading"
else
# we bail like yum when the package is older
- raise Chef::Exceptions::Package, "Installed package #{n}-#{current_version_array[idx]} is newer " +
- "than candidate package #{n}-#{v}"
+ raise Chef::Exceptions::Package, "Installed package #{yum_syntax(n, cv, a)} is newer " \
+ "than candidate package #{yum_syntax(n, v, a)}"
end
end
end
# methods don't count for packages we won't be touching
- next if RPMVersion.parse(current_version_array[idx]) == RPMVersion.parse(v)
+ next if RPMVersion.parse(cv) == RPMVersion.parse(v)
methods << method
end
@@ -298,103 +342,26 @@ class Chef
repos = []
pkg_string_bits = []
- as_array(name).zip(as_array(version)).each do |n, v|
- idx = package_name_array.index(n)
- a = arch_for_name(n)
- s = ""
- unless v == current_version_array[idx]
- s = "#{n}-#{v}#{yum_arch(a)}"
- repo = @yum.package_repository(n, v, a)
- repos << "#{s} from #{repo} repository"
- pkg_string_bits << s
- end
+ as_array(name).zip(current_version_array, as_array(version), safe_arch_array).each do |n, cv, v, a|
+ next if n.nil?
+ next if v == cv
+ s = yum_syntax(n, v, a)
+ repo = @yum.package_repository(n, v, a)
+ repos << "#{s} from #{repo} repository"
+ pkg_string_bits << s
end
pkg_string = pkg_string_bits.join(" ")
- Chef::Log.info("#{@new_resource} #{log_method} #{repos.join(' ')}")
- yum_command("-d0 -e0 -y#{expand_options(@new_resource.options)} #{method} #{pkg_string}")
+ Chef::Log.info("#{new_resource} #{log_method} #{repos.join(' ')}")
+ yum_command("-d0 -e0 -y#{expand_options(new_resource.options)} #{method} #{pkg_string}")
else
- raise Chef::Exceptions::Package, "Version #{version} of #{name} not found. Did you specify both version " +
+ raise Chef::Exceptions::Package, "Version #{version} of #{name} not found. Did you specify both version " \
"and release? (version-release, e.g. 1.84-10.fc6)"
end
end
- def install_package(name, version)
- if @new_resource.source
- yum_command("-d0 -e0 -y#{expand_options(@new_resource.options)} localinstall #{@new_resource.source}")
- else
- install_remote_package(name, version)
- end
-
- if flush_cache[:after]
- @yum.reload
- else
- @yum.reload_installed
- end
- end
-
- # Keep upgrades from trying to install an older candidate version. Can happen when a new
- # version is installed then removed from a repository, now the older available version
- # shows up as a viable install candidate.
- #
- # Can be done in upgrade_package but an upgraded from->to log message slips out
- #
- # Hacky - better overall solution? Custom compare in Package provider?
- def action_upgrade
- # Could be uninstalled or have no candidate
- if @current_resource.version.nil? || !candidate_version_array.any?
- super
- elsif candidate_version_array.zip(current_version_array).any? do |c, i|
- RPMVersion.parse(c) > RPMVersion.parse(i)
- end
- super
- else
- Chef::Log.debug("#{@new_resource} is at the latest version - nothing to do")
- end
- end
-
- def upgrade_package(name, version)
- install_package(name, version)
- end
-
- def remove_package(name, version)
- if version
- remove_str = as_array(name).zip(as_array(version)).map do |n, v|
- a = arch_for_name(n)
- "#{[n, v].join('-')}#{yum_arch(a)}"
- end.join(" ")
- else
- remove_str = as_array(name).map do |n|
- a = arch_for_name(n)
- "#{n}#{yum_arch(a)}"
- end.join(" ")
- end
- yum_command("-d0 -e0 -y#{expand_options(@new_resource.options)} remove #{remove_str}")
-
- if flush_cache[:after]
- @yum.reload
- else
- @yum.reload_installed
- end
- end
-
- def purge_package(name, version)
- remove_package(name, version)
- end
-
- def lock_package(name, version)
- yum_command("-d0 -e0 -y#{expand_options(@new_resource.options)} versionlock add #{name}")
- end
-
- def unlock_package(name, version)
- yum_command("-d0 -e0 -y#{expand_options(@new_resource.options)} versionlock delete #{name}")
- end
-
- private
-
+ # Allow for foo.x86_64 style package_name like yum uses in it's output
def parse_arch(package_name)
- # Allow for foo.x86_64 style package_name like yum uses in it's output
- #
- if package_name =~ %r{^(.*)\.(.*)$}
+ if package_name =~ /^(.*)\.(.*)$/
new_package_name = $1
new_arch = $2
# foo.i386 and foo.beta1 are both valid package names or expressions of an arch.
@@ -410,7 +377,31 @@ class Chef
return new_package_name, new_arch
end
end
- return package_name, nil
+ [package_name, nil]
+ end
+
+ #
+ # Dependency String Handling
+ #
+
+ # Iterate through the list of package_names given to us by the user and
+ # see if any of them are in the depenency format ("foo >= 1.1"). Modify
+ # the list of packages and versions to incorporate those values.
+ def convert_dependency_strings_into_packages
+ package_name_array.each_with_index do |n, index|
+ next if @yum.package_available?(n)
+ # If they aren't in the installed packages they could be a dependency.
+ dep = parse_dependency(n, new_version_array[index])
+ if dep
+ if new_resource.package_name.is_a?(Array)
+ new_resource.package_name(package_name_array - [n] + [dep.first])
+ new_resource.version(new_version_array - [new_version_array[index]] + [dep.last]) if dep.last
+ else
+ new_resource.package_name(dep.first)
+ new_resource.version(dep.last) if dep.last
+ end
+ end
+ end
end
# If we don't have the package we could have been passed a 'whatprovides' feature
@@ -423,18 +414,20 @@ class Chef
# matching them up with an actual package so the standard resource handling can apply.
#
# There is currently no support for filename matching.
+ #
+ # Note: This was largely left alone during the multipackage refactor
def parse_dependency(name, version)
# Transform the package_name into a requirement
# If we are passed a version or a version constraint we have to assume it's a requirement first. If it can't be
- # parsed only yum_require.name will be set and @new_resource.version will be left intact
- if version
- require_string = "#{name} #{version}"
- else
- # Transform the package_name into a requirement, might contain a version, could just be
- # a match for virtual provides
- require_string = name
- end
+ # parsed only yum_require.name will be set and new_resource.version will be left intact
+ require_string = if version
+ "#{name} #{version}"
+ else
+ # Transform the package_name into a requirement, might contain a version, could just be
+ # a match for virtual provides
+ name
+ end
yum_require = RPMRequire.parse(require_string)
# and gather all the packages that have a Provides feature satisfying the requirement.
# It could be multiple be we can only manage one
@@ -442,9 +435,9 @@ class Chef
if packages.empty?
# Don't bother if we are just ensuring a package is removed - we don't need Provides data
- actions = Array(@new_resource.action)
+ actions = Array(new_resource.action)
unless actions.size == 1 && (actions[0] == :remove || actions[0] == :purge)
- Chef::Log.debug("#{@new_resource} couldn't match #{@new_resource.package_name} in " +
+ Chef::Log.debug("#{new_resource} couldn't match #{new_resource.package_name} in " \
"installed Provides, loading available Provides - this may take a moment")
@yum.reload_provides
packages = @yum.packages_from_require(yum_require)
@@ -467,8 +460,8 @@ class Chef
unique_names.uniq!
if unique_names.size > 1
- Chef::Log.warn("#{@new_resource} matched multiple Provides for #{@new_resource.package_name} " +
- "but we can only use the first match: #{new_package_name}. Please use a more " +
+ Chef::Log.warn("#{new_resource} matched multiple Provides for #{new_resource.package_name} " \
+ "but we can only use the first match: #{new_package_name}. Please use a more " \
"specific version.")
end
@@ -480,6 +473,63 @@ class Chef
end
end
+ #
+ # Misc Helpers
+ #
+
+ # Given an list of names and versions, generate the full yum syntax package name
+ def full_package_name(name, version)
+ as_array(name).zip(as_array(version), safe_arch_array).map do |n, v, a|
+ yum_syntax(n, v, a)
+ end
+ end
+
+ # Generate the yum syntax for the package
+ def yum_syntax(name, version, arch)
+ s = name
+ s += "-#{version}" if version
+ s += ".#{arch}" if arch
+ s
+ end
+
+ # Set the package name correctly based on whether it is a String or Array
+ def set_package_name(idx, name)
+ if new_resource.package_name.is_a?(String)
+ new_resource.package_name(name)
+ else
+ new_resource.package_name[idx] = name
+ end
+ end
+
+ # Set the architecture correcly based on whether it is a String or Array
+ def set_package_arch(idx, arch)
+ if new_resource.package_name.is_a?(String)
+ new_resource.arch(arch) unless arch.nil?
+ else
+ new_resource.arch ||= []
+ new_resource.arch[idx] = arch
+ end
+ end
+
+ # A cousin of package_name_array, return a list of the architectures
+ # defined in the resource.
+ def safe_arch_array
+ if new_resource.arch.is_a?(Array)
+ new_resource.arch
+ elsif new_resource.arch.nil?
+ package_name_array.map { nil }
+ else
+ [ new_resource.arch ]
+ end
+ end
+
+ def flush_cache
+ if new_resource.respond_to?("flush_cache")
+ new_resource.flush_cache
+ else
+ { before: false, after: false }
+ end
+ end
end
end
end
diff --git a/lib/chef/provider/package/yum/rpm_utils.rb b/lib/chef/provider/package/yum/rpm_utils.rb
index 032597d047..0709118184 100644
--- a/lib/chef/provider/package/yum/rpm_utils.rb
+++ b/lib/chef/provider/package/yum/rpm_utils.rb
@@ -37,7 +37,7 @@ class Chef
lead = 0
tail = evr.size
- if %r{^([\d]+):}.match(evr) # rubocop:disable Performance/RedundantMatch
+ if /^([\d]+):/.match(evr) # rubocop:disable Performance/RedundantMatch
epoch = $1.to_i
lead = $1.length + 1
elsif evr[0].ord == ":".ord
@@ -45,7 +45,7 @@ class Chef
lead = 1
end
- if %r{:?.*-(.*)$}.match(evr) # rubocop:disable Performance/RedundantMatch
+ if /:?.*-(.*)$/.match(evr) # rubocop:disable Performance/RedundantMatch
release = $1
tail = evr.length - release.length - lead - 1
@@ -230,17 +230,17 @@ class Chef
@v = args[1]
@r = args[2]
else
- raise ArgumentError, "Expecting either 'epoch-version-release' or 'epoch, " +
+ raise ArgumentError, "Expecting either 'epoch-version-release' or 'epoch, " \
"version, release'"
end
end
attr_reader :e, :v, :r
- alias :epoch :e
- alias :version :v
- alias :release :r
+ alias epoch e
+ alias version v
+ alias release r
def self.parse(*args)
- self.new(*args)
+ new(*args)
end
def <=>(other)
@@ -317,7 +317,7 @@ class Chef
return cmp
end
- return 0
+ 0
end
end
@@ -339,7 +339,7 @@ class Chef
@a = args[4]
@provides = args[5]
else
- raise ArgumentError, "Expecting either 'name, epoch-version-release, arch, provides' " +
+ raise ArgumentError, "Expecting either 'name, epoch-version-release, arch, provides' " \
"or 'name, epoch, version, release, arch, provides'"
end
@@ -349,8 +349,8 @@ class Chef
end
end
attr_reader :n, :a, :version, :provides
- alias :name :n
- alias :arch :a
+ alias name n
+ alias arch a
def <=>(other)
compare(other)
@@ -395,7 +395,7 @@ class Chef
end
end
- return 0
+ 0
end
def to_s
@@ -423,7 +423,7 @@ class Chef
@version = RPMVersion.new(e, v, r)
@flag = args[4] || :==
else
- raise ArgumentError, "Expecting either 'name, epoch-version-release, flag' or " +
+ raise ArgumentError, "Expecting either 'name, epoch-version-release, flag' or " \
"'name, epoch, version, release, flag'"
end
end
@@ -434,25 +434,25 @@ class Chef
# "mtr >= 2:0.71-3.0"
# "mta"
def self.parse(string)
- if %r{^(\S+)\s+(>|>=|=|==|<=|<)\s+(\S+)$}.match(string) # rubocop:disable Performance/RedundantMatch
+ if /^(\S+)\s+(>|>=|=|==|<=|<)\s+(\S+)$/.match(string) # rubocop:disable Performance/RedundantMatch
name = $1
- if $2 == "="
- flag = :==
- else
- flag = :"#{$2}"
- end
+ flag = if $2 == "="
+ :==
+ else
+ :"#{$2}"
+ end
version = $3
- return self.new(name, version, flag)
+ new(name, version, flag)
else
name = string
- return self.new(name, nil, nil)
+ new(name, nil, nil)
end
end
# Test if another RPMDependency satisfies our requirements
def satisfy?(y)
- unless y.kind_of?(RPMDependency)
+ unless y.is_a?(RPMDependency)
raise ArgumentError, "Expecting an RPMDependency object"
end
@@ -481,7 +481,7 @@ class Chef
return true
end
- return false
+ false
end
end
@@ -504,11 +504,11 @@ class Chef
class RPMDb
def initialize
# package name => [ RPMPackage, RPMPackage ] of different versions
- @rpms = Hash.new
+ @rpms = {}
# package nevra => RPMPackage for lookups
- @index = Hash.new
+ @index = {}
# provide name (aka feature) => [RPMPackage, RPMPackage] each providing this feature
- @provides = Hash.new
+ @provides = {}
# RPMPackages listed as available
@available = Set.new
# RPMPackages listed as installed
@@ -516,7 +516,7 @@ class Chef
end
def [](package_name)
- self.lookup(package_name)
+ lookup(package_name)
end
# Lookup package_name and return a descending array of package objects
@@ -537,11 +537,11 @@ class Chef
# The available/installed state can be overwritten for existing packages.
def push(*args)
args.flatten.each do |new_rpm|
- unless new_rpm.kind_of?(RPMDbPackage)
+ unless new_rpm.is_a?(RPMDbPackage)
raise ArgumentError, "Expecting an RPMDbPackage object"
end
- @rpms[new_rpm.n] ||= Array.new
+ @rpms[new_rpm.n] ||= []
# we may already have this one, like when the installed list is refreshed
idx = @index[new_rpm.nevra]
@@ -552,7 +552,7 @@ class Chef
@rpms[new_rpm.n] << new_rpm
new_rpm.provides.each do |provide|
- @provides[provide.name] ||= Array.new
+ @provides[provide.name] ||= []
@provides[provide.name] << new_rpm
end
@@ -574,7 +574,7 @@ class Chef
end
def <<(*args)
- self.push(args)
+ push(args)
end
def clear
@@ -596,7 +596,7 @@ class Chef
def size
@rpms.size
end
- alias :length :size
+ alias length size
def available_size
@available.size
@@ -615,7 +615,7 @@ class Chef
end
def whatprovides(rpmdep)
- unless rpmdep.kind_of?(RPMDependency)
+ unless rpmdep.is_a?(RPMDependency)
raise ArgumentError, "Expecting an RPMDependency object"
end
@@ -632,7 +632,7 @@ class Chef
end
end
- return what
+ what
end
end
diff --git a/lib/chef/provider/package/yum/yum_cache.rb b/lib/chef/provider/package/yum/yum_cache.rb
index 7462529113..9fd95af138 100644
--- a/lib/chef/provider/package/yum/yum_cache.rb
+++ b/lib/chef/provider/package/yum/yum_cache.rb
@@ -101,12 +101,12 @@ class Chef
status = nil
begin
- status = shell_out!("#{python_bin} #{yum_dump_path}#{opts}", :timeout => Chef::Config[:yum_timeout])
+ status = shell_out!("#{python_bin} #{yum_dump_path}#{opts}", timeout: Chef::Config[:yum_timeout])
status.stdout.each_line do |line|
one_line = true
line.chomp!
- if line =~ %r{\[option (.*)\] (.*)}
+ if line =~ /\[option (.*)\] (.*)/
if $1 == "installonlypkgs"
@allow_multi_install = $2.split
else
@@ -115,7 +115,7 @@ class Chef
next
end
- if line =~ %r{^(\S+) ([0-9]+) (\S+) (\S+) (\S+) \[(.*)\] ([i,a,r]) (\S+)$}
+ if line =~ /^(\S+) ([0-9]+) (\S+) (\S+) (\S+) \[(.*)\] ([i,a,r]) (\S+)$/
name = $1
epoch = $2
version = $3
@@ -125,7 +125,7 @@ class Chef
type = $7
repoid = $8
else
- Chef::Log.warn("Problem parsing line '#{line}' from yum-dump.py! " +
+ Chef::Log.warn("Problem parsing line '#{line}' from yum-dump.py! " \
"Please check your yum configuration.")
next
end
@@ -158,7 +158,7 @@ class Chef
raise Chef::Exceptions::Package, "Yum failed - #{status.inspect} - returns: #{error}"
else
unless one_line
- Chef::Log.warn("Odd, no output from yum-dump.py. Please check " +
+ Chef::Log.warn("Odd, no output from yum-dump.py. Please check " \
"your yum configuration.")
end
end
@@ -233,7 +233,7 @@ class Chef
if @rpmdb.lookup(package_name)
return true
else
- if package_name =~ %r{^(.*)\.(.*)$}
+ if package_name =~ /^(.*)\.(.*)$/
pkg_name = $1
pkg_arch = $2
@@ -245,7 +245,7 @@ class Chef
end
end
- return false
+ false
end
# Returns a array of packages satisfying an RPMDependency
@@ -260,7 +260,7 @@ class Chef
return true if desired_version == v
end
- return false
+ false
end
# Return the source repository for a package-version.arch
@@ -269,14 +269,14 @@ class Chef
return pkg.repoid if desired_version == pkg.version.to_s
end
- return nil
+ nil
end
# Return the latest available version for a package.arch
def available_version(package_name, arch = nil)
version(package_name, arch, true, false)
end
- alias :candidate_version :available_version
+ alias candidate_version available_version
# Return the currently installed version for a package.arch
def installed_version(package_name, arch = nil)
@@ -361,12 +361,12 @@ class Chef
# ['atk = 1.12.2-1.fc6', 'libatk-1.0.so.0']
string.split(", ").each do |seg|
# 'atk = 1.12.2-1.fc6'
- if seg =~ %r{^'(.*)'$}
+ if seg =~ /^'(.*)'$/
ret << RPMProvide.parse($1)
end
end
- return ret
+ ret
end
end # YumCache
diff --git a/lib/chef/provider/package/zypper.rb b/lib/chef/provider/package/zypper.rb
index edad45c3e4..45c6c91f60 100644
--- a/lib/chef/provider/package/zypper.rb
+++ b/lib/chef/provider/package/zypper.rb
@@ -35,7 +35,7 @@ class Chef
candidate_version = current_version = nil
is_installed = false
Chef::Log.debug("#{new_resource} checking zypper")
- status = shell_out_with_timeout!("zypper --non-interactive info #{package_name}")
+ status = shell_out_compact_timeout!("zypper", "--non-interactive", "info", package_name)
status.stdout.each_line do |line|
case line
when /^Version *: (.+) *$/
@@ -77,14 +77,14 @@ class Chef
def package_locked(name, version)
islocked = false
- locked = shell_out_with_timeout!("zypper locks")
+ locked = shell_out_compact_timeout!("zypper", "locks")
locked.stdout.each_line do |line|
line_package = line.split("|").shift(2).last.strip
if line_package == name
islocked = true
end
end
- return islocked
+ islocked
end
def load_current_resource
@@ -103,7 +103,7 @@ class Chef
end
def install_package(name, version)
- zypper_package("install --auto-agree-with-licenses", name, version)
+ zypper_package("install", "--auto-agree-with-licenses", name, version)
end
def upgrade_package(name, version)
@@ -116,7 +116,7 @@ class Chef
end
def purge_package(name, version)
- zypper_package("remove --clean-deps", name, version)
+ zypper_package("remove", "--clean-deps", name, version)
end
def lock_package(name, version)
@@ -135,24 +135,24 @@ class Chef
end
end
- def zypper_package(command, names, versions)
+ def zypper_package(command, *options, names, versions)
zipped_names = zip(names, versions)
if zypper_version < 1.0
- shell_out_with_timeout!(a_to_s("zypper", gpg_checks, command, "-y", names))
+ shell_out_compact_timeout!("zypper", gpg_checks, command, *options, "-y", names)
else
- shell_out_with_timeout!(a_to_s("zypper --non-interactive", gpg_checks, command, zipped_names))
+ shell_out_compact_timeout!("zypper", "--non-interactive", gpg_checks, command, *options, zipped_names)
end
end
- def gpg_checks()
+ 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. " +
+ 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
diff --git a/lib/chef/provider/powershell_script.rb b/lib/chef/provider/powershell_script.rb
index ab85ec35ac..db12f61a0b 100644
--- a/lib/chef/provider/powershell_script.rb
+++ b/lib/chef/provider/powershell_script.rb
@@ -74,7 +74,7 @@ class Chef
def add_exit_status_wrapper
self.code = wrapper_script
Chef::Log.debug("powershell_script provider called with script code:\n\n#{@new_resource.code}\n")
- Chef::Log.debug("powershell_script provider will execute transformed code:\n\n#{self.code}\n")
+ Chef::Log.debug("powershell_script provider will execute transformed code:\n\n#{code}\n")
end
def validate_script_syntax!
@@ -149,6 +149,14 @@ EOH
<<-EOH
# Chef Client wrapper for powershell_script resources
+# In rare cases, such as when PowerShell is executed
+# as an alternate user, the new-variable cmdlet is not
+# available, so import it just in case
+if ( get-module -ListAvailable Microsoft.PowerShell.Utility )
+{
+ Import-Module Microsoft.PowerShell.Utility
+}
+
# LASTEXITCODE can be uninitialized -- make it explictly 0
# to avoid incorrect detection of failure (non-zero) codes
$global:LASTEXITCODE = 0
diff --git a/lib/chef/provider/route.rb b/lib/chef/provider/route.rb
index 64c89aac6d..5e20fdf11e 100644
--- a/lib/chef/provider/route.rb
+++ b/lib/chef/provider/route.rb
@@ -21,209 +21,211 @@ require "chef/mixin/command"
require "chef/provider"
require "ipaddr"
-class Chef::Provider::Route < Chef::Provider
- include Chef::Mixin::Command
-
- provides :route
-
- attr_accessor :is_running
-
- MASK = { "0.0.0.0" => "0",
- "128.0.0.0" => "1",
- "192.0.0.0" => "2",
- "224.0.0.0" => "3",
- "240.0.0.0" => "4",
- "248.0.0.0" => "5",
- "252.0.0.0" => "6",
- "254.0.0.0" => "7",
- "255.0.0.0" => "8",
- "255.128.0.0" => "9",
- "255.192.0.0" => "10",
- "255.224.0.0" => "11",
- "255.240.0.0" => "12",
- "255.248.0.0" => "13",
- "255.252.0.0" => "14",
- "255.254.0.0" => "15",
- "255.255.0.0" => "16",
- "255.255.128.0" => "17",
- "255.255.192.0" => "18",
- "255.255.224.0" => "19",
- "255.255.240.0" => "20",
- "255.255.248.0" => "21",
- "255.255.252.0" => "22",
- "255.255.254.0" => "23",
- "255.255.255.0" => "24",
- "255.255.255.128" => "25",
- "255.255.255.192" => "26",
- "255.255.255.224" => "27",
- "255.255.255.240" => "28",
- "255.255.255.248" => "29",
- "255.255.255.252" => "30",
- "255.255.255.254" => "31",
- "255.255.255.255" => "32" }
-
- def hex2ip(hex_data)
- # Cleanup hex data
- hex_ip = hex_data.to_s.downcase.gsub(/[^0-9a-f]/, "")
-
- # Check hex data format (IP is a 32bit integer, so should be 8 chars long)
- return nil if hex_ip.length != hex_data.length || hex_ip.length != 8
-
- # Extract octets from hex data
- octets = hex_ip.scan(/../).reverse.collect { |octet| [octet].pack("H2").unpack("C").first }
-
- # Validate IP
- ip = octets.join(".")
- begin
- IPAddr.new(ip, Socket::AF_INET).to_s
- rescue ArgumentError
- Chef::Log.debug("Invalid IP address data: hex=#{hex_ip}, ip=#{ip}")
- return nil
- end
- end
-
- def whyrun_supported?
- true
- end
+class Chef
+ class Provider
+ class Route < Chef::Provider
+ include Chef::Mixin::Command
+
+ provides :route
+
+ attr_accessor :is_running
+
+ MASK = { "0.0.0.0" => "0",
+ "128.0.0.0" => "1",
+ "192.0.0.0" => "2",
+ "224.0.0.0" => "3",
+ "240.0.0.0" => "4",
+ "248.0.0.0" => "5",
+ "252.0.0.0" => "6",
+ "254.0.0.0" => "7",
+ "255.0.0.0" => "8",
+ "255.128.0.0" => "9",
+ "255.192.0.0" => "10",
+ "255.224.0.0" => "11",
+ "255.240.0.0" => "12",
+ "255.248.0.0" => "13",
+ "255.252.0.0" => "14",
+ "255.254.0.0" => "15",
+ "255.255.0.0" => "16",
+ "255.255.128.0" => "17",
+ "255.255.192.0" => "18",
+ "255.255.224.0" => "19",
+ "255.255.240.0" => "20",
+ "255.255.248.0" => "21",
+ "255.255.252.0" => "22",
+ "255.255.254.0" => "23",
+ "255.255.255.0" => "24",
+ "255.255.255.128" => "25",
+ "255.255.255.192" => "26",
+ "255.255.255.224" => "27",
+ "255.255.255.240" => "28",
+ "255.255.255.248" => "29",
+ "255.255.255.252" => "30",
+ "255.255.255.254" => "31",
+ "255.255.255.255" => "32" }.freeze
+
+ def hex2ip(hex_data)
+ # Cleanup hex data
+ hex_ip = hex_data.to_s.downcase.gsub(/[^0-9a-f]/, "")
+
+ # Check hex data format (IP is a 32bit integer, so should be 8 chars long)
+ return nil if hex_ip.length != hex_data.length || hex_ip.length != 8
+
+ # Extract octets from hex data
+ octets = hex_ip.scan(/../).reverse.collect { |octet| [octet].pack("H2").unpack("C").first }
+
+ # Validate IP
+ ip = octets.join(".")
+ begin
+ IPAddr.new(ip, Socket::AF_INET).to_s
+ rescue ArgumentError
+ Chef::Log.debug("Invalid IP address data: hex=#{hex_ip}, ip=#{ip}")
+ return nil
+ end
+ end
- def load_current_resource
- self.is_running = false
+ def whyrun_supported?
+ true
+ end
- # cidr or quad dot mask
- if @new_resource.netmask
- new_ip = IPAddr.new("#{@new_resource.target}/#{@new_resource.netmask}")
- else
- new_ip = IPAddr.new(@new_resource.target)
- end
+ def load_current_resource
+ self.is_running = false
+
+ # cidr or quad dot mask
+ new_ip = if new_resource.netmask
+ IPAddr.new("#{new_resource.target}/#{new_resource.netmask}")
+ else
+ IPAddr.new(new_resource.target)
+ end
+
+ # For linux, we use /proc/net/route file to read proc table info
+ return if node[:os] != "linux"
+
+ route_file = ::File.open("/proc/net/route", "r")
+
+ # Read all routes
+ while (line = route_file.gets)
+ # Get all the fields for a route
+ _, destination, gateway, _, _, _, _, mask = line.split
+
+ # Convert hex-encoded values to quad-dotted notation (e.g. 0064A8C0 => 192.168.100.0)
+ destination = hex2ip(destination)
+ gateway = hex2ip(gateway)
+ mask = hex2ip(mask)
+
+ # Skip formatting lines (header, etc)
+ next unless destination && gateway && mask
+ Chef::Log.debug("#{new_resource} system has route: dest=#{destination} mask=#{mask} gw=#{gateway}")
+
+ # check if what were trying to configure is already there
+ # use an ipaddr object with ip/mask this way we can have
+ # a new resource be in cidr format (i don't feel like
+ # expanding bitmask by hand.
+ #
+ running_ip = IPAddr.new("#{destination}/#{mask}")
+ Chef::Log.debug("#{new_resource} new ip: #{new_ip.inspect} running ip: #{running_ip.inspect}")
+ self.is_running = true if running_ip == new_ip && gateway == new_resource.gateway
+ end
- # For linux, we use /proc/net/route file to read proc table info
- if node[:os] == "linux"
- route_file = ::File.open("/proc/net/route", "r")
-
- # Read all routes
- while (line = route_file.gets)
- # Get all the fields for a route
- iface, destination, gateway, flags, refcnt, use, metric, mask, mtu, window, irtt = line.split
-
- # Convert hex-encoded values to quad-dotted notation (e.g. 0064A8C0 => 192.168.100.0)
- destination = hex2ip(destination)
- gateway = hex2ip(gateway)
- mask = hex2ip(mask)
-
- # Skip formatting lines (header, etc)
- next unless destination && gateway && mask
- Chef::Log.debug("#{@new_resource} system has route: dest=#{destination} mask=#{mask} gw=#{gateway}")
-
- # check if what were trying to configure is already there
- # use an ipaddr object with ip/mask this way we can have
- # a new resource be in cidr format (i don't feel like
- # expanding bitmask by hand.
- #
- running_ip = IPAddr.new("#{destination}/#{mask}")
- Chef::Log.debug("#{@new_resource} new ip: #{new_ip.inspect} running ip: #{running_ip.inspect}")
- self.is_running = true if running_ip == new_ip && gateway == @new_resource.gateway
+ route_file.close
end
- route_file.close
- end
- end
+ def action_add
+ # check to see if load_current_resource found the route
+ if is_running
+ Chef::Log.debug("#{new_resource} route already active - nothing to do")
+ else
+ command = generate_command(:add)
+ converge_by("run #{command.join(' ')} to add route") do
+ shell_out_compact!(command)
+ Chef::Log.info("#{new_resource} added")
+ end
+ end
- def action_add
- # check to see if load_current_resource found the route
- if is_running
- Chef::Log.debug("#{@new_resource} route already active - nothing to do")
- else
- command = generate_command(:add)
- converge_by ("run #{ command } to add route") do
- run_command( :command => command )
- Chef::Log.info("#{@new_resource} added")
+ # for now we always write the file (ugly but its what it is)
+ generate_config
end
- end
- #for now we always write the file (ugly but its what it is)
- generate_config
- end
+ def action_delete
+ if is_running
+ command = generate_command(:delete)
+ converge_by("run #{command.join(' ')} to delete route ") do
+ shell_out_compact!(command)
+ Chef::Log.info("#{new_resource} removed")
+ end
+ else
+ Chef::Log.debug("#{new_resource} route does not exist - nothing to do")
+ end
- def action_delete
- if is_running
- command = generate_command(:delete)
- converge_by ("run #{ command } to delete route ") do
- run_command( :command => command )
- Chef::Log.info("#{@new_resource} removed")
+ # for now we always write the file (ugly but its what it is)
+ generate_config
end
- else
- Chef::Log.debug("#{@new_resource} route does not exist - nothing to do")
- end
-
- #for now we always write the file (ugly but its what it is)
- generate_config
- end
- def generate_config
- conf = Hash.new
- case node[:platform]
- when "centos", "redhat", "fedora"
- # walk the collection
- run_context.resource_collection.each do |resource|
- if resource.is_a? Chef::Resource::Route
- # default to eth0
- if resource.device
- dev = resource.device
- else
- dev = "eth0"
+ def generate_config
+ conf = {}
+ case node[:platform]
+ when "centos", "redhat", "fedora"
+ # walk the collection
+ run_context.resource_collection.each do |resource|
+ next unless resource.is_a? Chef::Resource::Route
+ # default to eth0
+ dev = if resource.device
+ resource.device
+ else
+ "eth0"
+ end
+
+ conf[dev] = "" if conf[dev].nil?
+ case @action
+ when :add
+ conf[dev] << config_file_contents(:add, target: resource.target, netmask: resource.netmask, gateway: resource.gateway) if resource.action == [:add]
+ when :delete
+ # need to do this for the case when the last route on an int
+ # is removed
+ conf[dev] << config_file_contents(:delete)
+ end
end
-
- conf[dev] = String.new if conf[dev].nil?
- case @action
- when :add
- conf[dev] << config_file_contents(:add, :target => resource.target, :netmask => resource.netmask, :gateway => resource.gateway) if resource.action == [:add]
- when :delete
- # need to do this for the case when the last route on an int
- # is removed
- conf[dev] << config_file_contents(:delete)
+ conf.each do |k, v|
+ network_file_name = "/etc/sysconfig/network-scripts/route-#{k}"
+ converge_by("write route route.#{k}\n#{conf[k]} to #{network_file_name}") do
+ network_file = ::File.new(network_file_name, "w")
+ network_file.puts(conf[k])
+ Chef::Log.debug("#{new_resource} writing route.#{k}\n#{conf[k]}")
+ network_file.close
+ end
end
end
end
- conf.each do |k, v|
- network_file_name = "/etc/sysconfig/network-scripts/route-#{k}"
- converge_by ("write route route.#{k}\n#{conf[k]} to #{ network_file_name }") do
- network_file = ::File.new(network_file_name, "w")
- network_file.puts(conf[k])
- Chef::Log.debug("#{@new_resource} writing route.#{k}\n#{conf[k]}")
- network_file.close
+
+ def generate_command(action)
+ target = new_resource.target
+ target = "#{target}/#{MASK[new_resource.netmask.to_s]}" if new_resource.netmask
+
+ case action
+ when :add
+ command = [ "ip", "route", "replace", target ]
+ command += [ "via", new_resource.gateway ] if new_resource.gateway
+ command += [ "dev", new_resource.device ] if new_resource.device
+ when :delete
+ command = [ "ip", "route", "delete", target ]
+ command += [ "via", new_resource.gateway ] if new_resource.gateway
end
- end
- end
- end
- def generate_command(action)
- common_route_items = ""
- common_route_items << "/#{MASK[@new_resource.netmask.to_s]}" if @new_resource.netmask
- common_route_items << " via #{@new_resource.gateway} " if @new_resource.gateway
-
- case action
- when :add
- command = "ip route replace #{@new_resource.target}"
- command << common_route_items
- command << " dev #{@new_resource.device} " if @new_resource.device
- when :delete
- command = "ip route delete #{@new_resource.target}"
- command << common_route_items
- end
+ command
+ end
- return command
- end
+ def config_file_contents(action, options = {})
+ content = ""
+ case action
+ when :add
+ content << (options[:target]).to_s
+ content << "/#{MASK[options[:netmask].to_s]}" if options[:netmask]
+ content << " via #{options[:gateway]}" if options[:gateway]
+ content << "\n"
+ end
- def config_file_contents(action, options = {})
- content = ""
- case action
- when :add
- content << "#{options[:target]}"
- content << "/#{options[:netmask]}" if options[:netmask]
- content << " via #{options[:gateway]}" if options[:gateway]
- content << "\n"
+ content
+ end
end
-
- return content
end
end
diff --git a/lib/chef/provider/script.rb b/lib/chef/provider/script.rb
index 6ca4e9f6f3..fca9cea467 100644
--- a/lib/chef/provider/script.rb
+++ b/lib/chef/provider/script.rb
@@ -18,6 +18,7 @@
require "tempfile"
require "chef/provider/execute"
+require "chef/win32/security" if Chef::Platform.windows?
require "forwardable"
class Chef
@@ -66,10 +67,45 @@ class Chef
end
def set_owner_and_group
- # FileUtils itself implements a no-op if +user+ or +group+ are nil
- # You can prove this by running FileUtils.chown(nil,nil,'/tmp/file')
- # as an unprivileged user.
- FileUtils.chown(new_resource.user, new_resource.group, script_file.path)
+ if Chef::Platform.windows?
+ # And on Windows also this is a no-op if there is no user specified.
+ grant_alternate_user_read_access
+ else
+ # FileUtils itself implements a no-op if +user+ or +group+ are nil
+ # You can prove this by running FileUtils.chown(nil,nil,'/tmp/file')
+ # as an unprivileged user.
+ FileUtils.chown(new_resource.user, new_resource.group, script_file.path)
+ end
+ end
+
+ def grant_alternate_user_read_access
+ # Do nothing if an alternate user isn't specified -- the file
+ # will already have the correct permissions for the user as part
+ # of the default ACL behavior on Windows.
+ return if new_resource.user.nil?
+
+ # Duplicate the script file's existing DACL
+ # so we can add an ACE later
+ securable_object = Chef::ReservedNames::Win32::Security::SecurableObject.new(script_file.path)
+ aces = securable_object.security_descriptor.dacl.reduce([]) { |result, current| result.push(current) }
+
+ username = new_resource.user
+
+ if new_resource.domain
+ username = new_resource.domain + '\\' + new_resource.user
+ end
+
+ # Create an ACE that allows the alternate user read access to the script
+ # file so it can be read and executed.
+ user_sid = Chef::ReservedNames::Win32::Security::SID.from_account(username)
+ read_ace = Chef::ReservedNames::Win32::Security::ACE.access_allowed(user_sid, Chef::ReservedNames::Win32::API::Security::GENERIC_READ | Chef::ReservedNames::Win32::API::Security::GENERIC_EXECUTE, 0)
+ aces.push(read_ace)
+ acl = Chef::ReservedNames::Win32::Security::ACL.create(aces)
+
+ # This actually applies the modified DACL to the file
+ # Use parentheses to bypass RuboCop / ChefStyle warning
+ # about useless setter
+ (securable_object.dacl = acl)
end
def script_file
diff --git a/lib/chef/provider/service.rb b/lib/chef/provider/service.rb
index e693bd2eed..e048b2e43b 100644
--- a/lib/chef/provider/service.rb
+++ b/lib/chef/provider/service.rb
@@ -218,7 +218,7 @@ class Chef
def default_init_command
if @new_resource.init_command
@new_resource.init_command
- elsif self.instance_variable_defined?(:@init_command)
+ elsif instance_variable_defined?(:@init_command)
@init_command
end
end
diff --git a/lib/chef/provider/service/arch.rb b/lib/chef/provider/service/arch.rb
index 2fd32e37aa..e34227036a 100644
--- a/lib/chef/provider/service/arch.rb
+++ b/lib/chef/provider/service/arch.rb
@@ -66,7 +66,7 @@ class Chef::Provider::Service::Arch < Chef::Provider::Service::Init
end
end
- def enable_service()
+ def enable_service
new_daemons = []
entries = daemons
@@ -92,7 +92,7 @@ class Chef::Provider::Service::Arch < Chef::Provider::Service::Init
end
end
- def disable_service()
+ def disable_service
new_daemons = []
entries = daemons
diff --git a/lib/chef/provider/service/freebsd.rb b/lib/chef/provider/service/freebsd.rb
index 76d8c1d17b..9746dfdef0 100644
--- a/lib/chef/provider/service/freebsd.rb
+++ b/lib/chef/provider/service/freebsd.rb
@@ -74,7 +74,7 @@ class Chef
end
requirements.assert(:start, :enable, :reload, :restart) do |a|
- a.assertion { service_enable_variable_name != nil }
+ a.assertion { !service_enable_variable_name.nil? }
a.failure_message Chef::Exceptions::Service, "Could not find the service name in #{init_command} and rcvar"
# No recovery in whyrun mode - the init file is present but not correct.
end
diff --git a/lib/chef/provider/service/gentoo.rb b/lib/chef/provider/service/gentoo.rb
index 8fb6d1f9af..7bb57113ac 100644
--- a/lib/chef/provider/service/gentoo.rb
+++ b/lib/chef/provider/service/gentoo.rb
@@ -61,11 +61,11 @@ class Chef::Provider::Service::Gentoo < Chef::Provider::Service::Init
end
end
- def enable_service()
+ def enable_service
shell_out!("/sbin/rc-update add #{@new_resource.service_name} default")
end
- def disable_service()
+ def disable_service
shell_out!("/sbin/rc-update del #{@new_resource.service_name} default")
end
end
diff --git a/lib/chef/provider/service/insserv.rb b/lib/chef/provider/service/insserv.rb
index 76b2ee7477..c3dca10495 100644
--- a/lib/chef/provider/service/insserv.rb
+++ b/lib/chef/provider/service/insserv.rb
@@ -45,12 +45,12 @@ class Chef
current_resource
end
- def enable_service()
+ def enable_service
shell_out!("/sbin/insserv -r -f #{new_resource.service_name}")
shell_out!("/sbin/insserv -d -f #{new_resource.service_name}")
end
- def disable_service()
+ def disable_service
shell_out!("/sbin/insserv -r -f #{new_resource.service_name}")
end
end
diff --git a/lib/chef/provider/service/macosx.rb b/lib/chef/provider/service/macosx.rb
index 648cd9748b..4056b72649 100644
--- a/lib/chef/provider/service/macosx.rb
+++ b/lib/chef/provider/service/macosx.rb
@@ -181,7 +181,7 @@ class Chef
end
def set_service_status
- return if @plist == nil || @service_label.to_s.empty?
+ return if @plist.nil? || @service_label.to_s.empty?
cmd = "launchctl list #{@service_label}"
res = shell_out_as_user(cmd)
@@ -197,7 +197,7 @@ class Chef
case line.downcase
when /\s+\"pid\"\s+=\s+(\d+).*/
pid = $1
- @current_resource.running(!pid.to_i.zero?)
+ @current_resource.running(pid.to_i != 0)
Chef::Log.debug("Current PID for #{@service_label} is #{pid}")
end
end
diff --git a/lib/chef/provider/service/openbsd.rb b/lib/chef/provider/service/openbsd.rb
index c60bbf170c..780337e1b6 100644
--- a/lib/chef/provider/service/openbsd.rb
+++ b/lib/chef/provider/service/openbsd.rb
@@ -72,7 +72,7 @@ class Chef
end
requirements.assert(:start, :enable, :reload, :restart) do |a|
- a.assertion { init_command && builtin_service_enable_variable_name != nil }
+ a.assertion { init_command && !builtin_service_enable_variable_name.nil? }
a.failure_message Chef::Exceptions::Service, "Could not find the service name in #{init_command} and rcvar"
# No recovery in whyrun mode - the init file is present but not correct.
end
diff --git a/lib/chef/provider/service/redhat.rb b/lib/chef/provider/service/redhat.rb
index 200a2d3400..21ab678706 100644
--- a/lib/chef/provider/service/redhat.rb
+++ b/lib/chef/provider/service/redhat.rb
@@ -109,7 +109,7 @@ class Chef
(run_levels.nil? || run_levels.empty?) ? "" : "--level #{run_levels.join('')} "
end
- def enable_service()
+ def enable_service
unless run_levels.nil? || run_levels.empty?
disable_levels = current_run_levels - run_levels
shell_out! "/sbin/chkconfig --level #{disable_levels.join('')} #{new_resource.service_name} off" unless disable_levels.empty?
@@ -117,7 +117,7 @@ class Chef
shell_out! "/sbin/chkconfig #{levels}#{new_resource.service_name} on"
end
- def disable_service()
+ def disable_service
shell_out! "/sbin/chkconfig #{levels}#{new_resource.service_name} off"
end
end
diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb
index 868b3e1ac1..f7f8eaf31b 100644
--- a/lib/chef/provider/service/solaris.rb
+++ b/lib/chef/provider/service/solaris.rb
@@ -73,7 +73,7 @@ class Chef
def restart_service
## svcadm restart doesn't supports sync(-s) option
disable_service
- return enable_service
+ enable_service
end
def service_status
diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb
index 712f0f60c3..deec25b187 100644
--- a/lib/chef/provider/service/systemd.rb
+++ b/lib/chef/provider/service/systemd.rb
@@ -89,7 +89,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
args = "--system"
end
- return options, args
+ [options, args]
end
def start_service
diff --git a/lib/chef/provider/support/yum_repo.erb b/lib/chef/provider/support/yum_repo.erb
index 7d9a2d09e2..6f1325573d 100644
--- a/lib/chef/provider/support/yum_repo.erb
+++ b/lib/chef/provider/support/yum_repo.erb
@@ -4,8 +4,13 @@
[<%= @config.repositoryid %>]
name=<%= @config.description %>
<% if @config.baseurl %>
-baseurl=<%= @config.baseurl %>
-<% end %>
+baseurl=<%= case @config.baseurl
+ when Array
+ @config.baseurl.join("\n")
+ else
+ @config.baseurl
+ end %>
+<% end -%>
<% if @config.cost %>
cost=<%= @config.cost %>
<% end %>
@@ -24,7 +29,9 @@ exclude=<%= @config.exclude %>
failovermethod=<%= @config.failovermethod %>
<% end %>
<% if @config.fastestmirror_enabled %>
-fastestmirror_enabled=<%= @config.fastestmirror_enabled %>
+fastestmirror_enabled=1
+<% else %>
+fastestmirror_enabled=0
<% end %>
<% if @config.gpgcheck %>
gpgcheck=1
diff --git a/lib/chef/provider/systemd_unit.rb b/lib/chef/provider/systemd_unit.rb
index a656fbbf80..5175dc6be9 100644
--- a/lib/chef/provider/systemd_unit.rb
+++ b/lib/chef/provider/systemd_unit.rb
@@ -20,6 +20,7 @@ require "chef/provider"
require "chef/mixin/which"
require "chef/mixin/shell_out"
require "chef/resource/file"
+require "chef/resource/file/verification/systemd_unit"
require "iniparse"
class Chef
@@ -193,6 +194,7 @@ class Chef
f.group "root"
f.mode "0644"
f.content new_resource.to_ini
+ f.verify :systemd_unit
end.run_action(action)
end
diff --git a/lib/chef/provider/user.rb b/lib/chef/provider/user.rb
index 4b05ac8f5e..de94871a87 100644
--- a/lib/chef/provider/user.rb
+++ b/lib/chef/provider/user.rb
@@ -39,7 +39,7 @@ class Chef
if @new_resource.gid.is_a? String
@new_resource.gid(Etc.getgrnam(@new_resource.gid).gid)
end
- rescue ArgumentError => e
+ rescue ArgumentError
@group_name_resolved = false
end
@@ -53,7 +53,7 @@ class Chef
begin
user_info = Etc.getpwnam(@new_resource.username)
- rescue ArgumentError => e
+ rescue ArgumentError
@user_exists = false
Chef::Log.debug("#{@new_resource} user does not exist")
user_info = nil
@@ -97,7 +97,7 @@ class Chef
requirements.assert(:all_actions) do |a|
a.assertion { @shadow_lib_ok }
a.failure_message Chef::Exceptions::MissingLibrary, "You must have ruby-shadow installed for password support!"
- a.whyrun "ruby-shadow is not installed. Attempts to set user password will cause failure. Assuming that this gem will have been previously installed." +
+ a.whyrun "ruby-shadow is not installed. Attempts to set user password will cause failure. Assuming that this gem will have been previously installed." \
"Note that user update converge may report false-positive on the basis of mismatched password. "
end
requirements.assert(:modify, :lock, :unlock) do |a|
@@ -137,34 +137,31 @@ class Chef
end
def action_remove
- if @user_exists
- converge_by("remove user #{@new_resource.username}") do
- remove_user
- Chef::Log.info("#{@new_resource} removed")
- end
+ return unless @user_exists
+ converge_by("remove user #{@new_resource.username}") do
+ remove_user
+ Chef::Log.info("#{@new_resource} removed")
end
end
def action_manage
- if @user_exists && compare_user
- converge_by("manage user #{@new_resource.username}") do
- manage_user
- Chef::Log.info("#{@new_resource} managed")
- end
+ return unless @user_exists && compare_user
+ converge_by("manage user #{@new_resource.username}") do
+ manage_user
+ Chef::Log.info("#{@new_resource} managed")
end
end
def action_modify
- if compare_user
- converge_by("modify user #{@new_resource.username}") do
- manage_user
- Chef::Log.info("#{@new_resource} modified")
- end
+ return unless compare_user
+ converge_by("modify user #{@new_resource.username}") do
+ manage_user
+ Chef::Log.info("#{@new_resource} modified")
end
end
def action_lock
- if check_lock() == false
+ if check_lock == false
converge_by("lock the user #{@new_resource.username}") do
lock_user
Chef::Log.info("#{@new_resource} locked")
@@ -175,7 +172,7 @@ class Chef
end
def action_unlock
- if check_lock() == true
+ if check_lock == true
converge_by("unlock user #{@new_resource.username}") do
unlock_user
Chef::Log.info("#{@new_resource} unlocked")
diff --git a/lib/chef/provider/user/aix.rb b/lib/chef/provider/user/aix.rb
index 8ac229ae4d..0e81c76bbc 100644
--- a/lib/chef/provider/user/aix.rb
+++ b/lib/chef/provider/user/aix.rb
@@ -23,7 +23,7 @@ class Chef
provides :user, os: "aix"
provides :aix_user
- UNIVERSAL_OPTIONS = [[:comment, "-c"], [:gid, "-g"], [:shell, "-s"], [:uid, "-u"]]
+ UNIVERSAL_OPTIONS = [[:comment, "-c"], [:gid, "-g"], [:shell, "-s"], [:uid, "-u"]].freeze
def create_user
super
@@ -44,53 +44,52 @@ class Chef
end
def check_lock
- lock_info = shell_out!("lsuser -a account_locked #{new_resource.username}")
+ lock_info = shell_out_compact!("lsuser", "-a", "account_locked", new_resource.username)
if whyrun_mode? && passwd_s.stdout.empty? && lock_info.stderr.match(/does not exist/)
# if we're in whyrun mode and the user is not yet created we assume it would be
return false
end
- raise Chef::Exceptions::User, "Cannot determine if #{@new_resource} is locked!" if lock_info.stdout.empty?
+ raise Chef::Exceptions::User, "Cannot determine if #{new_resource} is locked!" if lock_info.stdout.empty?
status = /\S+\s+account_locked=(\S+)/.match(lock_info.stdout)
- if status && status[1] == "true"
- @locked = true
- else
- @locked = false
- end
+ @locked =
+ if status && status[1] == "true"
+ true
+ else
+ false
+ end
@locked
end
def lock_user
- shell_out!("chuser account_locked=true #{new_resource.username}")
+ shell_out_compact!("chuser", "account_locked=true", new_resource.username)
end
def unlock_user
- shell_out!("chuser account_locked=false #{new_resource.username}")
+ shell_out_compact!("chuser", "account_locked=false", new_resource.username)
end
private
def add_password
- if @current_resource.password != @new_resource.password && @new_resource.password
- Chef::Log.debug("#{@new_resource.username} setting password to #{@new_resource.password}")
- command = "echo '#{@new_resource.username}:#{@new_resource.password}' | chpasswd -e"
- shell_out!(command)
- end
+ return unless current_resource.password != new_resource.password && new_resource.password
+ Chef::Log.debug("#{new_resource.username} setting password to #{new_resource.password}")
+ command = "echo '#{new_resource.username}:#{new_resource.password}' | chpasswd -e"
+ shell_out!(command)
end
# Aix specific handling to update users home directory.
def manage_home
+ return unless updating_home? && managing_home_dir?
# -m option does not work on aix, so move dir.
- if updating_home? && managing_home_dir?
- universal_options.delete("-m")
- if ::File.directory?(@current_resource.home)
- Chef::Log.debug("Changing users home directory from #{@current_resource.home} to #{new_resource.home}")
- shell_out!("mv #{@current_resource.home} #{new_resource.home}")
- else
- Chef::Log.debug("Creating users home directory #{new_resource.home}")
- shell_out!("mkdir -p #{new_resource.home}")
- end
+ universal_options.delete("-m")
+ if ::File.directory?(current_resource.home)
+ Chef::Log.debug("Changing users home directory from #{current_resource.home} to #{new_resource.home}")
+ FileUtils.mv current_resource.home, new_resource.home
+ else
+ Chef::Log.debug("Creating users home directory #{new_resource.home}")
+ FileUtils.mkdir_p new_resource.home
end
end
diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb
index 16d60ba116..2302a874e2 100644
--- a/lib/chef/provider/user/dscl.rb
+++ b/lib/chef/provider/user/dscl.rb
@@ -65,12 +65,12 @@ class Chef
end
requirements.assert(:all_actions) do |a|
- a.assertion { ::File.exists?("/usr/bin/dscl") }
+ a.assertion { ::File.exist?("/usr/bin/dscl") }
a.failure_message(Chef::Exceptions::User, "Cannot find binary '/usr/bin/dscl' on the system for #{new_resource}!")
end
requirements.assert(:all_actions) do |a|
- a.assertion { ::File.exists?("/usr/bin/plutil") }
+ a.assertion { ::File.exist?("/usr/bin/plutil") }
a.failure_message(Chef::Exceptions::User, "Cannot find binary '/usr/bin/plutil' on the system for #{new_resource}!")
end
@@ -199,7 +199,7 @@ user password using shadow hash.")
# Create a user using dscl
#
def dscl_create_user
- run_dscl("create /Users/#{new_resource.username}")
+ run_dscl("create", "/Users/#{new_resource.username}")
end
#
@@ -208,7 +208,7 @@ user password using shadow hash.")
#
def dscl_create_comment
comment = new_resource.comment || new_resource.username
- run_dscl("create /Users/#{new_resource.username} RealName '#{comment}'")
+ run_dscl("create", "/Users/#{new_resource.username}", "RealName", comment)
end
#
@@ -224,7 +224,7 @@ user password using shadow hash.")
raise(Chef::Exceptions::RequestedUIDUnavailable, "uid #{new_resource.uid} is already in use")
end
- run_dscl("create /Users/#{new_resource.username} UniqueID #{new_resource.uid}")
+ run_dscl("create", "/Users/#{new_resource.username}", "UniqueID", new_resource.uid)
end
#
@@ -235,7 +235,7 @@ user password using shadow hash.")
uid = nil
base_uid = new_resource.system ? 200 : 500
next_uid_guess = base_uid
- users_uids = run_dscl("list /Users uid")
+ users_uids = run_dscl("list", "/Users", "uid")
while next_uid_guess < search_limit + base_uid
if users_uids =~ Regexp.new("#{Regexp.escape(next_uid_guess.to_s)}\n")
next_uid_guess += 1
@@ -244,7 +244,7 @@ user password using shadow hash.")
break
end
end
- return uid || raise("uid not found. Exhausted. Searched #{search_limit} times")
+ uid || raise("uid not found. Exhausted. Searched #{search_limit} times")
end
#
@@ -252,18 +252,18 @@ user password using shadow hash.")
#
def uid_used?(uid)
return false unless uid
- users_uids = run_dscl("list /Users uid").split("\n")
- uid_map = users_uids.inject({}) do |tmap, tuid|
+ users_uids = run_dscl("list", "/Users", "uid").split("\n")
+ uid_map = users_uids.each_with_object({}) do |tuid, tmap|
x = tuid.split
tmap[x[1]] = x[0]
tmap
end
if uid_map[uid.to_s]
- unless uid_map[uid.to_s] == new_resource.username.to_s
+ unless uid_map[uid.to_s] == new_resource.username
return true
end
end
- return false
+ false
end
#
@@ -277,14 +277,14 @@ user password using shadow hash.")
new_resource.gid(STAFF_GROUP_ID)
elsif !new_resource.gid.to_s.match(/^\d+$/)
begin
- possible_gid = run_dscl("read /Groups/#{new_resource.gid} PrimaryGroupID").split(" ").last
- rescue Chef::Exceptions::DsclCommandFailed => e
- raise Chef::Exceptions::GroupIDNotFound.new("Group not found for #{new_resource.gid} when creating user #{new_resource.username}")
+ possible_gid = run_dscl("read", "/Groups/#{new_resource.gid}", "PrimaryGroupID").split(" ").last
+ rescue Chef::Exceptions::DsclCommandFailed
+ raise Chef::Exceptions::GroupIDNotFound, "Group not found for #{new_resource.gid} when creating user #{new_resource.username}"
end
# XXX: mutates the new resource
new_resource.gid(possible_gid) if possible_gid && possible_gid.match(/^\d+$/)
end
- run_dscl("create /Users/#{new_resource.username} PrimaryGroupID '#{new_resource.gid}'")
+ run_dscl("create", "/Users/#{new_resource.username}", "PrimaryGroupID", new_resource.gid)
end
#
@@ -293,7 +293,7 @@ user password using shadow hash.")
#
def dscl_set_home
if new_resource.home.nil? || new_resource.home.empty?
- run_dscl("delete /Users/#{new_resource.username} NFSHomeDirectory")
+ run_dscl("delete", "/Users/#{new_resource.username}", "NFSHomeDirectory")
return
end
@@ -308,7 +308,7 @@ user password using shadow hash.")
move_home
end
end
- run_dscl("create /Users/#{new_resource.username} NFSHomeDirectory '#{new_resource.home}'")
+ run_dscl("create", "/Users/#{new_resource.username}", "NFSHomeDirectory", new_resource.home)
end
def validate_home_dir_specification!
@@ -318,17 +318,17 @@ user password using shadow hash.")
end
def current_home_exists?
- ::File.exist?("#{current_resource.home}")
+ ::File.exist?(current_resource.home)
end
def new_home_exists?
- ::File.exist?("#{new_resource.home}")
+ ::File.exist?(new_resource.home)
end
def ditto_home
skel = "/System/Library/User Template/English.lproj"
- raise(Chef::Exceptions::User, "can't find skel at: #{skel}") unless ::File.exists?(skel)
- shell_out! "ditto '#{skel}' '#{new_resource.home}'"
+ raise(Chef::Exceptions::User, "can't find skel at: #{skel}") unless ::File.exist?(skel)
+ shell_out_compact!("ditto", skel, new_resource.home)
::FileUtils.chown_R(new_resource.username, new_resource.gid.to_s, new_resource.home)
end
@@ -338,7 +338,7 @@ user password using shadow hash.")
src = current_resource.home
FileUtils.mkdir_p(new_resource.home)
files = ::Dir.glob("#{Chef::Util::PathHelper.escape_glob_dir(src)}/*", ::File::FNM_DOTMATCH) - ["#{src}/.", "#{src}/.."]
- ::FileUtils.mv(files, new_resource.home, :force => true)
+ ::FileUtils.mv(files, new_resource.home, force: true)
::FileUtils.rmdir(src)
::FileUtils.chown_R(new_resource.username, new_resource.gid.to_s, new_resource.home)
end
@@ -347,10 +347,10 @@ user password using shadow hash.")
# Sets the shell for the user using dscl.
#
def dscl_set_shell
- if new_resource.shell || ::File.exists?("#{new_resource.shell}")
- run_dscl("create /Users/#{new_resource.username} UserShell '#{new_resource.shell}'")
+ if new_resource.shell
+ run_dscl("create", "/Users/#{new_resource.username}", "UserShell", new_resource.shell)
else
- run_dscl("create /Users/#{new_resource.username} UserShell '/usr/bin/false'")
+ run_dscl("create", "/Users/#{new_resource.username}", "UserShell", "/usr/bin/false")
end
end
@@ -367,9 +367,8 @@ user password using shadow hash.")
# Shadow info is saved as binary plist. Convert the info to binary plist.
shadow_info_binary = StringIO.new
- command = Mixlib::ShellOut.new("plutil -convert binary1 -o - -",
- :input => shadow_info.to_plist, :live_stream => shadow_info_binary)
- command.run_command
+ shell_out_compact("plutil", "-convert", "binary1", "-o", "-", "-",
+ input: shadow_info.to_plist, live_stream: shadow_info_binary)
if user_info.nil?
# User is just created. read_user_info() will read the fresh information
@@ -401,7 +400,7 @@ user password using shadow hash.")
# Create a random 4 byte salt
salt = OpenSSL::Random.random_bytes(4)
encoded_password = OpenSSL::Digest::SHA512.hexdigest(salt + new_resource.password)
- hash_value = salt.unpack("H*").first + encoded_password
+ salt.unpack("H*").first + encoded_password
end
shadow_info["SALTED-SHA512"] = StringIO.new
@@ -449,21 +448,21 @@ user password using shadow hash.")
end
# Remove the user from its groups
- run_dscl("list /Groups").each_line do |group|
+ run_dscl("list", "/Groups").each_line do |group|
if member_of_group?(group.chomp)
- run_dscl("delete /Groups/#{group.chomp} GroupMembership '#{new_resource.username}'")
+ run_dscl("delete", "/Groups/#{group.chomp}", "GroupMembership", new_resource.username)
end
end
# Remove user account
- run_dscl("delete /Users/#{new_resource.username}")
+ run_dscl("delete", "/Users/#{new_resource.username}")
end
#
# Locks the user.
#
def lock_user
- run_dscl("append /Users/#{new_resource.username} AuthenticationAuthority ';DisabledUser;'")
+ run_dscl("append", "/Users/#{new_resource.username}", "AuthenticationAuthority", ";DisabledUser;")
end
#
@@ -471,7 +470,7 @@ user password using shadow hash.")
#
def unlock_user
auth_string = authentication_authority.gsub(/AuthenticationAuthority: /, "").gsub(/;DisabledUser;/, "").strip
- run_dscl("create /Users/#{new_resource.username} AuthenticationAuthority '#{auth_string}'")
+ run_dscl("create", "/Users/#{new_resource.username}", "AuthenticationAuthority", auth_string)
end
#
@@ -489,7 +488,7 @@ user password using shadow hash.")
# This is the interface base User provider requires to provide idempotency.
#
def check_lock
- return @locked = locked?
+ @locked = locked?
end
#
@@ -501,11 +500,11 @@ user password using shadow hash.")
# given attribute.
#
def diverged?(parameter)
- parameter_updated?(parameter) && (not new_resource.send(parameter).nil?)
+ parameter_updated?(parameter) && !new_resource.send(parameter).nil?
end
def parameter_updated?(parameter)
- not (new_resource.send(parameter) == current_resource.send(parameter))
+ !(new_resource.send(parameter) == current_resource.send(parameter))
end
#
@@ -551,7 +550,7 @@ user password using shadow hash.")
def member_of_group?(group_name)
membership_info = ""
begin
- membership_info = run_dscl("read /Groups/#{group_name}")
+ membership_info = run_dscl("read", "/Groups/#{group_name}")
rescue Chef::Exceptions::DsclCommandFailed
# Raised if the group doesn't contain any members
end
@@ -568,14 +567,14 @@ user password using shadow hash.")
# A simple map of Chef's terms to DSCL's terms.
DSCL_PROPERTY_MAP = {
- :uid => "uid",
- :gid => "gid",
- :home => "home",
- :shell => "shell",
- :comment => "realname",
- :password => "passwd",
- :auth_authority => "authentication_authority",
- :shadow_hash => "ShadowHashData",
+ uid: "uid",
+ gid: "gid",
+ home: "home",
+ shell: "shell",
+ comment: "realname",
+ password: "passwd",
+ auth_authority: "authentication_authority",
+ shadow_hash: "ShadowHashData",
}.freeze
# Directory where the user plist files are stored for versions 10.7 and above
@@ -590,11 +589,11 @@ user password using shadow hash.")
# We flush the cache here in order to make sure that we read fresh information
# for the user.
- shell_out("dscacheutil '-flushcache'")
+ shell_out_compact("dscacheutil", "-flushcache") # FIXME: this is MacOS version dependent
begin
user_plist_file = "#{USER_PLIST_DIRECTORY}/#{new_resource.username}.plist"
- user_plist_info = run_plutil("convert xml1 -o - #{user_plist_file}")
+ user_plist_info = run_plutil("convert", "xml1", "-o", "-", user_plist_file)
user_info = Plist.parse_xml(user_plist_info)
rescue Chef::Exceptions::PlistUtilCommandFailed
end
@@ -609,7 +608,7 @@ user password using shadow hash.")
def save_user_info(user_info)
user_plist_file = "#{USER_PLIST_DIRECTORY}/#{new_resource.username}.plist"
Plist::Emit.save_plist(user_info, user_plist_file)
- run_plutil("convert binary1 #{user_plist_file}")
+ run_plutil("convert", "binary1", user_plist_file)
end
#
@@ -658,7 +657,9 @@ user password using shadow hash.")
end
def run_dscl(*args)
- result = shell_out("dscl . -#{args.join(' ')}")
+ argdup = args.dup
+ cmd = argdup.shift
+ result = shell_out_compact("dscl", ".", "-#{cmd}", argdup)
return "" if ( args.first =~ /^delete/ ) && ( result.exitstatus != 0 )
raise(Chef::Exceptions::DsclCommandFailed, "dscl error: #{result.inspect}") unless result.exitstatus == 0
raise(Chef::Exceptions::DsclCommandFailed, "dscl error: #{result.inspect}") if result.stdout =~ /No such key: /
@@ -666,17 +667,19 @@ user password using shadow hash.")
end
def run_plutil(*args)
- result = shell_out("plutil -#{args.join(' ')}")
+ argdup = args.dup
+ cmd = argdup.shift
+ result = shell_out_compact("plutil", "-#{cmd}", argdup)
raise(Chef::Exceptions::PlistUtilCommandFailed, "plutil error: #{result.inspect}") unless result.exitstatus == 0
if result.stdout.encoding == Encoding::ASCII_8BIT
- result.stdout.encode("utf-8", "binary", :undef => :replace, :invalid => :replace, :replace => "?")
+ result.stdout.encode("utf-8", "binary", undef: :replace, invalid: :replace, replace: "?")
else
result.stdout
end
end
def convert_binary_plist_to_xml(binary_plist_string)
- Mixlib::ShellOut.new("plutil -convert xml1 -o - -", :input => binary_plist_string).run_command.stdout
+ shell_out_compact("plutil", "-convert", "xml1", "-o", "-", "-", input: binary_plist_string).stdout
end
def convert_to_binary(string)
diff --git a/lib/chef/provider/user/linux.rb b/lib/chef/provider/user/linux.rb
index 968cf771e4..445421ad38 100644
--- a/lib/chef/provider/user/linux.rb
+++ b/lib/chef/provider/user/linux.rb
@@ -24,23 +24,23 @@ class Chef
provides :user, os: "linux"
def create_user
- shell_out!(*clean_array("useradd", universal_options, useradd_options, new_resource.username))
+ shell_out_compact!("useradd", universal_options, useradd_options, new_resource.username)
end
def manage_user
- shell_out!(*clean_array("usermod", universal_options, usermod_options, new_resource.username))
+ shell_out_compact!("usermod", universal_options, usermod_options, new_resource.username)
end
def remove_user
- shell_out!(*clean_array("userdel", userdel_options, new_resource.username))
+ shell_out_compact!("userdel", userdel_options, new_resource.username)
end
def lock_user
- shell_out!(*clean_array("usermod", "-L", new_resource.username))
+ shell_out_compact!("usermod", "-L", new_resource.username)
end
def unlock_user
- shell_out!(*clean_array("usermod", "-U", new_resource.username))
+ shell_out_compact!("usermod", "-U", new_resource.username)
end
# common to usermod and useradd
@@ -69,11 +69,11 @@ class Chef
def useradd_options
opts = []
opts << "-r" if new_resource.system
- if managing_home_dir?
- opts << "-m"
- else
- opts << "-M"
- end
+ opts << if managing_home_dir?
+ "-m"
+ else
+ "-M"
+ end
opts
end
@@ -97,15 +97,12 @@ class Chef
def check_lock
# there's an old bug in rhel (https://bugzilla.redhat.com/show_bug.cgi?id=578534)
# which means that both 0 and 1 can be success.
- passwd_s = shell_out("passwd", "-S", new_resource.username, returns: [ 0, 1 ])
+ passwd_s = shell_out_compact("passwd", "-S", new_resource.username, returns: [ 0, 1 ])
# checking "does not exist" has to come before exit code handling since centos and ubuntu differ in exit codes
if passwd_s.stderr =~ /does not exist/
- if whyrun_mode?
- return false
- else
- raise Chef::Exceptions::User, "User #{new_resource.username} does not exist when checking lock status for #{new_resource}"
- end
+ return false if whyrun_mode?
+ raise Chef::Exceptions::User, "User #{new_resource.username} does not exist when checking lock status for #{new_resource}"
end
# now raise if we didn't get a 0 or 1 (see above)
diff --git a/lib/chef/provider/user/pw.rb b/lib/chef/provider/user/pw.rb
index b210374eb9..42d862a983 100644
--- a/lib/chef/provider/user/pw.rb
+++ b/lib/chef/provider/user/pw.rb
@@ -27,49 +27,45 @@ class Chef
def load_current_resource
super
- raise Chef::Exceptions::User, "Could not find binary /usr/sbin/pw for #{@new_resource}" unless ::File.exists?("/usr/sbin/pw")
+ raise Chef::Exceptions::User, "Could not find binary /usr/sbin/pw for #{new_resource}" unless ::File.exist?("/usr/sbin/pw")
end
def create_user
- command = "pw useradd"
- command << set_options
- run_command(:command => command)
+ shell_out_compact!("pw", "useradd", set_options)
modify_password
end
def manage_user
- command = "pw usermod"
- command << set_options
- run_command(:command => command)
+ shell_out_compact!("pw", "usermod", set_options)
modify_password
end
def remove_user
- command = "pw userdel #{@new_resource.username}"
- command << " -r" if managing_home_dir?
- run_command(:command => command)
+ command = [ "pw", "userdel", new_resource.username ]
+ command << "-r" if managing_home_dir?
+ shell_out_compact!(command)
end
def check_lock
- case @current_resource.password
- when /^\*LOCKED\*/
- @locked = true
- else
- @locked = false
- end
+ @locked = case current_resource.password
+ when /^\*LOCKED\*/
+ true
+ else
+ false
+ end
@locked
end
def lock_user
- run_command(:command => "pw lock #{@new_resource.username}")
+ shell_out_compact!("pw", "lock", new_resource.username)
end
def unlock_user
- run_command(:command => "pw unlock #{@new_resource.username}")
+ shell_out_compact!("pw", "unlock", new_resource.username)
end
def set_options
- opts = " #{@new_resource.username}"
+ opts = [ new_resource.username ]
field_list = {
"comment" => "-c",
@@ -80,26 +76,26 @@ class Chef
}
field_list.sort { |a, b| a[0] <=> b[0] }.each do |field, option|
field_symbol = field.to_sym
- if @current_resource.send(field_symbol) != @new_resource.send(field_symbol)
- if @new_resource.send(field_symbol)
- Chef::Log.debug("#{@new_resource} setting #{field} to #{@new_resource.send(field_symbol)}")
- opts << " #{option} '#{@new_resource.send(field_symbol)}'"
- end
+ next unless current_resource.send(field_symbol) != new_resource.send(field_symbol)
+ if new_resource.send(field_symbol)
+ Chef::Log.debug("#{new_resource} setting #{field} to #{new_resource.send(field_symbol)}")
+ opts << option
+ opts << new_resource.send(field_symbol)
end
end
if managing_home_dir?
- Chef::Log.debug("#{@new_resource} is managing the users home directory")
- opts << " -m"
+ Chef::Log.debug("#{new_resource} is managing the users home directory")
+ opts << "-m"
end
opts
end
def modify_password
- if (not @new_resource.password.nil?) && (@current_resource.password != @new_resource.password)
+ 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}"
+ 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
diff --git a/lib/chef/provider/user/solaris.rb b/lib/chef/provider/user/solaris.rb
index 7aa0ceb93a..4e772312ae 100644
--- a/lib/chef/provider/user/solaris.rb
+++ b/lib/chef/provider/user/solaris.rb
@@ -26,7 +26,7 @@ class Chef
class Solaris < Chef::Provider::User::Useradd
provides :solaris_user
provides :user, os: %w{omnios solaris2}
- UNIVERSAL_OPTIONS = [[:comment, "-c"], [:gid, "-g"], [:shell, "-s"], [:uid, "-u"]]
+ UNIVERSAL_OPTIONS = [[:comment, "-c"], [:gid, "-g"], [:shell, "-s"], [:uid, "-u"]].freeze
attr_writer :password_file
@@ -46,22 +46,22 @@ class Chef
end
def check_lock
- user = IO.read(@password_file).match(/^#{Regexp.escape(@new_resource.username)}:([^:]*):/)
+ user = IO.read(@password_file).match(/^#{Regexp.escape(new_resource.username)}:([^:]*):/)
# If we're in whyrun mode, and the user is not created, we assume it will be
return false if whyrun_mode? && user.nil?
- raise Chef::Exceptions::User, "Cannot determine if #{@new_resource} is locked!" if user.nil?
+ raise Chef::Exceptions::User, "Cannot determine if #{new_resource} is locked!" if user.nil?
@locked = user[1].start_with?("*LK*")
end
def lock_user
- shell_out!("passwd", "-l", new_resource.username)
+ shell_out_compact!("passwd", "-l", new_resource.username)
end
def unlock_user
- shell_out!("passwd", "-u", new_resource.username)
+ shell_out_compact!("passwd", "-u", new_resource.username)
end
private
@@ -82,10 +82,9 @@ class Chef
end
def manage_password
- if @current_resource.password != @new_resource.password && @new_resource.password
- Chef::Log.debug("#{@new_resource} setting password to #{@new_resource.password}")
- write_shadow_file
- end
+ return unless current_resource.password != new_resource.password && new_resource.password
+ Chef::Log.debug("#{new_resource} setting password to #{new_resource.password}")
+ write_shadow_file
end
def write_shadow_file
@@ -93,7 +92,7 @@ class Chef
::File.open(@password_file) do |shadow_file|
shadow_file.each do |entry|
user = entry.split(":").first
- if user == @new_resource.username
+ if user == new_resource.username
buffer.write(updated_password(entry))
else
buffer.write(entry)
@@ -104,7 +103,7 @@ class Chef
# FIXME: mostly duplicates code with file provider deploying a file
s = ::File.stat(@password_file)
- mode = s.mode & 07777
+ mode = s.mode & 0o7777
uid = s.uid
gid = s.gid
@@ -116,7 +115,7 @@ class Chef
def updated_password(entry)
fields = entry.split(":")
- fields[1] = @new_resource.password
+ fields[1] = new_resource.password
fields[2] = days_since_epoch
fields.join(":")
end
diff --git a/lib/chef/provider/user/useradd.rb b/lib/chef/provider/user/useradd.rb
index 35a106b0b6..cf6f4e727f 100644
--- a/lib/chef/provider/user/useradd.rb
+++ b/lib/chef/provider/user/useradd.rb
@@ -23,25 +23,25 @@ class Chef
class Provider
class User
class Useradd < Chef::Provider::User
- # MAJOR XXX: this should become the base class of all Useradd providers instead of the linux implementation
+ # the linux version of this has been forked off, this is the base class now of solaris and AIX and should be abandoned
+ # and those provider should be rewritten like the linux version.
- UNIVERSAL_OPTIONS = [[:comment, "-c"], [:gid, "-g"], [:password, "-p"], [:shell, "-s"], [:uid, "-u"]]
+ UNIVERSAL_OPTIONS = [[:comment, "-c"], [:gid, "-g"], [:password, "-p"], [:shell, "-s"], [:uid, "-u"]].freeze
def create_user
command = compile_command("useradd") do |useradd|
useradd.concat(universal_options)
useradd.concat(useradd_options)
end
- shell_out!(*command)
+ shell_out_compact!(command)
end
def manage_user
- unless universal_options.empty?
- command = compile_command("usermod") do |u|
- u.concat(universal_options)
- end
- shell_out!(*command)
+ return if universal_options.empty?
+ command = compile_command("usermod") do |u|
+ u.concat(universal_options)
end
+ shell_out_compact!(command)
end
def remove_user
@@ -49,19 +49,19 @@ class Chef
command << "-r" if managing_home_dir?
command << "-f" if new_resource.force
command << new_resource.username
- shell_out!(*command)
+ shell_out_compact!(command)
end
def check_lock
# we can get an exit code of 1 even when it's successful on
# rhel/centos (redhat bug 578534). See additional error checks below.
- passwd_s = shell_out!("passwd", "-S", new_resource.username, :returns => [0, 1])
+ passwd_s = shell_out_compact!("passwd", "-S", new_resource.username, returns: [0, 1])
if whyrun_mode? && passwd_s.stdout.empty? && passwd_s.stderr.match(/does not exist/)
# if we're in whyrun mode and the user is not yet created we assume it would be
return false
end
- raise Chef::Exceptions::User, "Cannot determine if #{@new_resource} is locked!" if passwd_s.stdout.empty?
+ raise Chef::Exceptions::User, "Cannot determine if #{new_resource} is locked!" if passwd_s.stdout.empty?
status_line = passwd_s.stdout.split(" ")
case status_line[1]
@@ -76,7 +76,7 @@ class Chef
unless passwd_s.exitstatus == 0
raise_lock_error = false
if %w{redhat centos}.include?(node[:platform])
- passwd_version_check = shell_out!("rpm -q passwd")
+ passwd_version_check = shell_out_compact!("rpm", "-q", "passwd")
passwd_version = passwd_version_check.stdout.chomp
unless passwd_version == "passwd-0.73-1"
@@ -93,11 +93,11 @@ class Chef
end
def lock_user
- shell_out!("usermod", "-L", new_resource.username)
+ shell_out_compact!("usermod", "-L", new_resource.username)
end
def unlock_user
- shell_out!("usermod", "-U", new_resource.username)
+ shell_out_compact!("usermod", "-U", new_resource.username)
end
def compile_command(base_command)
@@ -130,12 +130,10 @@ class Chef
end
def update_options(field, option, opts)
- if @current_resource.send(field).to_s != new_resource.send(field).to_s
- if new_resource.send(field)
- Chef::Log.debug("#{new_resource} setting #{field} to #{new_resource.send(field)}")
- opts << option << new_resource.send(field).to_s
- end
- end
+ return unless current_resource.send(field).to_s != new_resource.send(field).to_s
+ return unless new_resource.send(field)
+ Chef::Log.debug("#{new_resource} setting #{field} to #{new_resource.send(field)}")
+ opts << option << new_resource.send(field).to_s
end
def useradd_options
@@ -150,8 +148,8 @@ class Chef
# Pathname#cleanpath does a better job than ::File::expand_path (on both unix and windows)
# ::File.expand_path("///tmp") == ::File.expand_path("/tmp") => false
# ::File.expand_path("\\tmp") => "C:/tmp"
- return true if @current_resource.home.nil? && new_resource.home
- new_resource.home && Pathname.new(@current_resource.home).cleanpath != Pathname.new(new_resource.home).cleanpath
+ return true if current_resource.home.nil? && new_resource.home
+ new_resource.home && Pathname.new(current_resource.home).cleanpath != Pathname.new(new_resource.home).cleanpath
end
end
diff --git a/lib/chef/provider/user/windows.rb b/lib/chef/provider/user/windows.rb
index b086a1e32b..0afa8fa14a 100644
--- a/lib/chef/provider/user/windows.rb
+++ b/lib/chef/provider/user/windows.rb
@@ -31,31 +31,30 @@ class Chef
def initialize(new_resource, run_context)
super
- @net_user = Chef::Util::Windows::NetUser.new(@new_resource.username)
+ @net_user = Chef::Util::Windows::NetUser.new(new_resource.username)
end
def load_current_resource
- if @new_resource.gid
+ if new_resource.gid
Chef::Log.warn("The 'gid' attribute is not implemented by the Windows platform. Please use the 'group' resource to assign a user to a group.")
end
- @current_resource = Chef::Resource::User.new(@new_resource.name)
- @current_resource.username(@new_resource.username)
- user_info = nil
+ @current_resource = Chef::Resource::User.new(new_resource.name)
+ current_resource.username(new_resource.username)
begin
user_info = @net_user.get_info
- @current_resource.uid(user_info[:user_id])
- @current_resource.comment(user_info[:full_name])
- @current_resource.home(user_info[:home_dir])
- @current_resource.shell(user_info[:script_path])
+ current_resource.uid(user_info[:user_id])
+ current_resource.comment(user_info[:full_name])
+ current_resource.home(user_info[:home_dir])
+ current_resource.shell(user_info[:script_path])
rescue Chef::Exceptions::UserIDNotFound => e
# e.message should be "The user name could not be found" but checking for that could cause a localization bug
@user_exists = false
- Chef::Log.debug("#{@new_resource} does not exist (#{e.message})")
+ Chef::Log.debug("#{new_resource} does not exist (#{e.message})")
end
- @current_resource
+ current_resource
end
# Check to see if the user needs any changes
@@ -64,12 +63,12 @@ class Chef
# <true>:: If a change is required
# <false>:: If the users are identical
def compare_user
- unless @net_user.validate_credentials(@new_resource.password)
- Chef::Log.debug("#{@new_resource} password has changed")
+ unless @net_user.validate_credentials(new_resource.password)
+ Chef::Log.debug("#{new_resource} password has changed")
return true
end
[ :uid, :comment, :home, :shell ].any? do |user_attrib|
- !@new_resource.send(user_attrib).nil? && @new_resource.send(user_attrib) != @current_resource.send(user_attrib)
+ !new_resource.send(user_attrib).nil? && new_resource.send(user_attrib) != current_resource.send(user_attrib)
end
end
@@ -98,7 +97,7 @@ class Chef
end
def set_options
- opts = { :name => @new_resource.username }
+ opts = { name: new_resource.username }
field_list = {
"comment" => "full_name",
@@ -110,14 +109,12 @@ class Chef
field_list.sort { |a, b| a[0] <=> b[0] }.each do |field, option|
field_symbol = field.to_sym
- if @current_resource.send(field_symbol) != @new_resource.send(field_symbol)
- if @new_resource.send(field_symbol)
- unless field_symbol == :password
- Chef::Log.debug("#{@new_resource} setting #{field} to #{@new_resource.send(field_symbol)}")
- end
- opts[option.to_sym] = @new_resource.send(field_symbol)
- end
+ next unless current_resource.send(field_symbol) != new_resource.send(field_symbol)
+ next unless new_resource.send(field_symbol)
+ unless field_symbol == :password
+ Chef::Log.debug("#{new_resource} setting #{field} to #{new_resource.send(field_symbol)}")
end
+ opts[option.to_sym] = new_resource.send(field_symbol)
end
opts
end
diff --git a/lib/chef/provider_resolver.rb b/lib/chef/provider_resolver.rb
index 1df473abbd..2eb4d72ba5 100644
--- a/lib/chef/provider_resolver.rb
+++ b/lib/chef/provider_resolver.rb
@@ -90,8 +90,10 @@ class Chef
@prioritized_handlers ||= begin
supported_handlers = self.supported_handlers
if supported_handlers.empty?
- # if none of the providers specifically support the resource, we still need to pick one of the providers that are
- # enabled on the node to handle the why-run use case. FIXME we should only do this in why-run mode then.
+ # We always require a provider to be able to call define_resource_requirements on. In the why-run case we need
+ # a provider to say "assuming /etc/init.d/whatever would have been installed" and in the non-why-run case we
+ # need to make a best guess at "cannot find /etc/init.d/whatever". We are essentially defining a "default" provider
+ # for the platform, which is the best we can do, but which might give misleading errors, but we cannot read minds.
Chef::Log.debug "No providers responded true to `supports?` for action #{action} on resource #{resource}, falling back to enabled handlers so we can return something anyway."
supported_handlers = enabled_handlers
end
@@ -157,8 +159,8 @@ class Chef
# perf concern otherwise.)
handlers = providers.select { |handler| overrode_provides?(handler) && handler.provides?(node, resource) }
handlers.each do |handler|
- Chef.log_deprecation("#{handler}.provides? returned true when asked if it provides DSL #{resource.resource_name}, but provides #{resource.resource_name.inspect} was never called!")
- Chef.log_deprecation("In Chef 13, this will break: you must call provides to mark the names you provide, even if you also override provides? yourself.")
+ message = "#{handler}.provides? returned true when asked if it provides DSL #{resource.resource_name}, but provides #{resource.resource_name.inspect} was never called! In Chef 13, this will break: you must call provides to mark the names you provide, even if you also override provides? yourself."
+ Chef.deprecated(:custom_resource, message)
end
end
handlers
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index 596629290b..35722840e6 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -65,6 +65,7 @@ require "chef/provider/env/windows"
require "chef/provider/package/apt"
require "chef/provider/package/chocolatey"
require "chef/provider/package/dpkg"
+require "chef/provider/package/dnf"
require "chef/provider/package/easy_install"
require "chef/provider/package/freebsd/port"
require "chef/provider/package/freebsd/pkg"
@@ -84,6 +85,8 @@ require "chef/provider/package/solaris"
require "chef/provider/package/smartos"
require "chef/provider/package/aix"
require "chef/provider/package/cab"
+require "chef/provider/package/powershell"
+require "chef/provider/package/msu"
require "chef/provider/service/arch"
require "chef/provider/service/freebsd"
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 074ab772a1..40911cd2cc 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -579,7 +579,7 @@ class Chef
def load_from(resource)
resource.instance_variables.each do |iv|
unless iv == :@source_line || iv == :@action || iv == :@not_if || iv == :@only_if
- self.instance_variable_set(iv, resource.instance_variable_get(iv))
+ instance_variable_set(iv, resource.instance_variable_get(iv))
end
end
end
@@ -667,21 +667,34 @@ class Chef
def to_text
return "suppressed sensitive resource output" if sensitive
- ivars = instance_variables.map { |ivar| ivar.to_sym } - HIDDEN_IVARS
text = "# Declared in #{@source_line}\n\n"
text << "#{resource_name}(\"#{name}\") do\n"
+
+ all_props = {}
+ self.class.state_properties.map do |p|
+ all_props[p.name.to_s] = p.sensitive? ? '"*sensitive value suppressed*"' : value_to_text(p.get(self))
+ end
+
+ ivars = instance_variables.map { |ivar| ivar.to_sym } - HIDDEN_IVARS
ivars.each do |ivar|
- if (value = instance_variable_get(ivar)) && !(value.respond_to?(:empty?) && value.empty?)
- value_string = value.respond_to?(:to_text) ? value.to_text : value.inspect
- text << " #{ivar.to_s.sub(/^@/, '')} #{value_string}\n"
+ iv = ivar.to_s.sub(/^@/, "")
+ if all_props.keys.include?(iv)
+ text << " #{iv} #{all_props[iv]}\n"
+ elsif (value = instance_variable_get(ivar)) && !(value.respond_to?(:empty?) && value.empty?)
+ text << " #{iv} #{value_to_text(value)}\n"
end
end
+
[@not_if, @only_if].flatten.each do |conditional|
text << " #{conditional.to_text}\n"
end
text << "end\n"
end
+ def value_to_text(value)
+ value.respond_to?(:to_text) ? value.to_text : value.inspect
+ end
+
def inspect
ivars = instance_variables.map { |ivar| ivar.to_sym } - FORBIDDEN_IVARS
ivars.inject("<#{self}") do |str, ivar|
@@ -726,7 +739,7 @@ class Chef
end
def self.json_create(o)
- resource = self.new(o["instance_vars"]["@name"])
+ resource = new(o["instance_vars"]["@name"])
o["instance_vars"].each do |k, v|
resource.instance_variable_set("@#{k}".to_sym, v)
end
@@ -925,9 +938,7 @@ class Chef
# @deprecated Multiple actions are supported by resources. Please call {}#updated_by_last_action} instead.
#
def updated=(true_or_false)
- Chef::Log.warn("Chef::Resource#updated=(true|false) is deprecated. Please call #updated_by_last_action(true|false) instead.")
- Chef::Log.warn("Called from:")
- caller[0..3].each { |line| Chef::Log.warn(line) }
+ 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
@@ -982,7 +993,7 @@ class Chef
# @deprecated Use resource_name instead.
#
def self.dsl_name
- Chef.log_deprecation "Resource.dsl_name is deprecated and will be removed in Chef 13. Use resource_name instead."
+ Chef.deprecated(:custom_resource, "Resource.dsl_name is deprecated and will be removed in Chef 13. Use resource_name instead.")
if name
name = self.name.split("::")[-1]
convert_to_snake_case(name)
@@ -1038,7 +1049,7 @@ class Chef
# A::B::BlahDBlah -> blah_d_blah
#
def self.use_automatic_resource_name
- automatic_name = convert_to_snake_case(self.name.split("::")[-1])
+ automatic_name = convert_to_snake_case(name.split("::")[-1])
resource_name automatic_name
end
@@ -1060,7 +1071,7 @@ class Chef
#
def self.provider_base(arg = nil)
if arg
- Chef.log_deprecation("Resource.provider_base is deprecated and will be removed in Chef 13. Use provides on the provider, or provider on the resource, instead.")
+ Chef.deprecated(:custom_resource, "Resource.provider_base is deprecated and will be removed in Chef 13. Use provides on the provider, or provider on the resource, instead.")
end
@provider_base ||= arg || Chef::Provider
end
@@ -1488,7 +1499,7 @@ class Chef
if args.size == 1
args.first
else
- return *args
+ args
end
end
@@ -1550,6 +1561,13 @@ class Chef
#
# Returns the class with the given resource_name.
#
+ # NOTE: Chef::Resource.resource_matching_short_name(:package) returns
+ # Chef::Resource::Package, while on rhel the API call
+ # Chef::Resource.resource_for_node(:package, node) will return
+ # Chef::Resource::YumPackage -- which is probably what you really
+ # want. This API should most likely be removed or changed to call
+ # resource_for_node.
+ #
# ==== Parameters
# short_name<Symbol>:: short_name of the resource (ie :directory)
#
@@ -1562,14 +1580,12 @@ class Chef
# @api private
def lookup_provider_constant(name, action = :nothing)
- begin
- self.class.provider_base.const_get(convert_to_class_name(name.to_s))
- rescue NameError => e
- if e.to_s =~ /#{Regexp.escape(self.class.provider_base.to_s)}/
- raise ArgumentError, "No provider found to match '#{name}'"
- else
- raise e
- end
+ self.class.provider_base.const_get(convert_to_class_name(name.to_s))
+ rescue NameError => e
+ if e.to_s =~ /#{Regexp.escape(self.class.provider_base.to_s)}/
+ raise ArgumentError, "No provider found to match '#{name}'"
+ else
+ raise e
end
end
diff --git a/lib/chef/resource/apt_repository.rb b/lib/chef/resource/apt_repository.rb
index 8b87371824..b38bd1c8ec 100644
--- a/lib/chef/resource/apt_repository.rb
+++ b/lib/chef/resource/apt_repository.rb
@@ -38,7 +38,6 @@ class Chef
property :cookbook, [String, nil, false], default: nil, desired_state: false, nillable: true, coerce: proc { |x| x ? x : nil }
property :cache_rebuild, [TrueClass, FalseClass], default: true, desired_state: false
- property :sensitive, [TrueClass, FalseClass], default: false, desired_state: false
default_action :add
allowed_actions :add, :remove
diff --git a/lib/chef/resource/apt_update.rb b/lib/chef/resource/apt_update.rb
index df2033b063..1a25ec2ef5 100644
--- a/lib/chef/resource/apt_update.rb
+++ b/lib/chef/resource/apt_update.rb
@@ -22,7 +22,7 @@ class Chef
class Resource
class AptUpdate < Chef::Resource
resource_name :apt_update
- provides :apt_update, os: "linux"
+ provides :apt_update
property :frequency, Integer, default: 86_400
diff --git a/lib/chef/resource/chef_gem.rb b/lib/chef/resource/chef_gem.rb
index 4445bf0f89..5f51c9e208 100644
--- a/lib/chef/resource/chef_gem.rb
+++ b/lib/chef/resource/chef_gem.rb
@@ -34,14 +34,13 @@ class Chef
# Chef::Resource.run_action: Caveat: this skips Chef::Runner.run_action, where notifications are handled
# Action could be an array of symbols, but probably won't (think install + enable for a package)
if compile_time.nil?
- Chef.log_deprecation "#{self} chef_gem compile_time installation is deprecated"
- Chef.log_deprecation "#{self} Please set `compile_time false` on the resource to use the new behavior."
- Chef.log_deprecation "#{self} or set `compile_time true` on the resource if compile_time behavior is required."
+ message = "#{self} chef_gem compile_time installation is deprecated. Please set `compile_time false` on the resource to use the new behavior, or set `compile_time true` on the resource if compile_time behavior is required."
+ Chef.deprecated :chef_gem_compile_time, message
end
if compile_time || compile_time.nil?
Array(action).each do |action|
- self.run_action(action)
+ run_action(action)
end
Gem.clear_paths
end
diff --git a/lib/chef/resource/chocolatey_package.rb b/lib/chef/resource/chocolatey_package.rb
index 805d3a3121..5460661f6d 100644
--- a/lib/chef/resource/chocolatey_package.rb
+++ b/lib/chef/resource/chocolatey_package.rb
@@ -34,6 +34,7 @@ class Chef
property :package_name, [String, Array], coerce: proc { |x| [x].flatten }
property :version, [String, Array], coerce: proc { |x| [x].flatten }
+ property :returns, [Integer, Array], default: [ 0 ], desired_state: false
end
end
end
diff --git a/lib/chef/resource/dnf_package.rb b/lib/chef/resource/dnf_package.rb
new file mode 100644
index 0000000000..f10c282f19
--- /dev/null
+++ b/lib/chef/resource/dnf_package.rb
@@ -0,0 +1,67 @@
+#
+# Copyright:: Copyright 2016-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 "chef/resource/package"
+require "chef/mixin/which"
+require "chef/mixin/shell_out"
+
+class Chef
+ class Resource
+ class DnfPackage < Chef::Resource::Package
+ extend Chef::Mixin::Which
+ extend Chef::Mixin::ShellOut
+
+ resource_name :dnf_package
+
+ allowed_actions :install, :upgrade, :remove, :purge, :reconfig, :lock, :unlock, :flush_cache
+
+ provides :package, platform_family: %w{rhel fedora} do
+ which("dnf") && shell_out("rpm -q dnf").stdout =~ /^dnf-[1-9]/
+ end
+
+ provides :dnf_package
+
+ # Install a specific arch
+ property :arch, [String, Array], coerce: proc { |x| [x].flatten }
+
+ # Flush the in-memory available/installed cache, this does not flush the dnf caches on disk
+ property :flush_cache,
+ Hash,
+ default: { before: false, after: false },
+ coerce: proc { |v|
+ if v.is_a?(Hash)
+ v
+ elsif v.is_a?(Array)
+ v.each_with_object({}) { |arg, obj| obj[arg] = true }
+ elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
+ { before: v, after: v }
+ elsif v == :before
+ { before: true, after: false }
+ elsif v == :after
+ { after: true, before: false }
+ end
+ }
+
+ def allow_downgrade(arg = nil)
+ if !arg.nil?
+ Chef.deprecated(:dnf_package_allow_downgrade, "the allow_downgrade property on the dnf_package provider is not used, DNF supports downgrades by default.")
+ end
+ false
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/dsc_resource.rb b/lib/chef/resource/dsc_resource.rb
index 58594cce7b..d3b579e428 100644
--- a/lib/chef/resource/dsc_resource.rb
+++ b/lib/chef/resource/dsc_resource.rb
@@ -29,7 +29,7 @@ class Chef
# to dump the actual ivars
class ToTextHash < Hash
def to_text
- descriptions = self.map do |(property, obj)|
+ descriptions = map do |(property, obj)|
obj_text = if obj.respond_to?(:to_text)
obj.to_text
else
@@ -68,6 +68,14 @@ class Chef
end
end
+ def module_version(arg = nil)
+ set_or_return(
+ :module_version,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
def property(property_name, value = nil)
if not property_name.is_a?(Symbol)
raise TypeError, "A property name of type Symbol must be specified, '#{property_name}' of type #{property_name.class} was given"
diff --git a/lib/chef/resource/execute.rb b/lib/chef/resource/execute.rb
index 1a56607267..677c4608b3 100644
--- a/lib/chef/resource/execute.rb
+++ b/lib/chef/resource/execute.rb
@@ -135,12 +135,18 @@ class Chef
)
end
- def user(arg = nil)
- set_or_return(
- :user,
- arg,
- :kind_of => [ String, Integer ]
- )
+ property :user, [ String, Integer ]
+
+ property :domain, String
+
+ property :password, String, sensitive: true
+
+ def sensitive(args = nil)
+ if password
+ true
+ else
+ super
+ end
end
def self.set_guard_inherited_attributes(*inherited_attributes)
@@ -159,6 +165,64 @@ class Chef
ancestor_attributes.concat(@class_inherited_attributes ? @class_inherited_attributes : []).uniq
end
+ def after_created
+ validate_identity_platform(user, password, domain)
+ identity = qualify_user(user, password, domain)
+ domain(identity[:domain])
+ user(identity[:user])
+ end
+
+ def validate_identity_platform(specified_user, password = nil, specified_domain = nil)
+ if node[:platform_family] == "windows"
+ if specified_user && password.nil?
+ raise ArgumentError, "A value for `password` must be specified when a value for `user` is specified on the Windows platform"
+ end
+ else
+ if password || specified_domain
+ raise Exceptions::UnsupportedPlatform, "Values for `domain` and `password` are only supported on the Windows platform"
+ end
+ end
+ end
+
+ def qualify_user(specified_user, password = nil, specified_domain = nil)
+ domain = specified_domain
+ user = specified_user
+
+ if specified_user.nil? && ! specified_domain.nil?
+ raise ArgumentError, "The domain `#{specified_domain}` was specified, but no user name was given"
+ end
+
+ # if domain is provided in both username and domain
+ if specified_user && ((specified_user.include? '\\') || (specified_user.include? "@")) && specified_domain
+ raise ArgumentError, "The domain is provided twice. Username: `#{specified_user}`, Domain: `#{specified_domain}`. Please specify domain only once."
+ end
+
+ if ! specified_user.nil? && specified_domain.nil?
+ # Splitting username of format: Domain\Username
+ domain_and_user = user.split('\\')
+
+ if domain_and_user.length == 2
+ domain = domain_and_user[0]
+ user = domain_and_user[1]
+ elsif domain_and_user.length == 1
+ # Splitting username of format: Username@Domain
+ domain_and_user = user.split("@")
+ if domain_and_user.length == 2
+ domain = domain_and_user[1]
+ user = domain_and_user[0]
+ elsif domain_and_user.length != 1
+ raise ArgumentError, "The specified user name `#{user}` is not a syntactically valid user name"
+ end
+ end
+ end
+
+ if ( password || domain ) && user.nil?
+ raise ArgumentError, "A value for `password` or `domain` was specified without specification of a value for `user`"
+ end
+
+ { domain: domain, user: user }
+ end
+
set_guard_inherited_attributes(
:cwd,
:environment,
diff --git a/lib/chef/resource/file/verification.rb b/lib/chef/resource/file/verification.rb
index e11035d33f..3400684bc5 100644
--- a/lib/chef/resource/file/verification.rb
+++ b/lib/chef/resource/file/verification.rb
@@ -108,10 +108,12 @@ class Chef
def verify_command(path, opts)
# First implementation interpolated `file`; docs & RFC claim `path`
# is interpolated. Until `file` can be deprecated, interpolate both.
- Chef.log_deprecation(
- "%{file} is deprecated in verify command and will not be "\
- "supported in Chef 13. Please use %{path} instead."
- ) if @command.include?("%{file}")
+ if @command.include?("%{file}")
+ Chef.deprecated(:verify_file,
+ "%{file} is deprecated in verify command and will not be "\
+ "supported in Chef 13. Please use %{path} instead."
+ )
+ end
command = @command % { :file => path, :path => path }
interpreter = Chef::GuardInterpreter.for_resource(@parent_resource, command, @command_opts)
interpreter.evaluate
diff --git a/lib/chef/resource/file/verification/systemd_unit.rb b/lib/chef/resource/file/verification/systemd_unit.rb
new file mode 100644
index 0000000000..b492b32d39
--- /dev/null
+++ b/lib/chef/resource/file/verification/systemd_unit.rb
@@ -0,0 +1,67 @@
+#
+# Author:: Mal Graty (<mal.graty@googlemail.com>)
+# 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 "chef/mixin/which"
+
+class Chef
+ class Resource
+ class File
+ class Verification
+
+ #
+ # Systemd provides a binary for verifying the correctness of
+ # unit files. Unfortunately some units have constraints on the
+ # filename meaning that normal verification against temp files
+ # won't work.
+ #
+ # Working around that requires placing a copy of the temp file
+ # in a temp directory, under its real name and running the
+ # verification tool against that file.
+ #
+
+ class SystemdUnit < Chef::Resource::File::Verification
+ include Chef::Mixin::Which
+
+ provides :systemd_unit
+
+ def initialize(parent_resource, command, opts, &block)
+ super
+ @command = systemd_analyze_cmd
+ end
+
+ def verify(path, opts = {})
+ return true unless systemd_analyze_path
+ Dir.mktmpdir("chef-systemd-unit") do |dir|
+ temp = "#{dir}/#{::File.basename(@parent_resource.path)}"
+ ::FileUtils.cp(path, temp)
+ verify_command(temp, opts)
+ end
+ end
+
+ def systemd_analyze_cmd
+ @systemd_analyze_cmd ||= "#{systemd_analyze_path} verify %{path}"
+ end
+
+ def systemd_analyze_path
+ @systemd_analyze_path ||= which("systemd-analyze")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb
index a94dd0a928..ecaff95244 100644
--- a/lib/chef/resource/freebsd_package.rb
+++ b/lib/chef/resource/freebsd_package.rb
@@ -37,7 +37,7 @@ class Chef
end
def supports_pkgng?
- ships_with_pkgng? || !!shell_out!("make -V WITH_PKGNG", :env => nil).stdout.match(/yes/i)
+ ships_with_pkgng? || !!shell_out_compact!("make", "-V", "WITH_PKGNG", :env => nil).stdout.match(/yes/i)
end
private
diff --git a/lib/chef/resource/gem_package.rb b/lib/chef/resource/gem_package.rb
index e095115356..5511d3c580 100644
--- a/lib/chef/resource/gem_package.rb
+++ b/lib/chef/resource/gem_package.rb
@@ -34,7 +34,7 @@ class Chef
# gem will be installed via the gems API. When a String is given, the gem
# will be installed by shelling out to the gem command. Using a Hash of
# options with an explicit gem_binary will result in undefined behavior.
- property :options, [ String, Hash, nil ], desired_state: false
+ property :options, [ String, Hash, Array, nil ], desired_state: false
end
end
diff --git a/lib/chef/resource/launchd.rb b/lib/chef/resource/launchd.rb
index 8dca90ef0e..c78ffa3f0e 100644
--- a/lib/chef/resource/launchd.rb
+++ b/lib/chef/resource/launchd.rb
@@ -29,23 +29,64 @@ class Chef
default_action :create
allowed_actions :create, :create_if_missing, :delete, :enable, :disable
- def initialize(name, run_context = nil)
- super
- provider = Chef::Provider::Launchd
- resource_name = :launchd
- end
-
property :label, String, default: lazy { name }, identity: true
property :backup, [Integer, FalseClass]
property :cookbook, String
property :group, [String, Integer]
- property :hash, Hash
+ property :plist_hash, Hash
property :mode, [String, Integer]
property :owner, [String, Integer]
property :path, String
property :source, String
property :session_type, String
+ # StartCalendarInterval has some gotchas so we coerce it to help sanity
+ # check. According to `man 5 launchd.plist`:
+ # StartCalendarInterval <dictionary of integers or array of dictionaries of integers>
+ # ... Missing arguments are considered to be wildcard.
+ # What the man page doesn't state, but what was observed (OSX 10.11.5, launchctrl v3.4.0)
+ # Is that keys that are specified, but invalid, will also be treated as a wildcard
+ # this means that an entry like:
+ # { "Hour"=>0, "Weekday"=>"6-7"}
+ # will not just run on midnight of Sat and Sun, rather it will run _every_ midnight.
+ property :start_calendar_interval, [Hash, Array], coerce: proc { |type|
+ # Coerce into an array of hashes to make validation easier
+ array = if type.is_a?(Array)
+ type
+ else
+ [type]
+ end
+
+ # Check to make sure that our array only has hashes
+ unless array.all? { |obj| obj.is_a?(Hash) }
+ error_msg = "start_calendar_interval must be a single hash or an array of hashes!"
+ raise Chef::Exceptions::ValidationFailed, error_msg
+ end
+
+ # Make sure the hashes don't have any incorrect keys/values
+ array.each do |entry|
+ allowed_keys = %w{Minute Hour Day Weekday Month}
+ unless entry.keys.all? { |key| allowed_keys.include?(key) }
+ failed_keys = entry.keys.reject { |k| allowed_keys.include?(k) }.join(", ")
+ error_msg = "The following key(s): #{failed_keys} are invalid for start_calendar_interval, must be one of: #{allowed_keys.join(", ")}"
+ raise Chef::Exceptions::ValidationFailed, error_msg
+ end
+
+ unless entry.values.all? { |val| val.is_a?(Integer) }
+ failed_values = entry.values.reject { |val| val.is_a?(Integer) }.join(", ")
+ error_msg = "Invalid value(s) (#{failed_values}) for start_calendar_interval item. Values must be integers!"
+ raise Chef::Exceptions::ValidationFailed, error_msg
+ end
+ end
+
+ # Don't return array if we only have one entry
+ if array.size == 1
+ array.first
+ else
+ array
+ end
+ }
+
property :type, String, default: "daemon", coerce: proc { |type|
type = type ? type.downcase : "daemon"
types = %w{daemon agent}
@@ -73,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, String
+ property :limit_load_to_session_type, Array
property :low_priority_io, [ TrueClass, FalseClass ]
property :mach_services, Hash
property :nice, Integer
@@ -89,7 +130,6 @@ class Chef
property :standard_error_path, String
property :standard_in_path, String
property :standard_out_path, String
- property :start_calendar_interval, Hash
property :start_interval, Integer
property :start_on_mount, [ TrueClass, FalseClass ]
property :throttle_interval, Integer
@@ -99,6 +139,18 @@ 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/mount.rb b/lib/chef/resource/mount.rb
index 2d85b3897c..3e35325246 100644
--- a/lib/chef/resource/mount.rb
+++ b/lib/chef/resource/mount.rb
@@ -28,7 +28,7 @@ class Chef
state_attrs :mount_point, :device_type, :fstype, :username, :password, :domain
default_action :mount
- allowed_actions :mount, :umount, :remount, :enable, :disable
+ allowed_actions :mount, :umount, :unmount, :remount, :enable, :disable
def initialize(name, run_context = nil)
super
diff --git a/lib/chef/resource/msu_package.rb b/lib/chef/resource/msu_package.rb
new file mode 100644
index 0000000000..753992c185
--- /dev/null
+++ b/lib/chef/resource/msu_package.rb
@@ -0,0 +1,47 @@
+#
+# 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/package"
+require "chef/mixin/uris"
+
+class Chef
+ class Resource
+ class MsuPackage < Chef::Resource::Package
+ include Chef::Mixin::Uris
+
+ provides :msu_package, os: "windows"
+
+ allowed_actions :install, :remove
+
+ def initialize(name, run_context = nil)
+ super
+ @resource_name = :msu_package
+ @source = name
+ @action = :install
+ end
+
+ property :source, String,
+ coerce: (proc do |s|
+ unless s.nil?
+ uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false)
+ end
+ end)
+ property :checksum, String, desired_state: false
+ end
+ end
+end
diff --git a/lib/chef/resource/ohai.rb b/lib/chef/resource/ohai.rb
index 09cd22efc5..6fffecf16e 100644
--- a/lib/chef/resource/ohai.rb
+++ b/lib/chef/resource/ohai.rb
@@ -20,34 +20,14 @@
class Chef
class Resource
class Ohai < Chef::Resource
+ resource_name :ohai
+ provides :ohai
- identity_attr :name
-
- state_attrs :plugin
+ property :ohai_name, name_property: true
+ property :plugin, [String]
default_action :reload
-
- def initialize(name, run_context = nil)
- super
- @name = name
- @plugin = nil
- end
-
- def plugin(arg = nil)
- set_or_return(
- :plugin,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def name(arg = nil)
- set_or_return(
- :name,
- arg,
- :kind_of => [ String ]
- )
- end
+ allowed_actions :reload
end
end
end
diff --git a/lib/chef/resource/package.rb b/lib/chef/resource/package.rb
index 0738107339..a1f174a6f3 100644
--- a/lib/chef/resource/package.rb
+++ b/lib/chef/resource/package.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2008-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");
@@ -36,7 +36,7 @@ class Chef
property :package_name, [ String, Array ], identity: true
property :version, [ String, Array ]
- property :options, String
+ property :options, [ String, Array ]
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/powershell_package.rb b/lib/chef/resource/powershell_package.rb
new file mode 100644
index 0000000000..4d658d3cc5
--- /dev/null
+++ b/lib/chef/resource/powershell_package.rb
@@ -0,0 +1,41 @@
+# Author:: Dheeraj Dubey(dheeraj.dubey@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/package"
+require "chef/mixin/uris"
+
+class Chef
+ class Resource
+ class PowershellPackage < Chef::Resource::Package
+ include Chef::Mixin::Uris
+
+ provides :powershell_package, os: "windows"
+
+ allowed_actions :install, :remove
+
+ def initialize(name, run_context = nil)
+ super
+ @resource_name = :powershell_package
+ end
+
+ property :package_name, [String, Array], coerce: proc { |x| [x].flatten }
+
+ property :version, [String, Array], coerce: proc { |x| [x].flatten }
+
+ end
+ end
+end
diff --git a/lib/chef/resource/reboot.rb b/lib/chef/resource/reboot.rb
index 24d6e74157..519defa602 100644
--- a/lib/chef/resource/reboot.rb
+++ b/lib/chef/resource/reboot.rb
@@ -41,7 +41,7 @@ class Chef
end
def delay_mins(arg = nil)
- set_or_return(:delay_mins, arg, :kind_of => Fixnum)
+ set_or_return(:delay_mins, arg, :kind_of => Integer)
end
end
end
diff --git a/lib/chef/resource/registry_key.rb b/lib/chef/resource/registry_key.rb
index da09b9668b..549897bb1d 100644
--- a/lib/chef/resource/registry_key.rb
+++ b/lib/chef/resource/registry_key.rb
@@ -96,7 +96,7 @@ class Chef
end
end
@unscrubbed_values = @values
- elsif self.instance_variable_defined?(:@values)
+ elsif instance_variable_defined?(:@values)
scrub_values(@values)
end
end
diff --git a/lib/chef/resource/user.rb b/lib/chef/resource/user.rb
index 06dfe95bd4..fc7720bc25 100644
--- a/lib/chef/resource/user.rb
+++ b/lib/chef/resource/user.rb
@@ -158,10 +158,10 @@ class Chef
def supports(args = {})
if args.key?(:manage_home)
- Chef.log_deprecation "supports { manage_home: #{args[:manage_home]} } on the user resource is deprecated and will be removed in Chef 13, set manage_home: #{args[:manage_home]} instead"
+ Chef.deprecated(:supports_property, "supports { manage_home: #{args[:manage_home]} } on the user resource is deprecated and will be removed in Chef 13, set manage_home #{args[:manage_home]} instead")
end
if args.key?(:non_unique)
- Chef.log_deprecation "supports { non_unique: #{args[:non_unique]} } on the user resource is deprecated and will be removed in Chef 13, set non_unique: #{args[:non_unique]} instead"
+ Chef.deprecated(:supports_property, "supports { non_unique: #{args[:non_unique]} } on the user resource is deprecated and will be removed in Chef 13, set non_unique #{args[:non_unique]} instead")
end
super
end
diff --git a/lib/chef/resource/yum_package.rb b/lib/chef/resource/yum_package.rb
index 9d69897f5f..2fc5db5cc3 100644
--- a/lib/chef/resource/yum_package.rb
+++ b/lib/chef/resource/yum_package.rb
@@ -1,6 +1,6 @@
#
# Author:: AJ Christensen (<aj@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");
@@ -17,7 +17,6 @@
#
require "chef/resource/package"
-require "chef/provider/package/yum"
class Chef
class Resource
@@ -25,24 +24,38 @@ class Chef
resource_name :yum_package
provides :package, os: "linux", platform_family: %w{rhel fedora}
- # Install a specific arch
- property :arch, [ String, Array ]
- # the {} on the proc here is because rspec chokes if it's do...end
+ # 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.
+ #
+ # <lecture>
+ # THIS is why updating the new_resource in a provider is so terrible, and is equivalent to methods scribbling over
+ # its own arguments as unintended side-effects (and why functional languages that don't allow modifcations
+ # of variables eliminate entire classes of bugs).
+ # </lecture>
+ property :package_name, [ String, Array ], identity: true, coerce: proc { |x| x.is_a?(Array) ? x.to_a : x }
+ property :version, [ String, Array ], coerce: proc { |x| x.is_a?(Array) ? x.to_a : x }
+ property :arch, [ String, Array ], coerce: proc { |x| x.is_a?(Array) ? x.to_a : x }
+
property :flush_cache,
- Hash,
- default: { before: false, after: false },
- coerce: proc { |v|
- if v.is_a?(Array)
- v.each_with_object({}) { |arg, obj| obj[arg] = true }
- elsif v.any?
- v
- else
- { before: v, after: v }
- end
- }
+ Hash,
+ default: { before: false, after: false },
+ coerce: proc { |v|
+ if v.is_a?(Hash)
+ v
+ elsif v.is_a?(Array)
+ v.each_with_object({}) { |arg, obj| obj[arg] = true }
+ elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
+ { before: v, after: v }
+ elsif v == :before
+ { before: true, after: false }
+ elsif v == :after
+ { after: true, before: false }
+ end
+ }
+
property :allow_downgrade, [ true, false ], default: false
- property :yum_binary, String
+ property :yum_binary, String
end
end
end
diff --git a/lib/chef/resource/yum_repository.rb b/lib/chef/resource/yum_repository.rb
index 1c215b51ff..f59ad56d16 100644
--- a/lib/chef/resource/yum_repository.rb
+++ b/lib/chef/resource/yum_repository.rb
@@ -25,7 +25,7 @@ class Chef
provides :yum_repository
# http://linux.die.net/man/5/yum.conf
- property :baseurl, String, regex: /.*/
+ property :baseurl, [String, Array], regex: /.*/
property :cost, String, regex: /^\d+$/
property :clean_headers, [TrueClass, FalseClass], default: false # deprecated
property :clean_metadata, [TrueClass, FalseClass], default: true
@@ -58,7 +58,6 @@ class Chef
property :repo_gpgcheck, [TrueClass, FalseClass]
property :report_instanceid, [TrueClass, FalseClass]
property :repositoryid, String, regex: /.*/, name_property: true
- property :sensitive, [TrueClass, FalseClass], default: false
property :skip_if_unavailable, [TrueClass, FalseClass]
property :source, String, regex: /.*/
property :sslcacert, String, regex: /.*/
diff --git a/lib/chef/resource_builder.rb b/lib/chef/resource_builder.rb
index 57c57dd8c3..1aee852f5d 100644
--- a/lib/chef/resource_builder.rb
+++ b/lib/chef/resource_builder.rb
@@ -56,7 +56,7 @@ class Chef
# This behavior is very counter-intuitive and should be removed.
# See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694
# Moved to this location to resolve CHEF-5052, https://tickets.opscode.com/browse/CHEF-5052
- if prior_resource
+ if prior_resource && Chef::Config[:resource_cloning]
resource.load_from(prior_resource)
end
@@ -80,7 +80,7 @@ class Chef
end
# emit a cloned resource warning if it is warranted
- if prior_resource
+ if prior_resource && Chef::Config[:resource_cloning]
if is_trivial_resource?(prior_resource) && identicalish_resources?(prior_resource, resource)
emit_harmless_cloning_debug
else
@@ -128,10 +128,10 @@ class Chef
end
def emit_cloned_resource_warning
- message = "Cloning resource attributes for #{resource} from prior resource (CHEF-3694)"
+ message = "Cloning resource attributes for #{resource} from prior resource"
message << "\nPrevious #{prior_resource}: #{prior_resource.source_line}" if prior_resource.source_line
message << "\nCurrent #{resource}: #{resource.source_line}" if resource.source_line
- Chef.log_deprecation(message)
+ Chef.deprecated(:resource_cloning, message)
end
def emit_harmless_cloning_debug
diff --git a/lib/chef/resource_collection/resource_collection_serialization.rb b/lib/chef/resource_collection/resource_collection_serialization.rb
index 0e76296a4a..647d28dfd0 100644
--- a/lib/chef/resource_collection/resource_collection_serialization.rb
+++ b/lib/chef/resource_collection/resource_collection_serialization.rb
@@ -21,8 +21,8 @@ class Chef
# Serialize this object as a hash
def to_hash
instance_vars = Hash.new
- self.instance_variables.each do |iv|
- instance_vars[iv] = self.instance_variable_get(iv)
+ instance_variables.each do |iv|
+ instance_vars[iv] = instance_variable_get(iv)
end
{
"json_class" => self.class.name,
@@ -40,7 +40,7 @@ class Chef
module ClassMethods
def json_create(o)
- collection = self.new()
+ collection = new()
o["instance_vars"].each do |k, v|
collection.instance_variable_set(k.to_sym, v)
end
diff --git a/lib/chef/resource_collection/resource_set.rb b/lib/chef/resource_collection/resource_set.rb
index 99be025cd5..1a73818790 100644
--- a/lib/chef/resource_collection/resource_set.rb
+++ b/lib/chef/resource_collection/resource_set.rb
@@ -146,7 +146,7 @@ class Chef
results << lookup(create_key(resource_type, instance_name))
end
end
- return results
+ results
end
def find_resource_by_string(arg)
@@ -166,7 +166,7 @@ class Chef
else
raise ArgumentError, "Bad string format #{arg}, you must have a string like resource_type[name]!"
end
- return results
+ results
end
end
end
diff --git a/lib/chef/resource_reporter.rb b/lib/chef/resource_reporter.rb
index 8422870e2a..afc8500a2a 100644
--- a/lib/chef/resource_reporter.rb
+++ b/lib/chef/resource_reporter.rb
@@ -87,7 +87,7 @@ class Chef
end
def success?
- !self.exception
+ !exception
end
end # End class ResouceReport
@@ -198,6 +198,17 @@ class Chef
def resource_completed(new_resource)
if @pending_update && !nested_resource?(new_resource)
@pending_update.finish
+
+ # Verify if the resource has sensitive data
+ # and create a new blank resource with only
+ # the name so we can report it back without
+ # sensitive data
+ if @pending_update.new_resource.sensitive
+ klass = @pending_update.new_resource.class
+ resource_name = @pending_update.new_resource.name
+ @pending_update.new_resource = klass.new(resource_name)
+ end
+
@updated_resources << @pending_update
@pending_update = nil
end
diff --git a/lib/chef/resource_resolver.rb b/lib/chef/resource_resolver.rb
index 769272d637..fca6c6db81 100644
--- a/lib/chef/resource_resolver.rb
+++ b/lib/chef/resource_resolver.rb
@@ -55,7 +55,7 @@ class Chef
attr_reader :resource_name
# @api private
def resource
- Chef.log_deprecation("Chef::ResourceResolver.resource deprecated. Use resource_name instead.")
+ Chef.deprecated(:custom_resource, "Chef::ResourceResolver.resource deprecated. Use resource_name instead.")
resource_name
end
# @api private
@@ -173,8 +173,7 @@ class Chef
if handlers.empty?
handlers = resources.select { |handler| overrode_provides?(handler) && handler.provides?(node, resource_name) }
handlers.each do |handler|
- Chef.log_deprecation("#{handler}.provides? returned true when asked if it provides DSL #{resource_name}, but provides #{resource_name.inspect} was never called!")
- Chef.log_deprecation("In Chef 13, this will break: you must call provides to mark the names you provide, even if you also override provides? yourself.")
+ Chef.deprecated(:custom_resource, "#{handler}.provides? returned true when asked if it provides DSL #{resource_name}, but provides #{resource_name.inspect} was never called! In Chef 13, this will break: you must call provides to mark the names you provide, even if you also override provides? yourself.")
end
end
handlers
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index 9ff772353b..ab89ce66e0 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -31,6 +31,7 @@ require "chef/resource/deploy"
require "chef/resource/deploy_revision"
require "chef/resource/directory"
require "chef/resource/dpkg_package"
+require "chef/resource/dnf_package"
require "chef/resource/dsc_script"
require "chef/resource/dsc_resource"
require "chef/resource/easy_install_package"
@@ -96,3 +97,5 @@ require "chef/resource/lwrp_base"
require "chef/resource/bff_package"
require "chef/resource/zypper_package"
require "chef/resource/cab_package"
+require "chef/resource/powershell_package"
+require "chef/resource/msu_package"
diff --git a/lib/chef/rest.rb b/lib/chef/rest.rb
index b3793418ce..0705ca9f5a 100644
--- a/lib/chef/rest.rb
+++ b/lib/chef/rest.rb
@@ -59,7 +59,7 @@ class Chef
# http://localhost:4000, a call to +get_rest+ with 'nodes' will make an
# HTTP GET request to http://localhost:4000/nodes
def initialize(url, client_name = Chef::Config[:node_name], signing_key_filename = Chef::Config[:client_key], options = {})
- Chef.log_deprecation("Chef::REST is deprecated. Please use Chef::ServerAPI, or investigate Ridley or ChefAPI.")
+ Chef.deprecated(:chef_rest, "Chef::REST is deprecated. Please use Chef::ServerAPI, or investigate Ridley or ChefAPI.")
signing_key_filename = nil if chef_zero_uri?(url)
diff --git a/lib/chef/role.rb b/lib/chef/role.rb
index 331fa614f1..218894ef03 100644
--- a/lib/chef/role.rb
+++ b/lib/chef/role.rb
@@ -170,7 +170,7 @@ class Chef
# Create a Chef::Role from JSON
def self.json_create(o)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::Role#from_hash")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::Role#from_hash")
from_hash(o)
end
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index 626977b09f..6d84b7773d 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -253,7 +253,7 @@ class Chef
# @return [Array[Notification]]
#
def before_notifications(resource)
- return before_notification_collection[resource.declared_key]
+ before_notification_collection[resource.declared_key]
end
#
@@ -262,7 +262,7 @@ class Chef
# @return [Array[Notification]]
#
def immediate_notifications(resource)
- return immediate_notification_collection[resource.declared_key]
+ immediate_notification_collection[resource.declared_key]
end
#
@@ -272,7 +272,7 @@ class Chef
# @return [Array[Notification]]
#
def delayed_notifications(resource)
- return delayed_notification_collection[resource.declared_key]
+ delayed_notification_collection[resource.declared_key]
end
#
@@ -581,17 +581,17 @@ ERROR_MESSAGE
# These need to be settable so deploy can run a resource_collection
# independent of any cookbooks via +recipe_eval+
def audits=(value)
- Chef.log_deprecation("Setting run_context.audits will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
+ Chef.deprecated(:internal_api, "Setting run_context.audits will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
@audits = value
end
def immediate_notification_collection=(value)
- Chef.log_deprecation("Setting run_context.immediate_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
+ Chef.deprecated(:internal_api, "Setting run_context.immediate_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
@immediate_notification_collection = value
end
def delayed_notification_collection=(value)
- Chef.log_deprecation("Setting run_context.delayed_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
+ Chef.deprecated(:internal_api, "Setting run_context.delayed_notification_collection will be removed in a future Chef. Use run_context.create_child to create a new RunContext instead.")
@delayed_notification_collection = value
end
end
diff --git a/lib/chef/run_list/run_list_item.rb b/lib/chef/run_list/run_list_item.rb
index 0abfb106ff..1c75907dd8 100644
--- a/lib/chef/run_list/run_list_item.rb
+++ b/lib/chef/run_list/run_list_item.rb
@@ -81,7 +81,7 @@ class Chef
def ==(other)
if other.kind_of?(String)
- self.to_s == other.to_s
+ to_s == other.to_s
else
other.respond_to?(:type) && other.respond_to?(:name) && other.respond_to?(:version) && other.type == @type && other.name == @name && other.version == @version
end
diff --git a/lib/chef/run_list/versioned_recipe_list.rb b/lib/chef/run_list/versioned_recipe_list.rb
index 7845568aaa..ccd7351eeb 100644
--- a/lib/chef/run_list/versioned_recipe_list.rb
+++ b/lib/chef/run_list/versioned_recipe_list.rb
@@ -36,17 +36,17 @@ class Chef
end
end
@versions[name] = version if version
- self << name unless self.include?(name)
+ self << name unless include?(name)
end
def with_versions
- self.map { |recipe_name| { :name => recipe_name, :version => @versions[recipe_name] } }
+ map { |recipe_name| { :name => recipe_name, :version => @versions[recipe_name] } }
end
# Return an Array of Hashes, each of the form:
# {:name => RECIPE_NAME, :version_constraint => Chef::VersionConstraint }
def with_version_constraints
- self.map do |recipe_name|
+ map do |recipe_name|
constraint = Chef::VersionConstraint.new(@versions[recipe_name])
{ :name => recipe_name, :version_constraint => constraint }
end
@@ -55,7 +55,7 @@ class Chef
# Return an Array of Strings, each of the form:
# "NAME@VERSION"
def with_version_constraints_strings
- self.map do |recipe_name|
+ map do |recipe_name|
if @versions[recipe_name]
"#{recipe_name}@#{@versions[recipe_name]}"
else
@@ -69,7 +69,7 @@ class Chef
#
# @return [Array] Array of strings with fully-qualified recipe names
def with_fully_qualified_names_and_version_constraints
- self.map do |recipe_name|
+ map do |recipe_name|
qualified_recipe = if recipe_name.include?("::")
recipe_name
else
@@ -89,7 +89,7 @@ class Chef
#
# @return [Array] Array of strings with fully-qualified and unexpanded recipe names
def with_duplicate_names
- self.map do |recipe_name|
+ map do |recipe_name|
if recipe_name.include?("::")
recipe_name
else
diff --git a/lib/chef/scan_access_control.rb b/lib/chef/scan_access_control.rb
index f55a106e6d..0e6df30303 100644
--- a/lib/chef/scan_access_control.rb
+++ b/lib/chef/scan_access_control.rb
@@ -70,7 +70,7 @@ class Chef
when Integer
stat.uid
else
- Chef::Log.error("The `owner` parameter of the #@new_resource resource is set to an invalid value (#{new_resource.owner.inspect})")
+ Chef::Log.error("The `owner` parameter of the #{@new_resource} resource is set to an invalid value (#{new_resource.owner.inspect})")
raise ArgumentError, "cannot resolve #{new_resource.owner.inspect} to uid, owner must be a string or integer"
end
end
@@ -97,7 +97,7 @@ class Chef
when Integer
stat.gid
else
- Chef::Log.error("The `group` parameter of the #@new_resource resource is set to an invalid value (#{new_resource.owner.inspect})")
+ Chef::Log.error("The `group` parameter of the #{@new_resource} resource is set to an invalid value (#{new_resource.owner.inspect})")
raise ArgumentError, "cannot resolve #{new_resource.group.inspect} to gid, group must be a string or integer"
end
end
@@ -121,8 +121,8 @@ class Chef
when String, Integer, nil
"0#{(stat.mode & 07777).to_s(8)}"
else
- Chef::Log.error("The `mode` parameter of the #@new_resource resource is set to an invalid value (#{new_resource.mode.inspect})")
- raise ArgumentError, "Invalid value #{new_resource.mode.inspect} for `mode` on resource #@new_resource"
+ Chef::Log.error("The `mode` parameter of the #{@new_resource} resource is set to an invalid value (#{new_resource.mode.inspect})")
+ raise ArgumentError, "Invalid value #{new_resource.mode.inspect} for `mode` on resource #{@new_resource}"
end
end
diff --git a/lib/chef/server_api.rb b/lib/chef/server_api.rb
index d233d25232..2bdc5d9fe8 100644
--- a/lib/chef/server_api.rb
+++ b/lib/chef/server_api.rb
@@ -24,6 +24,7 @@ require "chef/http/json_input"
require "chef/http/json_output"
require "chef/http/remote_request_id"
require "chef/http/validate_content_length"
+require "chef/http/api_versions"
class Chef
class ServerAPI < Chef::HTTP
@@ -42,6 +43,7 @@ class Chef
use Chef::HTTP::Decompressor
use Chef::HTTP::Authenticator
use Chef::HTTP::RemoteRequestID
+ use Chef::HTTP::APIVersions
# ValidateContentLength should come after Decompressor
# because the order of middlewares is reversed when handling
diff --git a/lib/chef/server_api_versions.rb b/lib/chef/server_api_versions.rb
new file mode 100644
index 0000000000..68dfd5ac90
--- /dev/null
+++ b/lib/chef/server_api_versions.rb
@@ -0,0 +1,40 @@
+#--
+# 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 "singleton"
+
+class Chef
+ class ServerAPIVersions
+ include Singleton
+
+ def set_versions(versions)
+ @versions ||= versions
+ end
+
+ def min_server_version
+ !@versions.nil? ? @versions["min_version"] : nil
+ end
+
+ def max_server_version
+ !@versions.nil? ? @versions["max_version"] : nil
+ end
+
+ def reset!
+ @versions = nil
+ end
+ end
+end
diff --git a/lib/chef/shell.rb b/lib/chef/shell.rb
index 26683cc25d..e8c3704553 100644
--- a/lib/chef/shell.rb
+++ b/lib/chef/shell.rb
@@ -281,7 +281,7 @@ FOOTER
end
def self.setup!
- self.new.parse_opts
+ new.parse_opts
end
def parse_opts
diff --git a/lib/chef/shell/ext.rb b/lib/chef/shell/ext.rb
index 0c10309521..fb0733e96e 100644
--- a/lib/chef/shell/ext.rb
+++ b/lib/chef/shell/ext.rb
@@ -73,7 +73,7 @@ module Shell
banner << "| " + "Command".ljust(25) + "| " + "Description"
banner << "".ljust(80, "=")
- self.all_help_descriptions.each do |help_text|
+ all_help_descriptions.each do |help_text|
banner << "| " + help_text.cmd.ljust(25) + "| " + help_text.desc
end
banner << "".ljust(80, "=")
@@ -84,7 +84,7 @@ module Shell
end
def explain_command(method_name)
- help = self.all_help_descriptions.find { |h| h.cmd.to_s == method_name.to_s }
+ help = all_help_descriptions.find { |h| h.cmd.to_s == method_name.to_s }
if help
puts ""
puts "Command: #{method_name}"
@@ -159,7 +159,7 @@ module Shell
module Symbol
def on_off_to_bool
- self.to_s.on_off_to_bool
+ to_s.on_off_to_bool
end
end
@@ -211,8 +211,8 @@ module Shell
def version
puts "This is the chef-shell.\n" +
" Chef Version: #{::Chef::VERSION}\n" +
- " http://www.chef.io/\n" +
- " http://docs.chef.io/"
+ " https://www.chef.io/\n" +
+ " https://docs.chef.io/"
:ucanhaz_automation
end
alias :shell :version
diff --git a/lib/chef/shell/shell_session.rb b/lib/chef/shell/shell_session.rb
index a458286157..3034e1cf5d 100644
--- a/lib/chef/shell/shell_session.rb
+++ b/lib/chef/shell/shell_session.rb
@@ -127,7 +127,7 @@ module Shell
def shorten_node_inspect
def @node.inspect # rubocop:disable Lint/NestedMethodDefinition
- "<Chef::Node:0x#{self.object_id.to_s(16)} @name=\"#{self.name}\">"
+ "<Chef::Node:0x#{object_id.to_s(16)} @name=\"#{name}\">"
end
end
diff --git a/lib/chef/user.rb b/lib/chef/user.rb
index a6fc21646d..fffaa106f8 100644
--- a/lib/chef/user.rb
+++ b/lib/chef/user.rb
@@ -26,13 +26,13 @@ require "chef/server_api"
# TODO
# DEPRECATION NOTE
# This class will be replaced by Chef::UserV1 in Chef 13. It is the code to support the User object
-# corrosponding to the Open Source Chef Server 11 and only still exists to support
+# corresponding to the Open Source Chef Server 11 and only still exists to support
# users still on OSC 11.
#
# Chef::UserV1 now supports Chef Server 12 and will be moved to this namespace in Chef 13.
#
# New development should occur in Chef::UserV1.
-# This file and corrosponding osc_user knife files
+# This file and corresponding osc_user knife files
# should be removed once client support for Open Source Chef Server 11 expires.
class Chef
class User
@@ -97,10 +97,10 @@ class Chef
end
def create
- payload = { :name => self.name, :admin => self.admin, :password => self.password }
+ payload = { :name => name, :admin => admin, :password => password }
payload[:public_key] = public_key if public_key
new_user = chef_rest_v0.post("users", payload)
- Chef::User.from_hash(self.to_hash.merge(new_user))
+ Chef::User.from_hash(to_hash.merge(new_user))
end
def update(new_key = false)
@@ -108,18 +108,16 @@ class Chef
payload[:private_key] = new_key if new_key
payload[:password] = password if password
updated_user = chef_rest_v0.put("users/#{name}", payload)
- Chef::User.from_hash(self.to_hash.merge(updated_user))
+ Chef::User.from_hash(to_hash.merge(updated_user))
end
def save(new_key = false)
- begin
- create
- rescue Net::HTTPServerException => e
- if e.response.code == "409"
- update(new_key)
- else
- raise e
- end
+ create
+ rescue Net::HTTPServerException => e
+ if e.response.code == "409"
+ update(new_key)
+ else
+ raise e
end
end
@@ -155,7 +153,7 @@ class Chef
end
def self.json_create(json)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::User#from_json or Chef::User#load.")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::User#from_json or Chef::User#load.")
Chef::User.from_json(json)
end
diff --git a/lib/chef/user_v1.rb b/lib/chef/user_v1.rb
index db44ced9d4..b408bbe667 100644
--- a/lib/chef/user_v1.rb
+++ b/lib/chef/user_v1.rb
@@ -180,7 +180,7 @@ class Chef
new_user = chef_root_rest_v0.post("users", payload)
end
- Chef::UserV1.from_hash(self.to_hash.merge(new_user))
+ Chef::UserV1.from_hash(to_hash.merge(new_user))
end
def update(new_key = false)
@@ -213,25 +213,23 @@ class Chef
end
updated_user = chef_root_rest_v0.put("users/#{username}", payload)
end
- Chef::UserV1.from_hash(self.to_hash.merge(updated_user))
+ Chef::UserV1.from_hash(to_hash.merge(updated_user))
end
def save(new_key = false)
- begin
- create
- rescue Net::HTTPServerException => e
- if e.response.code == "409"
- update(new_key)
- else
- raise e
- end
+ create
+ rescue Net::HTTPServerException => e
+ if e.response.code == "409"
+ update(new_key)
+ else
+ raise e
end
end
# Note: remove after API v0 no longer supported by client (and knife command).
def reregister
begin
- payload = self.to_hash.merge({ "private_key" => true })
+ payload = to_hash.merge({ "private_key" => true })
reregistered_self = chef_root_rest_v0.put("users/#{username}", payload)
private_key(reregistered_self["private_key"])
# only V0 supported for reregister
@@ -277,7 +275,7 @@ class Chef
end
def self.json_create(json)
- Chef.log_deprecation("Auto inflation of JSON data is deprecated. Please use Chef::UserV1#from_json or Chef::UserV1#load.")
+ Chef.deprecated(:json_auto_inflate, "Auto inflation of JSON data is deprecated. Please use Chef::UserV1#from_json or Chef::UserV1#load.")
Chef::UserV1.from_json(json)
end
diff --git a/lib/chef/util/diff.rb b/lib/chef/util/diff.rb
index bb1b4e2b95..61bc2bf666 100644
--- a/lib/chef/util/diff.rb
+++ b/lib/chef/util/diff.rb
@@ -117,7 +117,7 @@ class Chef
end
end
diff_str << old_hunk.diff(:unified) << "\n"
- return diff_str
+ diff_str
end
private
diff --git a/lib/chef/util/dsc/lcm_output_parser.rb b/lib/chef/util/dsc/lcm_output_parser.rb
index bdcedff7f8..9473ca8a86 100644
--- a/lib/chef/util/dsc/lcm_output_parser.rb
+++ b/lib/chef/util/dsc/lcm_output_parser.rb
@@ -119,7 +119,7 @@ class Chef
end
end
info.strip! # Because this was formatted for humans
- return [op_action, op_type, info]
+ [op_action, op_type, info]
end
private_class_method :parse_line
diff --git a/lib/chef/util/dsc/resource_store.rb b/lib/chef/util/dsc/resource_store.rb
index be8d0b301b..43b7d1bdf9 100644
--- a/lib/chef/util/dsc/resource_store.rb
+++ b/lib/chef/util/dsc/resource_store.rb
@@ -74,7 +74,7 @@ class Chef
found = rs.find_all do |r|
name_matches = r["Name"].casecmp(name) == 0
if name_matches
- module_name == nil || (r["Module"] && r["Module"]["Name"].casecmp(module_name) == 0)
+ module_name.nil? || (r["Module"] && r["Module"]["Name"].casecmp(module_name) == 0)
else
false
end
diff --git a/lib/chef/util/selinux.rb b/lib/chef/util/selinux.rb
index edca589034..0ff76c6407 100644
--- a/lib/chef/util/selinux.rb
+++ b/lib/chef/util/selinux.rb
@@ -83,7 +83,7 @@ class Chef
else
# We assume selinux is not enabled if selinux utils are not
# installed.
- return false
+ false
end
end
diff --git a/lib/chef/util/windows/net_group.rb b/lib/chef/util/windows/net_group.rb
index 0a351fbc6f..214881df56 100644
--- a/lib/chef/util/windows/net_group.rb
+++ b/lib/chef/util/windows/net_group.rb
@@ -35,50 +35,38 @@ class Chef::Util::Windows::NetGroup
end
def local_get_members
- begin
- Chef::ReservedNames::Win32::NetUser.net_local_group_get_members(nil, groupname)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::NetUser.net_local_group_get_members(nil, groupname)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def local_add
- begin
- Chef::ReservedNames::Win32::NetUser.net_local_group_add(nil, groupname)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::NetUser.net_local_group_add(nil, groupname)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def local_set_members(members)
- begin
- Chef::ReservedNames::Win32::NetUser.net_local_group_set_members(nil, groupname, members)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::NetUser.net_local_group_set_members(nil, groupname, members)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def local_add_members(members)
- begin
- Chef::ReservedNames::Win32::NetUser.net_local_group_add_members(nil, groupname, members)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::NetUser.net_local_group_add_members(nil, groupname, members)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def local_delete_members(members)
- begin
- Chef::ReservedNames::Win32::NetUser.net_local_group_del_members(nil, groupname, members)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::NetUser.net_local_group_del_members(nil, groupname, members)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def local_delete
- begin
- Chef::ReservedNames::Win32::NetUser.net_local_group_del(nil, groupname)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::NetUser.net_local_group_del(nil, groupname)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
end
diff --git a/lib/chef/util/windows/net_use.rb b/lib/chef/util/windows/net_use.rb
index b9c3ecc783..196ce42215 100644
--- a/lib/chef/util/windows/net_use.rb
+++ b/lib/chef/util/windows/net_use.rb
@@ -59,12 +59,10 @@ class Chef::Util::Windows::NetUse < Chef::Util::Windows
end
def get_info
- begin
- ui2 = Chef::ReservedNames::Win32::Net.net_use_get_info_l2(nil, use_name)
- from_use_info_struct(ui2)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ ui2 = Chef::ReservedNames::Win32::Net.net_use_get_info_l2(nil, use_name)
+ from_use_info_struct(ui2)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def device
@@ -72,11 +70,9 @@ class Chef::Util::Windows::NetUse < Chef::Util::Windows
end
def delete
- begin
- Chef::ReservedNames::Win32::Net.net_use_del(nil, use_name, :use_noforce)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::Net.net_use_del(nil, use_name, :use_noforce)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def use_name
diff --git a/lib/chef/util/windows/net_user.rb b/lib/chef/util/windows/net_user.rb
index 009252c4c1..f9f8f011af 100644
--- a/lib/chef/util/windows/net_user.rb
+++ b/lib/chef/util/windows/net_user.rb
@@ -78,11 +78,9 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows
end
def set_info(args)
- begin
- rc = NetUser.net_user_set_info_l3(nil, @username, transform_usri3(args))
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ rc = NetUser.net_user_set_info_l3(nil, @username, transform_usri3(args))
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
public
@@ -95,13 +93,11 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows
LOGON32_LOGON_NETWORK = Security::LOGON32_LOGON_NETWORK
#XXX for an extra painful alternative, see: http://support.microsoft.com/kb/180548
def validate_credentials(passwd)
- begin
- token = Security.logon_user(@username, nil, passwd,
- LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT)
- return true
- rescue Chef::Exceptions::Win32APIError
- return false
- end
+ token = Security.logon_user(@username, nil, passwd,
+ LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT)
+ return true
+ rescue Chef::Exceptions::Win32APIError
+ return false
end
def get_info
@@ -137,11 +133,9 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows
end
def delete
- begin
- NetUser.net_user_del(nil, @username)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ NetUser.net_user_del(nil, @username)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def disable_account
diff --git a/lib/chef/util/windows/volume.rb b/lib/chef/util/windows/volume.rb
index a18644cece..dc9c0ca1d0 100644
--- a/lib/chef/util/windows/volume.rb
+++ b/lib/chef/util/windows/volume.rb
@@ -30,27 +30,21 @@ class Chef::Util::Windows::Volume < Chef::Util::Windows
end
def device
- begin
- Chef::ReservedNames::Win32::File.get_volume_name_for_volume_mount_point(mount_point)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::File.get_volume_name_for_volume_mount_point(mount_point)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def delete
- begin
- Chef::ReservedNames::Win32::File.delete_volume_mount_point(mount_point)
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::File.delete_volume_mount_point(mount_point)
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def add(args)
- begin
- Chef::ReservedNames::Win32::File.set_volume_mount_point(mount_point, args[:remote])
- rescue Chef::Exceptions::Win32APIError => e
- raise ArgumentError, e
- end
+ Chef::ReservedNames::Win32::File.set_volume_mount_point(mount_point, args[:remote])
+ rescue Chef::Exceptions::Win32APIError => e
+ raise ArgumentError, e
end
def mount_point
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index b6fc2ca5a4..a7f9b8061a 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -21,7 +21,7 @@
class Chef
CHEF_ROOT = File.expand_path("../..", __FILE__)
- VERSION = "12.16.49"
+ VERSION = "12.19.30"
end
#
diff --git a/lib/chef/version_class.rb b/lib/chef/version_class.rb
index f26368902d..f98673b019 100644
--- a/lib/chef/version_class.rb
+++ b/lib/chef/version_class.rb
@@ -34,7 +34,7 @@ class Chef
def <=>(other)
[:major, :minor, :patch].each do |method|
- version = self.send(method)
+ version = send(method)
begin
ans = (version <=> other.send(method))
rescue NoMethodError # if the other thing isn't a version object, return nil
diff --git a/lib/chef/win32/api.rb b/lib/chef/win32/api.rb
index 64db9d2b63..503920a0ed 100644
--- a/lib/chef/win32/api.rb
+++ b/lib/chef/win32/api.rb
@@ -29,12 +29,10 @@ class Chef
# function into the calling module. If this fails a dummy method is
# defined which when called, raises a helpful exception to the end-user.
def safe_attach_function(win32_func, *args)
- begin
- attach_function(win32_func.to_sym, *args)
- rescue FFI::NotFoundError
- define_method(win32_func.to_sym) do |*margs|
- raise Chef::Exceptions::Win32APIFunctionNotImplemented, "This version of Windows does not implement the Win32 function [#{win32_func}]."
- end
+ attach_function(win32_func.to_sym, *args)
+ rescue FFI::NotFoundError
+ define_method(win32_func.to_sym) do |*margs|
+ raise Chef::Exceptions::Win32APIFunctionNotImplemented, "This version of Windows does not implement the Win32 function [#{win32_func}]."
end
end
diff --git a/lib/chef/win32/api/file.rb b/lib/chef/win32/api/file.rb
index 7489c94fd9..355cc81378 100644
--- a/lib/chef/win32/api/file.rb
+++ b/lib/chef/win32/api/file.rb
@@ -537,24 +537,22 @@ BOOL WINAPI VerQueryValue(
# ensures the handle is closed on exit of the block
# FIXME: yard with @yield
def file_search_handle(path)
- begin
# Workaround for CHEF-4419:
# Make sure paths starting with "/" has a drive letter
# assigned from the current working diretory.
# Note: With CHEF-4427 this issue will be fixed with a
# broader fix to map all the paths starting with "/" to
# SYSTEM_DRIVE on windows.
- path = ::File.expand_path(path) if path.start_with? "/"
- path = canonical_encode_path(path)
- find_data = WIN32_FIND_DATA.new
- handle = FindFirstFileW(path, find_data)
- if handle == INVALID_HANDLE_VALUE
- Chef::ReservedNames::Win32::Error.raise!
- end
- yield(handle, find_data)
- ensure
- FindClose(handle) if handle && handle != INVALID_HANDLE_VALUE
+ path = ::File.expand_path(path) if path.start_with? "/"
+ path = canonical_encode_path(path)
+ find_data = WIN32_FIND_DATA.new
+ handle = FindFirstFileW(path, find_data)
+ if handle == INVALID_HANDLE_VALUE
+ Chef::ReservedNames::Win32::Error.raise!
end
+ yield(handle, find_data)
+ ensure
+ FindClose(handle) if handle && handle != INVALID_HANDLE_VALUE
end
# retrieves a file handle and passes it
@@ -562,34 +560,30 @@ BOOL WINAPI VerQueryValue(
# ensures the handle is closed on exit of the block
# FIXME: yard with @yield
def file_handle(path)
- begin
- path = canonical_encode_path(path)
- handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
- nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, nil)
+ path = canonical_encode_path(path)
+ handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
+ nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, nil)
- if handle == INVALID_HANDLE_VALUE
- Chef::ReservedNames::Win32::Error.raise!
- end
- yield(handle)
- ensure
- CloseHandle(handle) if handle && handle != INVALID_HANDLE_VALUE
+ if handle == INVALID_HANDLE_VALUE
+ Chef::ReservedNames::Win32::Error.raise!
end
+ yield(handle)
+ ensure
+ CloseHandle(handle) if handle && handle != INVALID_HANDLE_VALUE
end
# FIXME: yard with @yield
def symlink_file_handle(path)
- begin
- path = encode_path(path)
- handle = CreateFileW(path, FILE_READ_EA, FILE_SHARE_READ,
- nil, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, nil)
+ path = encode_path(path)
+ handle = CreateFileW(path, FILE_READ_EA, FILE_SHARE_READ,
+ nil, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, nil)
- if handle == INVALID_HANDLE_VALUE
- Chef::ReservedNames::Win32::Error.raise!
- end
- yield(handle)
- ensure
- CloseHandle(handle) if handle && handle != INVALID_HANDLE_VALUE
+ if handle == INVALID_HANDLE_VALUE
+ Chef::ReservedNames::Win32::Error.raise!
end
+ yield(handle)
+ ensure
+ CloseHandle(handle) if handle && handle != INVALID_HANDLE_VALUE
end
def retrieve_file_info(file_name)
diff --git a/lib/chef/win32/api/installer.rb b/lib/chef/win32/api/installer.rb
index caf7b23f59..46930b65fc 100644
--- a/lib/chef/win32/api/installer.rb
+++ b/lib/chef/win32/api/installer.rb
@@ -107,7 +107,7 @@ UINT MsiCloseHandle(
end
msi_close_handle(pkg_ptr.read_pointer)
- return buffer.chomp(0.chr)
+ buffer.chomp(0.chr)
end
# Opens a Microsoft Installer (MSI) file from an absolute path and returns a pointer to a handle
@@ -124,7 +124,7 @@ UINT MsiCloseHandle(
else
raise Chef::Exceptions::Package, "msi_open_package: unexpected status #{status}: #{Chef::ReservedNames::Win32::Error.format_message(status)}"
end
- return pkg_ptr
+ pkg_ptr
end
# All installed product_codes should have a VersionString
diff --git a/lib/chef/win32/api/security.rb b/lib/chef/win32/api/security.rb
index 64df077686..a2cfe35dad 100644
--- a/lib/chef/win32/api/security.rb
+++ b/lib/chef/win32/api/security.rb
@@ -182,18 +182,18 @@ class Chef
MAXDWORD = 0xffffffff
# LOGON32 constants for LogonUser
- LOGON32_LOGON_INTERACTIVE = 2;
- LOGON32_LOGON_NETWORK = 3;
- LOGON32_LOGON_BATCH = 4;
- LOGON32_LOGON_SERVICE = 5;
- LOGON32_LOGON_UNLOCK = 7;
- LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
- LOGON32_LOGON_NEW_CREDENTIALS = 9;
-
- LOGON32_PROVIDER_DEFAULT = 0;
- LOGON32_PROVIDER_WINNT35 = 1;
- LOGON32_PROVIDER_WINNT40 = 2;
- LOGON32_PROVIDER_WINNT50 = 3;
+ LOGON32_LOGON_INTERACTIVE = 2
+ LOGON32_LOGON_NETWORK = 3
+ LOGON32_LOGON_BATCH = 4
+ LOGON32_LOGON_SERVICE = 5
+ LOGON32_LOGON_UNLOCK = 7
+ LOGON32_LOGON_NETWORK_CLEARTEXT = 8
+ LOGON32_LOGON_NEW_CREDENTIALS = 9
+
+ LOGON32_PROVIDER_DEFAULT = 0
+ LOGON32_PROVIDER_WINNT35 = 1
+ LOGON32_PROVIDER_WINNT40 = 2
+ LOGON32_PROVIDER_WINNT50 = 3
# LSA access policy
POLICY_VIEW_LOCAL_INFORMATION = 0x00000001
diff --git a/lib/chef/win32/file.rb b/lib/chef/win32/file.rb
index 1009f8c5a9..fa3d0f7a9d 100644
--- a/lib/chef/win32/file.rb
+++ b/lib/chef/win32/file.rb
@@ -155,13 +155,11 @@ class Chef
end
def self.verify_links_supported!
- begin
- CreateSymbolicLinkW(nil)
- rescue Chef::Exceptions::Win32APIFunctionNotImplemented => e
- raise e
- rescue Exception
+ CreateSymbolicLinkW(nil)
+ rescue Chef::Exceptions::Win32APIFunctionNotImplemented => e
+ raise e
+ rescue Exception
# things are ok.
- end
end
def self.file_access_check(path, desired_access)
diff --git a/lib/chef/win32/memory.rb b/lib/chef/win32/memory.rb
index 49dcdfbd41..2a9d5d8eb5 100644
--- a/lib/chef/win32/memory.rb
+++ b/lib/chef/win32/memory.rb
@@ -35,7 +35,7 @@ class Chef
Chef::ReservedNames::Win32::Error.raise!
end
# If a block is passed, handle freeing the memory at the end
- if block != nil
+ if !block.nil?
begin
yield result
ensure
diff --git a/lib/chef/win32/registry.rb b/lib/chef/win32/registry.rb
index 613994295c..6f1eb9ff12 100644
--- a/lib/chef/win32/registry.rb
+++ b/lib/chef/win32/registry.rb
@@ -170,7 +170,7 @@ class Chef
rescue Chef::Exceptions::Win32RegHiveMissing => e
return false
end
- return true
+ true
end
def has_subkeys?(key_path)
@@ -179,7 +179,7 @@ class Chef
hive.open(key, ::Win32::Registry::KEY_READ | registry_system_architecture) do |reg|
reg.each_key { |key| return true }
end
- return false
+ false
end
def get_subkeys(key_path)
@@ -189,7 +189,7 @@ class Chef
hive.open(key, ::Win32::Registry::KEY_READ | registry_system_architecture) do |reg|
reg.each_key { |current_key| subkeys << current_key }
end
- return subkeys
+ subkeys
end
# 32-bit chef clients running on 64-bit machines will default to reading the 64-bit registry
@@ -204,7 +204,7 @@ class Chef
hive.open(key, ::Win32::Registry::KEY_READ | registry_system_architecture) do |reg|
return true if reg.any? { |val| safely_downcase(val) == safely_downcase(value[:name]) }
end
- return false
+ false
end
def data_exists?(key_path, value)
@@ -219,7 +219,7 @@ class Chef
end
end
end
- return false
+ false
end
def value_exists!(key_path, value)
@@ -249,7 +249,7 @@ class Chef
end
end
end
- return false
+ false
end
def type_matches!(key_path, value)
@@ -279,7 +279,7 @@ class Chef
if val.is_a? String
return val.downcase
end
- return val
+ val
end
def node
@@ -316,7 +316,7 @@ class Chef
raise Chef::Exceptions::Win32RegHiveMissing, "Registry Hive #{hive_name} does not exist" unless hive
- return hive, key
+ [hive, key]
end
def _type_name_map
@@ -345,7 +345,7 @@ class Chef
5 => ::Win32::Registry::REG_DWORD_BIG_ENDIAN,
11 => ::Win32::Registry::REG_QWORD,
}[val_type]
- return value
+ value
end
def create_missing(key_path)
diff --git a/lib/chef/win32/security.rb b/lib/chef/win32/security.rb
index 7fc3215786..c7d3f55a40 100644
--- a/lib/chef/win32/security.rb
+++ b/lib/chef/win32/security.rb
@@ -239,7 +239,7 @@ class Chef
security_descriptor = FFI::MemoryPointer.new :pointer
hr = GetNamedSecurityInfoW(path.to_wstring, type, info, nil, nil, nil, nil, security_descriptor)
if hr != ERROR_SUCCESS
- Chef::ReservedNames::Win32::Error.raise!("get_named_security_info(#{path}, #{type}, #{info})")
+ Chef::ReservedNames::Win32::Error.raise!("get_named_security_info(#{path}, #{type}, #{info})", hr)
end
result_pointer = security_descriptor.read_pointer
@@ -538,7 +538,7 @@ class Chef
hr = SetNamedSecurityInfoW(path.to_wstring, type, security_information, owner, group, dacl, sacl)
if hr != ERROR_SUCCESS
- Chef::ReservedNames::Win32::Error.raise!
+ Chef::ReservedNames::Win32::Error.raise! nil, hr
end
end
@@ -551,7 +551,7 @@ class Chef
def set_security_descriptor_dacl(security_descriptor, acl, defaulted = false, present = nil)
security_descriptor = security_descriptor.pointer if security_descriptor.respond_to?(:pointer)
acl = acl.pointer if acl.respond_to?(:pointer)
- present = !security_descriptor.null? if present == nil
+ present = !security_descriptor.null? if present.nil?
unless SetSecurityDescriptorDacl(security_descriptor, present, acl, defaulted)
Chef::ReservedNames::Win32::Error.raise!
@@ -579,7 +579,7 @@ class Chef
def self.set_security_descriptor_sacl(security_descriptor, acl, defaulted = false, present = nil)
security_descriptor = security_descriptor.pointer if security_descriptor.respond_to?(:pointer)
acl = acl.pointer if acl.respond_to?(:pointer)
- present = !security_descriptor.null? if present == nil
+ present = !security_descriptor.null? if present.nil?
unless SetSecurityDescriptorSacl(security_descriptor, present, acl, defaulted)
Chef::ReservedNames::Win32::Error.raise!
diff --git a/lib/chef/win32/security/acl.rb b/lib/chef/win32/security/acl.rb
index 8a04987e44..0d9f7decd0 100644
--- a/lib/chef/win32/security/acl.rb
+++ b/lib/chef/win32/security/acl.rb
@@ -48,7 +48,7 @@ class Chef
0.upto(length - 1) do |i|
return false if self[i] != other[i]
end
- return true
+ true
end
def pointer
@@ -88,7 +88,7 @@ class Chef
end
def to_s
- "[#{self.collect { |ace| ace.to_s }.join(", ")}]"
+ "[#{collect { |ace| ace.to_s }.join(", ")}]"
end
def self.align_dword(size)
diff --git a/lib/chef/win32/security/sid.rb b/lib/chef/win32/security/sid.rb
index f6b88c60ce..983166ac70 100644
--- a/lib/chef/win32/security/sid.rb
+++ b/lib/chef/win32/security/sid.rb
@@ -50,7 +50,7 @@ class Chef
end
def ==(other)
- other != nil && Chef::ReservedNames::Win32::Security.equal_sid(self, other)
+ !other.nil? && Chef::ReservedNames::Win32::Security.equal_sid(self, other)
end
attr_reader :pointer
@@ -61,7 +61,7 @@ class Chef
def account_name
domain, name, use = account
- (domain != nil && domain.length > 0) ? "#{domain}\\#{name}" : name
+ (!domain.nil? && domain.length > 0) ? "#{domain}\\#{name}" : name
end
def size
diff --git a/lib/chef/win32/unicode.rb b/lib/chef/win32/unicode.rb
index d531463be0..dd5a197f71 100644
--- a/lib/chef/win32/unicode.rb
+++ b/lib/chef/win32/unicode.rb
@@ -40,13 +40,13 @@ module FFI
last_char = nil
while last_char != "\000\000"
length += 1
- last_char = self.get_bytes(0, length * 2)[-2..-1]
+ last_char = get_bytes(0, length * 2)[-2..-1]
end
num_wchars = length
end
- wide_to_utf8(self.get_bytes(0, num_wchars * 2))
+ wide_to_utf8(get_bytes(0, num_wchars * 2))
end
end
end
diff --git a/lib/chef/win32/version.rb b/lib/chef/win32/version.rb
index 303fe1531d..3e2d6bc1fe 100644
--- a/lib/chef/win32/version.rb
+++ b/lib/chef/win32/version.rb
@@ -100,7 +100,7 @@ class Chef
define_method(:marketing_name) do
marketing_names.each do |mn|
- break mn[0] if self.send(mn[1])
+ break mn[0] if send(mn[1])
end
end
diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock
index e64c4659b4..ceb322bf20 100644
--- a/omnibus/Gemfile.lock
+++ b/omnibus/Gemfile.lock
@@ -1,6 +1,6 @@
GIT
remote: git://github.com/chef/license_scout.git
- revision: 95a308e01848e7843c84fa9be6214fa06e30f436
+ revision: f90293a9753652fb64994a14de4108e503c06632
specs:
license_scout (0.1.2)
ffi-yajl (~> 2.2)
@@ -8,7 +8,7 @@ GIT
GIT
remote: git://github.com/chef/omnibus-software.git
- revision: cd69f8563fa8875c82a4e44652ffbfdac7ef201d
+ revision: 086710002ec0054b3d240d14ca04d11163f528aa
branch: shain/ruby_windows_monster
specs:
omnibus-software (4.0.0)
@@ -17,7 +17,7 @@ GIT
GIT
remote: git://github.com/chef/omnibus.git
- revision: 0612bf6333b2a7b125e599228ec6c46cbaa3ed3d
+ revision: dce5283a85a44484a66a8a84991beba92e46fd12
branch: rhass/COOL-502_with_gcc_investigate
specs:
omnibus (5.5.0)
@@ -35,15 +35,18 @@ GIT
GEM
remote: https://rubygems.org/
specs:
- addressable (2.4.0)
- artifactory (2.5.0)
+ addressable (2.5.0)
+ public_suffix (~> 2.0, >= 2.0.2)
+ artifactory (2.6.0)
awesome_print (1.7.0)
- aws-sdk (2.6.18)
- aws-sdk-resources (= 2.6.18)
- aws-sdk-core (2.6.18)
+ aws-sdk (2.7.5)
+ aws-sdk-resources (= 2.7.5)
+ aws-sdk-core (2.7.5)
+ aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-resources (2.6.18)
- aws-sdk-core (= 2.6.18)
+ aws-sdk-resources (2.7.5)
+ aws-sdk-core (= 2.7.5)
+ aws-sigv4 (1.0.0)
berkshelf (4.3.5)
addressable (~> 2.3, >= 2.3.4)
berkshelf-api-client (~> 2.0, >= 2.0.2)
@@ -76,14 +79,14 @@ GEM
buff-ruby_engine (0.1.0)
buff-shell_out (0.2.0)
buff-ruby_engine (~> 0.1.0)
- builder (3.2.2)
+ builder (3.2.3)
byebug (9.0.6)
celluloid (0.16.0)
timers (~> 4.0.0)
celluloid-io (0.16.2)
celluloid (>= 0.16.0)
nio4r (>= 1.1.0)
- chef-config (12.15.19)
+ chef-config (12.18.31)
addressable
fuzzyurl
mixlib-config (~> 2.0)
@@ -95,8 +98,8 @@ GEM
erubis (2.7.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
- ffi (1.9.14)
- ffi (1.9.14-x86-mingw32)
+ ffi (1.9.17)
+ ffi (1.9.17-x86-mingw32)
ffi-yajl (2.3.0)
libyajl2 (~> 1.2)
fuzzyurl (0.9.0)
@@ -104,14 +107,14 @@ GEM
ffi (>= 1.0.1)
gyoku (1.3.1)
builder (>= 2.1.2)
- hashie (3.4.6)
+ hashie (3.5.1)
hitimes (1.2.4)
hitimes (1.2.4-x86-mingw32)
httpclient (2.7.2)
iostruct (0.0.4)
ipaddress (0.8.3)
jmespath (1.3.1)
- json (2.0.2)
+ json (2.0.3)
kitchen-vagrant (0.19.0)
test-kitchen (~> 1.4)
libyajl2 (1.2.0)
@@ -120,14 +123,14 @@ GEM
little-plugger (~> 1.1)
multi_json (~> 1.10)
method_source (0.8.2)
- minitar (0.5.4)
- mixlib-archive (0.2.0)
+ minitar (0.6.1)
+ mixlib-archive (0.4.1)
mixlib-log
mixlib-authentication (1.4.1)
mixlib-log
mixlib-cli (1.7.0)
mixlib-config (2.2.4)
- mixlib-install (2.1.6)
+ mixlib-install (2.1.12)
artifactory
mixlib-shellout
mixlib-versioning
@@ -143,14 +146,14 @@ GEM
multipart-post (2.0.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
- net-ssh (3.2.0)
- net-ssh-gateway (1.2.0)
+ net-ssh (4.0.1)
+ net-ssh-gateway (1.3.0)
net-ssh (>= 2.6.5)
- nio4r (1.2.1)
+ nio4r (2.0.0)
nori (2.6.0)
- octokit (4.4.1)
- sawyer (~> 0.7.0, >= 0.5.3)
- ohai (8.21.0)
+ octokit (4.6.2)
+ sawyer (~> 0.8.0, >= 0.5.3)
+ ohai (8.23.0)
chef-config (>= 12.5.0.alpha.1, < 13)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
@@ -169,17 +172,18 @@ GEM
progressbar
zhexdump (>= 0.0.2)
plist (3.2.0)
- progressbar (0.21.0)
+ progressbar (1.8.2)
pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
- pry-byebug (3.4.0)
+ pry-byebug (3.4.2)
byebug (~> 9.0)
pry (~> 0.10)
pry-stack_explorer (0.4.9.2)
binding_of_caller (>= 0.7)
pry (>= 0.9.11)
+ public_suffix (2.0.5)
retryable (2.0.4)
ridley (4.6.1)
addressable
@@ -201,26 +205,26 @@ GEM
varia_model (~> 0.4.0)
ruby-progressbar (1.8.1)
rubyntlm (0.6.1)
- rubyzip (1.2.0)
+ rubyzip (1.2.1)
safe_yaml (1.0.4)
- sawyer (0.7.0)
- addressable (>= 2.3.5, < 2.5)
- faraday (~> 0.8, < 0.10)
+ sawyer (0.8.1)
+ addressable (>= 2.3.5, < 2.6)
+ faraday (~> 0.8, < 1.0)
semverse (1.2.1)
slop (3.6.0)
solve (2.0.3)
molinillo (~> 0.4.2)
semverse (~> 1.1)
systemu (2.6.5)
- test-kitchen (1.13.2)
+ test-kitchen (1.15.0)
mixlib-install (>= 1.2, < 3.0)
mixlib-shellout (>= 1.2, < 3.0)
net-scp (~> 1.1)
- net-ssh (>= 2.9, < 4.0)
- net-ssh-gateway (~> 1.2.0)
+ net-ssh (>= 2.9, < 5.0)
+ net-ssh-gateway (~> 1.2)
safe_yaml (~> 1.0)
thor (~> 0.18)
- thor (0.19.1)
+ thor (0.19.4)
timers (4.0.4)
hitimes
varia_model (0.4.1)
@@ -228,7 +232,7 @@ GEM
hashie (>= 2.0.2, < 4.0.0)
win32-process (0.8.3)
ffi (>= 1.0.0)
- winrm (2.1.0)
+ winrm (2.1.2)
builder (>= 2.1.2)
erubis (~> 2.7)
gssapi (~> 1.2)
@@ -237,7 +241,7 @@ GEM
logging (>= 1.6.1, < 3.0)
nori (~> 2.0)
rubyntlm (~> 0.6.0, >= 0.6.1)
- winrm-fs (1.0.0)
+ winrm-fs (1.0.1)
erubis (~> 2.7)
logging (>= 1.6.1, < 3.0)
rubyzip (~> 1.1)
diff --git a/omnibus/config/projects/angrychef.rb b/omnibus/config/projects/angrychef.rb
index 48902e6607..ff83f41327 100644
--- a/omnibus/config/projects/angrychef.rb
+++ b/omnibus/config/projects/angrychef.rb
@@ -21,7 +21,7 @@
#
current_file = __FILE__
chef_project_contents = IO.read(File.expand_path("../chef.rb", __FILE__))
-self.instance_eval chef_project_contents
+instance_eval chef_project_contents
name "angrychef"
friendly_name "Angry Chef Client"
diff --git a/omnibus/config/projects/chef.rb b/omnibus/config/projects/chef.rb
index 3d92d290a0..a0e490ceab 100644
--- a/omnibus/config/projects/chef.rb
+++ b/omnibus/config/projects/chef.rb
@@ -39,11 +39,6 @@ else
install_dir "#{default_root}/#{name}"
end
-# Global FIPS override flag.
-if windows? || rhel?
- override :fips, enabled: true
-end
-
# Load dynamically updated overrides
overrides_path = File.expand_path("../../../../omnibus_overrides.rb", current_file)
instance_eval(IO.read(overrides_path), overrides_path)
diff --git a/omnibus/config/software/chef-gem-bcrypt_pbkdf-ruby.rb b/omnibus/config/software/chef-gem-bcrypt_pbkdf-ruby.rb
new file mode 100644
index 0000000000..1f7f4d3207
--- /dev/null
+++ b/omnibus/config/software/chef-gem-bcrypt_pbkdf-ruby.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 "MIT"
+license_file "https://raw.githubusercontent.com/mfazekas/bcrypt_pbkdf-ruby/master/COPYING"
+skip_transitive_dependency_licensing true
diff --git a/omnibus/config/software/chef-gem-rbnacl-libsodium.rb b/omnibus/config/software/chef-gem-rbnacl-libsodium.rb
new file mode 100644
index 0000000000..90bbc69dfb
--- /dev/null
+++ b/omnibus/config/software/chef-gem-rbnacl-libsodium.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 "MIT"
+license_file "https://raw.githubusercontent.com/cryptosphere/rbnacl-libsodium/master/LICENSE"
+skip_transitive_dependency_licensing true
diff --git a/omnibus/config/software/chef.rb b/omnibus/config/software/chef.rb
index c6ced7e566..c53a2339ae 100644
--- a/omnibus/config/software/chef.rb
+++ b/omnibus/config/software/chef.rb
@@ -44,6 +44,10 @@ dependency "chef-gem-ruby-prof"
dependency "chef-gem-byebug"
dependency "chef-gem-debug_inspector"
dependency "chef-gem-binding_of_caller"
+unless ios_xr? || solaris?
+ dependency "chef-gem-rbnacl-libsodium"
+ dependency "chef-gem-bcrypt_pbkdf-ruby"
+end
# Now everyone else, in alphabetical order because we don't care THAT much
Dir.entries(File.dirname(__FILE__)).sort.each do |gem_software|
diff --git a/omnibus/files/chef/build-chef.rb b/omnibus/files/chef/build-chef.rb
index ba7a84c791..4b8ec78054 100644
--- a/omnibus/files/chef/build-chef.rb
+++ b/omnibus/files/chef/build-chef.rb
@@ -11,7 +11,7 @@ module BuildChef
def create_bundle_config(gemfile, without: without_groups, retries: nil, jobs: nil, frozen: nil)
bundle_config = File.expand_path("../.bundle/config", gemfile)
- block "Put build config into #{bundle_config}: #{ { without: without, retries: retries, jobs: jobs, frozen: frozen } }" do
+ block "Put build config into #{bundle_config}: #{{ without: without, retries: retries, jobs: jobs, frozen: frozen }}" do
# bundle config build.nokogiri #{nokogiri_build_config} messes up the line,
# so we write it directly ourselves.
new_bundle_config = "---\n"
diff --git a/omnibus/omnibus.rb b/omnibus/omnibus.rb
index c6f883adbc..dfbd2bc338 100644
--- a/omnibus/omnibus.rb
+++ b/omnibus/omnibus.rb
@@ -52,3 +52,4 @@ fetcher_read_timeout 120
# local_software_dirs ['/path/to/local/software']
fatal_transitive_dependency_licensing_warnings true
+fips_mode (ENV["OMNIBUS_FIPS_MODE"] || "").casecmp("true") >= 0
diff --git a/omnibus/resources/chef/msi/localization-en-us.wxl.erb b/omnibus/resources/chef/msi/localization-en-us.wxl.erb
index 62c27b99f6..c5e8e5ddab 100644
--- a/omnibus/resources/chef/msi/localization-en-us.wxl.erb
+++ b/omnibus/resources/chef/msi/localization-en-us.wxl.erb
@@ -16,15 +16,27 @@
<String Id="VerifyReadyDlgInstallTitle">{\WixUI_Font_Title_White}Ready to install [ProductName]</String>
+ <!-- Scheduled Task -->
+ <String Id="SchTaskDisplayName"><%= friendly_name %> Scheduled Task</String>
+ <String Id="SchTaskDescription">Schedule <%= friendly_name %> to run at a pre-defined time intervals.</String>
<!-- Service -->
<!-- Keep these in sync with the name and description in chef-service-manager -->
<String Id="ServiceDisplayName"><%= friendly_name %> Service</String>
<String Id="ServiceDescription">Runs <%= friendly_name %> on regular, configurable intervals.</String>
<String Id="FeatureMainName"><%= friendly_name %></String>
+ <String Id="FeatureSchTaskName"><%= friendly_name %> Scheduled Task</String>
<String Id="FeatureServiceName"><%= friendly_name %> Service</String>
<String Id="FeaturePSModuleName"><%= friendly_name %> PowerShell wrappers</String>
<String Id="MinimumOSVersionMessage">This package requires minimum OS version: Windows 7/Windows Server 2008 R2 or greater.</String>
<String Id="DowngradeErrorMessage">A newer version of [ProductName] is already installed.</String>
<String Id="FileExtractionProgress">Extracting files, please wait...</String>
+
+ <String Id="CustomizeDlgTextMsg">Select an option to change between the Chef's unattended execution options.</String>
+ <String Id="CustomizeDlgTextTitle">Chef Unattended Execution Options</String>
+ <String Id="CustomizeDlgFirstRadioButtonText">Chef Client Scheduled Task</String>
+ <String Id="CustomizeDlgSecondRadioButtonText">Chef Client Service</String>
+ <String Id="CustomizeDlgThirdRadioButtonText">None</String>
+
+ <String Id="CustomizeDlgOptionsMsg">The installer can configure the Chef Client to run periodically as either a scheduled task or a service. Using a scheduled task is recommended. For more information, see https://docs.chef.io/windows.html.</String>
</WixLocalization>
diff --git a/omnibus/resources/chef/msi/source.wxs.erb b/omnibus/resources/chef/msi/source.wxs.erb
index bdde02687e..c49a8324f9 100644
--- a/omnibus/resources/chef/msi/source.wxs.erb
+++ b/omnibus/resources/chef/msi/source.wxs.erb
@@ -28,6 +28,8 @@
<Media Id="1" Cabinet="ChefClient.cab" EmbedCab="yes" CompressionLevel="high" />
+ <Property Id="CHEF_SERVICE_OPTIONS_RADIO_BUTTON_GROUP" Value="None" />
+
<!--
Uncomment launch condition below to check for minimum OS
601 = Windows 7/Server 2008R2.
@@ -67,9 +69,42 @@
Impersonate="no"
Return="ignore" />
+ <CustomAction Id="CreateChefClientScheduledTask"
+ Directory="TARGETDIR"
+ ExeCommand="&quot;[SystemFolder]SCHTASKS.EXE&quot; /CREATE /TN &quot;chef-client&quot; /SC &quot;MINUTE&quot; /MO &quot;30&quot; /F /TR &quot;cmd /c \&quot;[EMBEDDEDBIN]ruby.exe [PROJECTLOCATIONBIN]chef-client -L [CONFIGLOCATION]chef-client.log -c [CONFIGLOCATION]client.rb\&quot;&quot; /RU &quot;NT Authority\System&quot; /RP /RL &quot;HIGHEST&quot;"
+ Execute="deferred"
+ Impersonate="no"
+ Return="check" />
+
+ <CustomAction Id="RemoveChefClientScheduledTask"
+ Directory="TARGETDIR"
+ ExeCommand="&quot;[SystemFolder]SCHTASKS.EXE&quot; /DELETE /TN &quot;chef-client&quot; /F"
+ Execute="deferred"
+ Impersonate="no"
+ Return="ignore" />
+
+ <CustomAction Id="RemoveChefClientService"
+ Directory="TARGETDIR"
+ ExeCommand="&quot;[SystemFolder]SC.EXE&quot; DELETE &quot;chef-client&quot;"
+ Execute="deferred"
+ Impersonate="no"
+ Return="ignore" />
+
<InstallExecuteSequence>
<Custom Action="FastUnzip" After="InstallFiles">NOT Installed</Custom>
<Custom Action="Cleanup" After="RemoveFiles">REMOVE~="ALL"</Custom>
+
+ <Custom Action="CreateChefClientScheduledTask" After="InstallFiles">
+ <![CDATA[&ChefSchTaskFeature=3]]>
+ </Custom>
+
+ <Custom Action="RemoveChefClientScheduledTask" Before="RemoveFiles">
+ <![CDATA[(Installed AND (&NoneFeature=3 OR &ChefServiceFeature=3)) OR (REMOVE="ALL")]]>
+ </Custom>
+
+ <Custom Action="RemoveChefClientService" Before="RemoveFiles">
+ <![CDATA[Installed AND (&NoneFeature=3 OR &ChefSchTaskFeature=3) OR (REMOVE="ALL")]]>
+ </Custom>
</InstallExecuteSequence>
<UI>
@@ -135,6 +170,16 @@
</Directory>
</Directory>
</Directory>
+ <Directory Id="ChefSchTaskFeatureTempDir">
+ <Component Id="ChefSchTask" Guid="{7f9f917a-952c-41d8-baa1-037269eecb50}">
+ <CreateFolder />
+ </Component>
+ </Directory>
+ <Directory Id="NoneFeatureTempDir">
+ <Component Id="None" Guid="{d8f3eba5-cecb-436c-a4ef-540dba3c5ccf}">
+ <CreateFolder />
+ </Component>
+ </Directory>
</Directory>
</Directory>
@@ -151,8 +196,24 @@
<ComponentRef Id="ChefPSModulePath" />
</Feature>
- <Feature Id="ChefServiceFeature" Title="!(loc.FeatureServiceName)" Level="1000" AllowAdvertise="no">
- <ComponentRef Id="ChefClientService" />
+ <Feature Id="ChefUnattendedExecutionOptions" Title="Chef Unattended Execution Options" Level="1000" AllowAdvertise="no">
+ <Feature Id="ChefSchTaskFeature" Title="!(loc.FeatureSchTaskName)" Level="1000" AllowAdvertise="no" Display="hidden">
+ <!-- Here, CustomAction will get executed and scheduled task for chef-client will get created -->
+
+ <!-- This is an empty component to keep track of the feature -->
+ <ComponentRef Id="ChefSchTask" />
+ </Feature>
+
+ <Feature Id="ChefServiceFeature" Title="!(loc.FeatureServiceName)" Level="1000" AllowAdvertise="no" Display="hidden">
+ <ComponentRef Id="ChefClientService" />
+ </Feature>
+
+ <Feature Id="NoneFeature" Title="None" Level="1000" AllowAdvertise="no" Display="hidden">
+ <!-- Do Nothing -->
+
+ <!-- This is an empty component to keep track of the feature -->
+ <ComponentRef Id="None" />
+ </Feature>
</Feature>
<!--
@@ -173,12 +234,92 @@
<UIRef Id="ChefClientUI_InstallDir"/>
<UI Id="ChefClientUI_InstallDir">
- <UIRef Id="WixUI_FeatureTree"/>
+ <!-- WixUI_FeatureTree module's code embedded and modified here as per the requirement -->
<TextStyle Id="WixUI_Font_Normal_White" FaceName="Tahoma" Size="8" Red="255" Green="255" Blue="255" />
<TextStyle Id="WixUI_Font_Bigger_White" FaceName="Tahoma" Size="12" Red="255" Green="255" Blue="255" />
<TextStyle Id="WixUI_Font_Title_White" FaceName="Tahoma" Size="9" Bold="yes" Red="255" Green="255" Blue="255" />
+ <TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
+ <TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
+ <TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
+ <TextStyle Id="WixUI_Font_Msg" FaceName="Tahoma" Size="9" />
+
+ <Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
+ <Property Id="WixUI_Mode" Value="FeatureTree" />
+
+ <DialogRef Id="ErrorDlg" />
+ <DialogRef Id="FatalError" />
+ <DialogRef Id="FilesInUse" />
+ <DialogRef Id="MsiRMFilesInUse" />
+ <DialogRef Id="PrepareDlg" />
+ <DialogRef Id="ProgressDlg" />
+ <DialogRef Id="ResumeDlg" />
+ <DialogRef Id="UserExit" />
+
+ <Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
+
+ <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="LicenseAgreementDlg">NOT Installed</Publish>
+ <Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
+
+ <Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
+ <Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="CustomizeDlg">LicenseAccepted = "1"</Publish>
+
+ <Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="1">Installed</Publish>
+ <Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg" Order="2">NOT Installed</Publish>
+
+ <Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg"><![CDATA[((NOT &ChefUnattendedExecutionOptions=3) AND NOT ((?ChefSchTask=3) OR (?ChefClientService=3) OR (?None=3)))]]></Publish>
+
+ <Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="ChefUnattendedExecutionOptionsSelectionDlg"><![CDATA[((&ChefUnattendedExecutionOptions=3) OR (?ChefSchTask=3 OR ?ChefClientService=3 OR ?None=3))]]></Publish>
+
+ <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="CustomizeDlg" Order="1"><![CDATA[NOT &ChefUnattendedExecutionOptions=3]]> AND (NOT Installed OR WixUI_InstallMode = "Change")</Publish>
+ <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="ChefUnattendedExecutionOptionsSelectionDlg" Order="1"><![CDATA[&ChefUnattendedExecutionOptions=3]]> AND (NOT Installed OR WixUI_InstallMode = "Change")</Publish>
+ <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
+ <Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="3">Installed AND PATCH</Publish>
+
+ <Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
+
+ <Publish Dialog="MaintenanceTypeDlg" Control="ChangeButton" Event="NewDialog" Value="CustomizeDlg">1</Publish>
+ <Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
+ <Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
+ <Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
+
+ <Dialog Id ="ChefUnattendedExecutionOptionsSelectionDlg" Width ="370" Height ="270" Title ="!(loc.ProductName) v$(var.DisplayVersionNumber) Setup" NoMinimize ="no">
+ <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.CustomizeDlgBannerBitmap)" />
+ <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
+ <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
+ <Control Id="Title" Type="Text" X="15" Y="6" Width="210" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.CustomizeDlgTitle)" />
+ <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.CustomizeDlgDescription)" />
+ <Control Id="TextMsg" Type="Text" X="25" Y="55" Width="320" Height="20" Text="!(loc.CustomizeDlgTextMsg)" />
+
+ <Control Id="LeftBox" Type="GroupBox" X="25" Y="81" Width="175" Height="118" />
+ <Control Id="TextTitle" Type="Text" X="30" Y="100" Width="169" Height="20" Text="{\WixUI_Font_Title}!(loc.CustomizeDlgTextTitle)" />
+ <Control Id="OptionsRadioGroup" Type="RadioButtonGroup" Property="CHEF_SERVICE_OPTIONS_RADIO_BUTTON_GROUP" Height="80" Width="140" X="35" Y="110">
+ <RadioButtonGroup Property="CHEF_SERVICE_OPTIONS_RADIO_BUTTON_GROUP">
+ <RadioButton Value="SchTask" Text="!(loc.CustomizeDlgFirstRadioButtonText)" Height="17" Width="140" X="0" Y="10" />
+ <RadioButton Value="Service" Text="!(loc.CustomizeDlgSecondRadioButtonText)" Height="17" Width="140" X="0" Y="35" />
+ <RadioButton Value="None" Text="!(loc.CustomizeDlgThirdRadioButtonText)" Height="17" Width="140" X="0" Y="60" />
+ </RadioButtonGroup>
+ </Control>
+
+ <Control Id="RightBox" Type="GroupBox" X="210" Y="81" Width="150" Height="118" />
+ <Control Id="OptionsMsg" Type="Text" X="214" Y="100" Width="146" Height="80" Text="{\WixUI_Font_Msg}!(loc.CustomizeDlgOptionsMsg)" />
+
+ <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Default="no" Text="Back">
+ <Publish Event="NewDialog" Value="CustomizeDlg">1</Publish>
+ </Control>
+ <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="Next">
+ <Publish Event="AddLocal" Value="ChefSchTaskFeature">CHEF_SERVICE_OPTIONS_RADIO_BUTTON_GROUP = "SchTask"</Publish>
+ <Publish Event="AddLocal" Value="ChefServiceFeature">CHEF_SERVICE_OPTIONS_RADIO_BUTTON_GROUP = "Service"</Publish>
+ <Publish Event="AddLocal" Value="NoneFeature">CHEF_SERVICE_OPTIONS_RADIO_BUTTON_GROUP = "None"</Publish>
+ <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
+ </Control>
+ <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="no" Text="Cancel" Cancel="yes">
+ <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
+ </Control>
+ </Dialog>
</UI>
+ <UIRef Id="WixUI_Common" />
+
<WixVariable Id="WixUILicenseRtf" Value="Resources\assets\LICENSE.rtf" />
<WixVariable Id="WixUIDialogBmp" Value="Resources\assets\dialog_background.bmp" />
<WixVariable Id="WixUIBannerBmp" Value="Resources\assets\banner_background.bmp" />
diff --git a/omnibus_overrides.rb b/omnibus_overrides.rb
index 0d740ff046..69a5a7af05 100644
--- a/omnibus_overrides.rb
+++ b/omnibus_overrides.rb
@@ -1,5 +1,5 @@
# DO NOT EDIT. Generated by "rake dependencies". Edit version_policy.rb instead.
-override :rubygems, version: "2.6.8"
+override :rubygems, version: "2.6.10"
override :bundler, version: "1.12.5"
override "libffi", version: "3.2.1"
override "libiconv", version: "1.14"
diff --git a/spec/data/prefer_metadata_json/metadata.json b/spec/data/prefer_metadata_json/metadata.json
new file mode 100644
index 0000000000..eff8836a3b
--- /dev/null
+++ b/spec/data/prefer_metadata_json/metadata.json
@@ -0,0 +1,51 @@
+{
+ "name": "prefer_metadata_json",
+ "description": "",
+ "long_description": "",
+ "maintainer": null,
+ "maintainer_email": null,
+ "license": "All rights reserved",
+ "platforms": {
+
+ },
+ "dependencies": {
+
+ },
+ "recommendations": {
+
+ },
+ "suggestions": {
+
+ },
+ "conflicting": {
+
+ },
+ "providing": {
+
+ },
+ "replacing": {
+
+ },
+ "attributes": {
+
+ },
+ "groupings": {
+
+ },
+ "recipes": {
+
+ },
+ "version": "1.2.3",
+ "source_url": "",
+ "issues_url": "",
+ "privacy": false,
+ "chef_versions": [
+
+ ],
+ "ohai_versions": [
+
+ ],
+ "gems": [
+
+ ]
+}
diff --git a/spec/data/prefer_metadata_json/metadata.rb b/spec/data/prefer_metadata_json/metadata.rb
new file mode 100644
index 0000000000..a46aa29a5c
--- /dev/null
+++ b/spec/data/prefer_metadata_json/metadata.rb
@@ -0,0 +1,6 @@
+# these deliberately do not match metadata.json
+name "test"
+version "0.0.1"
+
+# this raises hard if anything even tries to parse it
+raise "TEH SADNESS"
diff --git a/spec/data/prefer_metadata_json/recipes/default.rb b/spec/data/prefer_metadata_json/recipes/default.rb
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/spec/data/prefer_metadata_json/recipes/default.rb
diff --git a/spec/data/sample_msu1.xml b/spec/data/sample_msu1.xml
new file mode 100644
index 0000000000..cc68dbf060
--- /dev/null
+++ b/spec/data/sample_msu1.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<unattend xmlns="urn:schemas-microsoft-com:unattend">
+ <servicing>
+ <package action="install">
+ <assemblyIdentity name="Package_for_KB2859903" version="10.2.1.0" language="neutral" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35"/>
+ <source location="%configsetroot%\IE10-Windows6.1-KB2859903-x86.CAB" />
+ </package>
+ </servicing>
+</unattend>
+
diff --git a/spec/data/sample_msu2.xml b/spec/data/sample_msu2.xml
new file mode 100644
index 0000000000..6f95e04f93
--- /dev/null
+++ b/spec/data/sample_msu2.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<unattend xmlns="urn:schemas-microsoft-com:unattend">
+ <servicing>
+ <package action="install">
+ <assemblyIdentity name="Package_for_KB2859903" version="10.2.1.0" language="neutral" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35"/>
+ <source location="%configsetroot%\IE10-Windows6.1-KB2859903-x86.CAB" />
+ </package>
+ <package action="install">
+ <assemblyIdentity name="Package_for_abc" version="10.2.1.0" language="neutral" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35"/>
+ <source location="%configsetroot%\abc.CAB" />
+ </package>
+ </servicing>
+</unattend>
+
diff --git a/spec/data/sample_msu3.xml b/spec/data/sample_msu3.xml
new file mode 100644
index 0000000000..0ef09da206
--- /dev/null
+++ b/spec/data/sample_msu3.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<unattend xmlns="urn:schemas-microsoft-com:unattend">
+ <servicing>
+ <package action="install">
+ <assemblyIdentity name="Package_for_KB2859903" version="10.2.1.0" language="neutral" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35"/>
+ <source location="%configsetroot%\IE10-Windows6.1-KB2859903-x86.CAB" />
+ </package>
+ </servicing>
+ <servicing>
+ <package action="install">
+ <assemblyIdentity name="Package_for_abc" version="10.2.1.0" language="neutral" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35"/>
+ <source location="%configsetroot%\abc.CAB" />
+ </package>
+ </servicing>
+</unattend>
+
diff --git a/spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.i686.rpm b/spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.i686.rpm
new file mode 100644
index 0000000000..29a4624971
--- /dev/null
+++ b/spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.i686.rpm
Binary files differ
diff --git a/spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.src.rpm b/spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.src.rpm
new file mode 100644
index 0000000000..b6a6ec3176
--- /dev/null
+++ b/spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.src.rpm
Binary files differ
diff --git a/spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.x86_64.rpm b/spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.x86_64.rpm
new file mode 100644
index 0000000000..239b6ef145
--- /dev/null
+++ b/spec/functional/assets/yumrepo/chef_rpm-1.10-1.fc24.x86_64.rpm
Binary files differ
diff --git a/spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.i686.rpm b/spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.i686.rpm
new file mode 100644
index 0000000000..3421c3628f
--- /dev/null
+++ b/spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.i686.rpm
Binary files differ
diff --git a/spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.src.rpm b/spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.src.rpm
new file mode 100644
index 0000000000..d420659fd5
--- /dev/null
+++ b/spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.src.rpm
Binary files differ
diff --git a/spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm b/spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm
new file mode 100644
index 0000000000..93c1f5e3e3
--- /dev/null
+++ b/spec/functional/assets/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm
Binary files differ
diff --git a/spec/functional/assets/yumrepo/repodata/313329137b55fd333b2dc66394a6661a2befa6cc535d8460d92a4a78a9c581f0-primary.sqlite.bz2 b/spec/functional/assets/yumrepo/repodata/313329137b55fd333b2dc66394a6661a2befa6cc535d8460d92a4a78a9c581f0-primary.sqlite.bz2
new file mode 100644
index 0000000000..d7726b9df6
--- /dev/null
+++ b/spec/functional/assets/yumrepo/repodata/313329137b55fd333b2dc66394a6661a2befa6cc535d8460d92a4a78a9c581f0-primary.sqlite.bz2
Binary files differ
diff --git a/spec/functional/assets/yumrepo/repodata/31ac4db5d5ac593728fcc26aef82b7b93c4cc4dbec843786b1845b939b658553-other.xml.gz b/spec/functional/assets/yumrepo/repodata/31ac4db5d5ac593728fcc26aef82b7b93c4cc4dbec843786b1845b939b658553-other.xml.gz
new file mode 100644
index 0000000000..30d7778ac4
--- /dev/null
+++ b/spec/functional/assets/yumrepo/repodata/31ac4db5d5ac593728fcc26aef82b7b93c4cc4dbec843786b1845b939b658553-other.xml.gz
Binary files differ
diff --git a/spec/functional/assets/yumrepo/repodata/4ac40fa3c6728c1401318e2e20a997436624e83dcf7a5f952b851ef422637773-filelists.sqlite.bz2 b/spec/functional/assets/yumrepo/repodata/4ac40fa3c6728c1401318e2e20a997436624e83dcf7a5f952b851ef422637773-filelists.sqlite.bz2
new file mode 100644
index 0000000000..2df608aa34
--- /dev/null
+++ b/spec/functional/assets/yumrepo/repodata/4ac40fa3c6728c1401318e2e20a997436624e83dcf7a5f952b851ef422637773-filelists.sqlite.bz2
Binary files differ
diff --git a/spec/functional/assets/yumrepo/repodata/66391e53f0510b98b3f0b79f40ba1048026d9a1ef20905d9c40ba6f5411f3243-primary.xml.gz b/spec/functional/assets/yumrepo/repodata/66391e53f0510b98b3f0b79f40ba1048026d9a1ef20905d9c40ba6f5411f3243-primary.xml.gz
new file mode 100644
index 0000000000..d9b7cb879a
--- /dev/null
+++ b/spec/functional/assets/yumrepo/repodata/66391e53f0510b98b3f0b79f40ba1048026d9a1ef20905d9c40ba6f5411f3243-primary.xml.gz
Binary files differ
diff --git a/spec/functional/assets/yumrepo/repodata/8b34697595fcc87928e12d24644dda9462c3857bd932861e28bc77ae1f31be16-filelists.xml.gz b/spec/functional/assets/yumrepo/repodata/8b34697595fcc87928e12d24644dda9462c3857bd932861e28bc77ae1f31be16-filelists.xml.gz
new file mode 100644
index 0000000000..35a973d170
--- /dev/null
+++ b/spec/functional/assets/yumrepo/repodata/8b34697595fcc87928e12d24644dda9462c3857bd932861e28bc77ae1f31be16-filelists.xml.gz
Binary files differ
diff --git a/spec/functional/assets/yumrepo/repodata/b97cca3fe14bcf06c52be4449b6108f7731239ff221111dcce8aada5467f60dc-other.sqlite.bz2 b/spec/functional/assets/yumrepo/repodata/b97cca3fe14bcf06c52be4449b6108f7731239ff221111dcce8aada5467f60dc-other.sqlite.bz2
new file mode 100644
index 0000000000..e682fc0f0b
--- /dev/null
+++ b/spec/functional/assets/yumrepo/repodata/b97cca3fe14bcf06c52be4449b6108f7731239ff221111dcce8aada5467f60dc-other.sqlite.bz2
Binary files differ
diff --git a/spec/functional/assets/yumrepo/repodata/repomd.xml b/spec/functional/assets/yumrepo/repodata/repomd.xml
new file mode 100644
index 0000000000..92937e151a
--- /dev/null
+++ b/spec/functional/assets/yumrepo/repodata/repomd.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">
+ <revision>1479418959</revision>
+<data type="filelists">
+ <checksum type="sha256">8b34697595fcc87928e12d24644dda9462c3857bd932861e28bc77ae1f31be16</checksum>
+ <open-checksum type="sha256">9f5be999b4a535c19afc53703851577e1a325227fab651189c5c39708b9a1e38</open-checksum>
+ <location href="repodata/8b34697595fcc87928e12d24644dda9462c3857bd932861e28bc77ae1f31be16-filelists.xml.gz"/>
+ <timestamp>1479418959</timestamp>
+ <size>419</size>
+ <open-size>1127</open-size>
+</data>
+<data type="primary">
+ <checksum type="sha256">66391e53f0510b98b3f0b79f40ba1048026d9a1ef20905d9c40ba6f5411f3243</checksum>
+ <open-checksum type="sha256">dc25cfbf4520861130e0ba203d27cc40b183fbb7c576aac33d838fb20a68aa32</open-checksum>
+ <location href="repodata/66391e53f0510b98b3f0b79f40ba1048026d9a1ef20905d9c40ba6f5411f3243-primary.xml.gz"/>
+ <timestamp>1479418959</timestamp>
+ <size>859</size>
+ <open-size>4529</open-size>
+</data>
+<data type="primary_db">
+ <checksum type="sha256">313329137b55fd333b2dc66394a6661a2befa6cc535d8460d92a4a78a9c581f0</checksum>
+ <open-checksum type="sha256">720b637c782cce8604b922e9989ecfff9091e26163d643bd1b676778beb1c933</open-checksum>
+ <location href="repodata/313329137b55fd333b2dc66394a6661a2befa6cc535d8460d92a4a78a9c581f0-primary.sqlite.bz2"/>
+ <timestamp>1479418959</timestamp>
+ <database_version>10</database_version>
+ <size>2460</size>
+ <open-size>32768</open-size>
+</data>
+<data type="other_db">
+ <checksum type="sha256">b97cca3fe14bcf06c52be4449b6108f7731239ff221111dcce8aada5467f60dc</checksum>
+ <open-checksum type="sha256">938156bcfc95828cb6857e1b2790dceaef57196843a80464ba5749772fc15e83</open-checksum>
+ <location href="repodata/b97cca3fe14bcf06c52be4449b6108f7731239ff221111dcce8aada5467f60dc-other.sqlite.bz2"/>
+ <timestamp>1479418959</timestamp>
+ <database_version>10</database_version>
+ <size>967</size>
+ <open-size>6144</open-size>
+</data>
+<data type="other">
+ <checksum type="sha256">31ac4db5d5ac593728fcc26aef82b7b93c4cc4dbec843786b1845b939b658553</checksum>
+ <open-checksum type="sha256">2ea64cdb2f5ba3859af29fe67a85d61d5b4de23f3da1ee71d5af175d8d887ab6</open-checksum>
+ <location href="repodata/31ac4db5d5ac593728fcc26aef82b7b93c4cc4dbec843786b1845b939b658553-other.xml.gz"/>
+ <timestamp>1479418959</timestamp>
+ <size>413</size>
+ <open-size>1035</open-size>
+</data>
+<data type="filelists_db">
+ <checksum type="sha256">4ac40fa3c6728c1401318e2e20a997436624e83dcf7a5f952b851ef422637773</checksum>
+ <open-checksum type="sha256">8bc15efa19d02a5112e20c6ed1be17c5851287ddfba17aee2283ddb216dd08d7</open-checksum>
+ <location href="repodata/4ac40fa3c6728c1401318e2e20a997436624e83dcf7a5f952b851ef422637773-filelists.sqlite.bz2"/>
+ <timestamp>1479418959</timestamp>
+ <database_version>10</database_version>
+ <size>1131</size>
+ <open-size>7168</open-size>
+</data>
+</repomd>
diff --git a/spec/functional/knife/ssh_spec.rb b/spec/functional/knife/ssh_spec.rb
index 065b646ac6..aea7585bb2 100644
--- a/spec/functional/knife/ssh_spec.rb
+++ b/spec/functional/knife/ssh_spec.rb
@@ -181,7 +181,7 @@ describe Chef::Knife::Ssh do
it "uses the ssh_attribute" do
@knife.run
- expect(@knife.get_ssh_attribute(Chef::Node.new)).to eq("ec2.public_hostname")
+ expect(@knife.get_ssh_attribute({ "knife_config" => "ec2.public_hostname" })).to eq("ec2.public_hostname")
end
end
@@ -193,11 +193,11 @@ describe Chef::Knife::Ssh do
it "uses the default" do
@knife.run
- expect(@knife.get_ssh_attribute(Chef::Node.new)).to eq("fqdn")
+ expect(@knife.get_ssh_attribute({ "fqdn" => "fqdn" })).to eq("fqdn")
end
end
- context "when -a ec2.public_ipv4 is provided" do
+ context "when -a ec2.public_public_hostname is provided" do
before do
setup_knife(["-a ec2.public_hostname", "*:*", "uptime"])
Chef::Config[:knife][:ssh_attribute] = nil
@@ -276,8 +276,8 @@ describe Chef::Knife::Ssh do
Chef::Config[:client_key] = nil
Chef::Config[:chef_server_url] = "http://localhost:9000"
- @api.get("/search/node?q=*:*&sort=X_CHEF_id_CHEF_X%20asc&start=0", 200) do
- %({"total":1, "start":0, "rows":[{"name":"i-xxxxxxxx", "json_class":"Chef::Node", "automatic":{"fqdn":"the.fqdn", "ec2":{"public_hostname":"the_public_hostname"}},"recipes":[]}]})
+ @api.post("/search/node?q=*:*&sort=X_CHEF_id_CHEF_X%20asc&start=0", 200) do
+ %({"total":1, "start":0, "rows":[{"data": {"fqdn":"the.fqdn", "config": "the_public_hostname", "knife_config": "the_public_hostname" }}]})
end
end
diff --git a/spec/functional/rebooter_spec.rb b/spec/functional/rebooter_spec.rb
index 0006f3bcdb..1b6e95b39c 100644
--- a/spec/functional/rebooter_spec.rb
+++ b/spec/functional/rebooter_spec.rb
@@ -43,7 +43,7 @@ describe Chef::Platform::Rebooter do
let(:expected) do
{
- :windows => 'shutdown /r /t 300 /c "rebooter spec test"',
+ :windows => "#{ENV['SYSTEMROOT']}/System32/shutdown.exe /r /t 300 /c \"rebooter spec test\"",
:linux => 'shutdown -r +5 "rebooter spec test"',
}
end
@@ -80,7 +80,7 @@ describe Chef::Platform::Rebooter do
describe "when using #reboot_if_needed!" do
include_context "test a reboot method"
- it "should produce the correct string on Windows" do
+ it "should produce the correct string on Windows", :windows_only do
test_rebooter_method(:reboot_if_needed!, true, expected[:windows])
end
@@ -92,7 +92,7 @@ describe Chef::Platform::Rebooter do
describe "when using #reboot!" do
include_context "test a reboot method"
- it "should produce the correct string on Windows" do
+ it "should produce the correct string on Windows", :windows_only do
test_rebooter_method(:reboot!, true, expected[:windows])
end
diff --git a/spec/functional/resource/batch_spec.rb b/spec/functional/resource/batch_spec.rb
index e4fc6420c7..2b176ed06c 100644
--- a/spec/functional/resource/batch_spec.rb
+++ b/spec/functional/resource/batch_spec.rb
@@ -23,7 +23,11 @@ describe Chef::Resource::WindowsScript::Batch, :windows_only do
let(:output_command) { " > " }
- let (:architecture_command) { "@echo %PROCESSOR_ARCHITECTURE%" }
+ let(:architecture_command) { "@echo %PROCESSOR_ARCHITECTURE%" }
+
+ let(:resource) do
+ Chef::Resource::WindowsScript::Batch.new("Batch resource functional test", @run_context)
+ end
it_behaves_like "a Windows script running on Windows"
diff --git a/spec/functional/resource/dnf_package_spec.rb b/spec/functional/resource/dnf_package_spec.rb
new file mode 100644
index 0000000000..4c9ee6ca97
--- /dev/null
+++ b/spec/functional/resource/dnf_package_spec.rb
@@ -0,0 +1,686 @@
+#
+# Copyright:: Copyright 2016, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+require "functional/resource/base"
+require "chef/mixin/shell_out"
+
+# run this test only for following platforms.
+exclude_test = !(%w{rhel fedora}.include?(ohai[:platform_family]) && File.exist?("/usr/bin/dnf"))
+describe Chef::Resource::RpmPackage, :requires_root, :external => exclude_test do
+ include Chef::Mixin::ShellOut
+
+ def flush_cache
+ # needed on at least fc23/fc24 sometimes to deal with the dnf cache getting out of sync with the rpm db
+ FileUtils.rm_f "/var/cache/dnf/@System.solv"
+ Chef::Resource::DnfPackage.new("shouldnt-matter", run_context).run_action(:flush_cache)
+ end
+
+ def preinstall(*rpms)
+ rpms.each do |rpm|
+ shell_out!("rpm -ivh #{CHEF_SPEC_ASSETS}/yumrepo/#{rpm}")
+ end
+ flush_cache
+ end
+
+ before(:each) do
+ File.open("/etc/yum.repos.d/chef-dnf-localtesting.repo", "w+") do |f|
+ f.write <<-EOF
+[chef-dnf-localtesting]
+name=Chef DNF spec testing repo
+baseurl=file://#{CHEF_SPEC_ASSETS}/yumrepo
+enable=1
+gpgcheck=0
+ EOF
+ end
+ shell_out!("rpm -qa | grep chef_rpm | xargs -r rpm -e")
+ end
+
+ after(:all) do
+ shell_out!("rpm -qa | grep chef_rpm | xargs -r rpm -e")
+ FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
+ end
+
+ let(:package_name) { "chef_rpm" }
+ let(:dnf_package) { Chef::Resource::DnfPackage.new(package_name, run_context) }
+
+ describe ":install" do
+ context "vanilla use case" do
+ let(:package_name) { "chef_rpm" }
+
+ it "installs if the package is not installed" do
+ flush_cache
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "does not install if the package is installed" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "does not install twice" do
+ flush_cache
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "does not install if the prior version package is installed" do
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "does not install if the i686 package is installed" do
+ skip "FIXME: do nothing, or install the x86_64 version?"
+ preinstall("chef_rpm-1.10-1.fc24.i686.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.i686")
+ end
+
+ it "does not install if the prior version i686 package is installed" do
+ skip "FIXME: do nothing, or install the x86_64 version?"
+ preinstall("chef_rpm-1.2-1.fc24.i686.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.i686")
+ end
+ end
+
+ context "with versions or globs in the name" do
+ it "works with a version" do
+ flush_cache
+ dnf_package.package_name("chef_rpm-1.10")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "works with an older version" do
+ flush_cache
+ dnf_package.package_name("chef_rpm-1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "works with an evr" do
+ flush_cache
+ dnf_package.package_name("chef_rpm-0:1.2-1.fc24")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "works with a version glob" do
+ flush_cache
+ dnf_package.package_name("chef_rpm-1*")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "works with a name glob + version glob" do
+ flush_cache
+ dnf_package.package_name("chef_rp*-1*")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+ end
+
+ # version only matches the actual dnf version, does not work with epoch or release or combined evr
+ context "with version property" do
+ it "matches the full version" do
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.version("1.10")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "matches with a glob" do
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.version("1*")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "matches the vr" do
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.version("1.10-1.fc24")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "matches the evr" do
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.version("0:1.10-1.fc24")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "matches with a vr glob" do
+ pending "doesn't work on command line either"
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.version("1.10-1*")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "matches with an evr glob" do
+ pending "doesn't work on command line either"
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.version("0:1.10-1*")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+ end
+
+ context "downgrades" do
+ it "just work with DNF" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.version("1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "throws a deprecation warning with allow_downgrade" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ expect(Chef).to receive(:deprecated).with(:dnf_package_allow_downgrade, /^the allow_downgrade property on the dnf_package provider is not used/)
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.version("1.2")
+ dnf_package.run_action(:install)
+ dnf_package.allow_downgrade true
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+ end
+
+ context "with arches" do
+ it "installs with 64-bit arch in the name" do
+ flush_cache
+ dnf_package.package_name("chef_rpm.x86_64")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "installs with 32-bit arch in the name" do
+ flush_cache
+ dnf_package.package_name("chef_rpm.i686")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.i686")
+ end
+
+ it "installs with 64-bit arch in the property" do
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.arch("x86_64")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "installs with 32-bit arch in the property" do
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.arch("i686")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.i686")
+ end
+ end
+
+ context "with constraints" do
+ it "with nothing installed, it installs the latest version" do
+ flush_cache
+ dnf_package.package_name("chef_rpm >= 1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "when it is met, it does nothing" do
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.package_name("chef_rpm >= 1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "when it is met, it does nothing" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.package_name("chef_rpm >= 1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "with nothing intalled, it installs the latest version" do
+ flush_cache
+ dnf_package.package_name("chef_rpm > 1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "when it is not met by an installed rpm, it upgrades" do
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.package_name("chef_rpm > 1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "when it is met by an installed rpm, it does nothing" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.package_name("chef_rpm > 1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "when there is no solution to the contraint" do
+ flush_cache
+ dnf_package.package_name("chef_rpm > 2.0")
+ expect { dnf_package.run_action(:install) }.to raise_error(Chef::Exceptions::Package, /No candidate version available/)
+ end
+
+ it "when there is no solution to the contraint but an rpm is preinstalled" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.package_name("chef_rpm > 2.0")
+ expect { dnf_package.run_action(:install) }.to raise_error(Chef::Exceptions::Package, /No candidate version available/)
+ end
+ end
+
+ context "with source arguments" do
+ it "raises an exception when the package does not exist" do
+ flush_cache
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/this-file-better-not-exist.rpm")
+ expect { dnf_package.run_action(:install) }.to raise_error(Chef::Exceptions::Package, /No candidate version available/)
+ end
+
+ it "does not raise a hard exception in why-run mode when the package does not exist" do
+ Chef::Config[:why_run] = true
+ flush_cache
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/this-file-better-not-exist.rpm")
+ dnf_package.run_action(:install)
+ expect { dnf_package.run_action(:install) }.not_to raise_error
+ end
+
+ it "installs the package when using the source argument" do
+ flush_cache
+ dnf_package.name "something"
+ dnf_package.package_name "somethingelse"
+ dnf_package.source("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "installs the package when the name is a path to a file" do
+ flush_cache
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "does not downgrade the package with :install" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "does not upgrade the package with :install" do
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "is idempotent when the package is already installed" do
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+ end
+
+ context "with no available version" do
+ it "works when a package is installed" do
+ FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "works with a local source" do
+ FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
+ flush_cache
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+ end
+
+ context "multipackage with arches" do
+ it "installs two rpms" do
+ flush_cache
+ dnf_package.package_name([ "chef_rpm.x86_64", "chef_rpm.i686" ] )
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.x86_64/)
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.i686/)
+ end
+
+ it "does nothing if both are installed" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm", "chef_rpm-1.10-1.fc24.i686.rpm")
+ flush_cache
+ dnf_package.package_name([ "chef_rpm.x86_64", "chef_rpm.i686" ] )
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ end
+
+ it "installs the second rpm if the first is installed" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.package_name([ "chef_rpm.x86_64", "chef_rpm.i686" ] )
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.x86_64/)
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.i686/)
+ end
+
+ it "installs the first rpm if the second is installed" do
+ preinstall("chef_rpm-1.10-1.fc24.i686.rpm")
+ dnf_package.package_name([ "chef_rpm.x86_64", "chef_rpm.i686" ] )
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.x86_64/)
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.i686/)
+ end
+
+ # unlikely to work consistently correct, okay to deprecate the arch-array in favor of the arch in the name
+ it "installs two rpms with multi-arch" do
+ flush_cache
+ dnf_package.package_name(%w{chef_rpm chef_rpm} )
+ dnf_package.arch(%w{x86_64 i686})
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.x86_64/)
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.i686/)
+ end
+
+ # unlikely to work consistently correct, okay to deprecate the arch-array in favor of the arch in the name
+ it "installs the second rpm if the first is installed (muti-arch)" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.package_name(%w{chef_rpm chef_rpm} )
+ dnf_package.arch(%w{x86_64 i686})
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.x86_64/)
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.i686/)
+ end
+
+ # unlikely to work consistently correct, okay to deprecate the arch-array in favor of the arch in the name
+ it "installs the first rpm if the second is installed (muti-arch)" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.package_name(%w{chef_rpm chef_rpm} )
+ dnf_package.arch(%w{x86_64 i686})
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.x86_64/)
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.fc24.i686/)
+ end
+
+ # unlikely to work consistently correct, okay to deprecate the arch-array in favor of the arch in the name
+ it "does nothing if both are installed (muti-arch)" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm", "chef_rpm-1.10-1.fc24.i686.rpm")
+ dnf_package.package_name(%w{chef_rpm chef_rpm} )
+ dnf_package.arch(%w{x86_64 i686})
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ end
+ end
+ end
+
+ describe ":upgrade" do
+ context "downgrades" do
+ it "just work with DNF" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.version("1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "throws a deprecation warning with allow_downgrade" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ expect(Chef).to receive(:deprecated).with(:dnf_package_allow_downgrade, /^the allow_downgrade property on the dnf_package provider is not used/)
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.version("1.2")
+ dnf_package.run_action(:install)
+ dnf_package.allow_downgrade true
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+ end
+
+ context "with source arguments" do
+ it "installs the package when using the source argument" do
+ flush_cache
+ dnf_package.name "something"
+ dnf_package.package_name "somethingelse"
+ dnf_package.source("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "installs the package when the name is a path to a file" do
+ flush_cache
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "downgrades the package" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "upgrades the package" do
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+
+ it "is idempotent when the package is already installed" do
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+ end
+
+ context "with no available version" do
+ it "works when a package is installed" do
+ FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+
+ it "works with a local source" do
+ FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
+ flush_cache
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.x86_64")
+ end
+ end
+ end
+
+ describe ":remove" do
+ context "vanilla use case" do
+ let(:package_name) { "chef_rpm" }
+ it "does nothing if the package is not installed" do
+ flush_cache
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+
+ it "removes the package if the package is installed" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+
+ it "does not remove the package twice" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+
+ it "removes the package if the prior version package is installed" do
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+
+ it "removes the package if the i686 package is installed" do
+ skip "FIXME: should this be fixed or is the current behavior correct?"
+ preinstall("chef_rpm-1.10-1.fc24.i686.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+
+ it "removes the package if the prior version i686 package is installed" do
+ skip "FIXME: should this be fixed or is the current behavior correct?"
+ preinstall("chef_rpm-1.2-1.fc24.i686.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+ end
+
+ context "with 64-bit arch" do
+ let(:package_name) { "chef_rpm.x86_64" }
+ it "does nothing if the package is not installed" do
+ flush_cache
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+
+ it "removes the package if the package is installed" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+
+ it "removes the package if the prior version package is installed" do
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+
+ it "does nothing if the i686 package is installed" do
+ preinstall("chef_rpm-1.10-1.fc24.i686.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.i686")
+ end
+
+ it "does nothing if the prior version i686 package is installed" do
+ preinstall("chef_rpm-1.2-1.fc24.i686.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.fc24.i686")
+ end
+ end
+
+ context "with 32-bit arch" do
+ let(:package_name) { "chef_rpm.i686" }
+ it "removes only the 32-bit arch if both are installed" do
+ preinstall("chef_rpm-1.10-1.fc24.x86_64.rpm", "chef_rpm-1.10-1.fc24.i686.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.fc24.x86_64")
+ end
+ end
+
+ context "with no available version" do
+ it "works when a package is installed" do
+ FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
+ preinstall("chef_rpm-1.2-1.fc24.x86_64.rpm")
+ dnf_package.run_action(:remove)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ end
+ end
+ end
+end
diff --git a/spec/functional/resource/dsc_script_spec.rb b/spec/functional/resource/dsc_script_spec.rb
index e2b58f6432..ce92c468f0 100644
--- a/spec/functional/resource/dsc_script_spec.rb
+++ b/spec/functional/resource/dsc_script_spec.rb
@@ -65,10 +65,8 @@ describe Chef::Resource::DscScript, :windows_powershell_dsc_only do
end
def delete_user(target_user)
- begin
- shell_out!("net user #{target_user} /delete")
- rescue Mixlib::ShellOut::ShellCommandFailed
- end
+ shell_out!("net user #{target_user} /delete")
+ rescue Mixlib::ShellOut::ShellCommandFailed
end
let(:dsc_env_variable) { "chefenvtest" }
@@ -76,6 +74,7 @@ describe Chef::Resource::DscScript, :windows_powershell_dsc_only do
let(:env_value2) { "value2" }
let(:dsc_test_run_context) do
node = Chef::Node.new
+ node.automatic["os"] = "windows"
node.automatic["platform"] = "windows"
node.automatic["platform_version"] = "6.1"
node.automatic["kernel"][:machine] = :x86_64 # Only 64-bit architecture is supported
diff --git a/spec/functional/resource/execute_spec.rb b/spec/functional/resource/execute_spec.rb
index 3c31537ebe..09b7286854 100644
--- a/spec/functional/resource/execute_spec.rb
+++ b/spec/functional/resource/execute_spec.rb
@@ -137,6 +137,18 @@ describe Chef::Resource::Execute do
end
end
+ describe "when a guard is specified" do
+ describe "when using the default guard interpreter" do
+ let(:guard_interpreter_resource) { nil }
+ it_behaves_like "a resource with a guard specifying an alternate user identity"
+ end
+
+ describe "when using the execute resource as the guard interpreter" do
+ let(:guard_interpreter_resource) { :execute }
+ it_behaves_like "a resource with a guard specifying an alternate user identity"
+ end
+ end
+
# Ensure that CommandTimeout is raised, and is caused by resource.timeout really expiring.
# https://github.com/chef/chef/issues/2985
#
@@ -151,4 +163,9 @@ describe Chef::Resource::Execute do
expect { resource.run_action(:run) }.to raise_error(Mixlib::ShellOut::CommandTimeout)
end
end
+
+ describe "when running with an alternate user identity" do
+ let(:resource_command_property) { :command }
+ it_behaves_like "an execute resource that supports alternate user identity"
+ end
end
diff --git a/spec/functional/resource/link_spec.rb b/spec/functional/resource/link_spec.rb
index de6976448e..256f350640 100644
--- a/spec/functional/resource/link_spec.rb
+++ b/spec/functional/resource/link_spec.rb
@@ -20,6 +20,7 @@ require "spec_helper"
if windows?
require "chef/win32/file" #probably need this in spec_helper
+ require "chef/win32/security"
end
describe Chef::Resource::Link do
@@ -62,6 +63,18 @@ describe Chef::Resource::Link do
end
end
+ def node
+ node = Chef::Node.new
+ node.consume_external_attrs(ohai.data, {})
+ node
+ end
+
+ def user(user)
+ usr = Chef::Resource.resource_for_node(:user, node).new(user, run_context)
+ usr.password("ComplexPass11!") if windows?
+ usr
+ end
+
def cleanup_link(path)
if windows? && File.directory?(path)
# If the link target is a directory rm_rf doesn't work all the
@@ -108,6 +121,42 @@ describe Chef::Resource::Link do
end
end
+ let(:test_user) { windows? ? nil : ENV["USER"] }
+
+ def expected_owner
+ if windows?
+ get_sid(test_user)
+ else
+ test_user
+ end
+ end
+
+ def get_sid(value)
+ if value.kind_of?(String)
+ Chef::ReservedNames::Win32::Security::SID.from_account(value)
+ elsif value.kind_of?(Chef::ReservedNames::Win32::Security::SID)
+ value
+ else
+ raise "Must specify username or SID: #{value}"
+ end
+ end
+
+ def chown(file, user)
+ if windows?
+ Chef::ReservedNames::Win32::Security::SecurableObject.new(file).owner = get_sid(user)
+ else
+ File.lchown(Etc.getpwnam(user).uid, Etc.getpwnam(user).gid, file)
+ end
+ end
+
+ def owner(file)
+ if windows?
+ Chef::ReservedNames::Win32::Security::SecurableObject.new(file).security_descriptor.owner
+ else
+ Etc.getpwuid(File.lstat(file).uid).name
+ end
+ end
+
def create_resource
node = Chef::Node.new
events = Chef::EventDispatch::Dispatcher.new
@@ -184,6 +233,7 @@ describe Chef::Resource::Link do
it "links to the target file" do
expect(symlink?(target_file)).to be_truthy
expect(readlink(target_file)).to eq(canonicalize(to))
+ expect(owner(target_file)).to eq(expected_owner) unless test_user.nil?
end
it "marks the resource updated" do
expect(resource).to be_updated
@@ -205,6 +255,7 @@ describe Chef::Resource::Link do
it "leaves the file linked" do
expect(symlink?(target_file)).to be_truthy
expect(readlink(target_file)).to eq(canonicalize(to))
+ expect(owner(target_file)).to eq(expected_owner) unless test_user.nil?
end
it "does not mark the resource updated" do
expect(resource).not_to be_updated
@@ -291,13 +342,23 @@ describe Chef::Resource::Link do
expect(File.exists?(to)).to be_truthy
end
end
- context "pointing somewhere else" do
+ context "pointing somewhere else", :requires_root_or_running_windows do
+ let(:test_user) { "test-link-user" }
+ before do
+ user(test_user).run_action(:create)
+ end
+ after do
+ user(test_user).run_action(:remove)
+ end
before(:each) do
+ resource.owner(test_user)
@other_target = File.join(test_file_dir, make_tmpname("other_spec"))
File.open(@other_target, "w") { |file| file.write("eek") }
symlink(@other_target, target_file)
+ chown(target_file, test_user)
expect(symlink?(target_file)).to be_truthy
expect(readlink(target_file)).to eq(canonicalize(@other_target))
+ expect(owner(target_file)).to eq(expected_owner)
end
after(:each) do
File.delete(@other_target)
diff --git a/spec/functional/resource/msu_package_spec.rb b/spec/functional/resource/msu_package_spec.rb
new file mode 100644
index 0000000000..23342be6ae
--- /dev/null
+++ b/spec/functional/resource/msu_package_spec.rb
@@ -0,0 +1,84 @@
+#
+# Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
+# Copyright:: Copyright (c) 2016 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+require "chef/provider/package/cab"
+
+describe Chef::Resource::MsuPackage, :win2012r2_only do
+
+ let(:package_name) { "Package_for_KB2959977" }
+ let(:package_source) { "https://download.microsoft.com/download/3/B/3/3B320C07-B7B1-41E5-81F4-79EBC02DF7D3/Windows8.1-KB2959977-x64.msu" }
+
+ let(:new_resource) { Chef::Resource::CabPackage.new("windows_test_pkg") }
+ let(:cab_provider) do
+ node = Chef::Node.new
+ events = Chef::EventDispatch::Dispatcher.new
+ run_context = Chef::RunContext.new(node, {}, events)
+ Chef::Provider::Package::Cab.new(new_resource, run_context)
+ end
+
+ subject do
+ new_resource = Chef::Resource::MsuPackage.new("test msu package", run_context)
+ new_resource.package_name package_name
+ new_resource.source package_source
+ new_resource
+ end
+
+ context "installing package" do
+ after { remove_package }
+
+ it "installs the package successfully" do
+ subject.run_action(:install)
+ found_packages = cab_provider.installed_packages.select { |p| p["package_identity"] =~ /^#{package_name}~/ }
+ expect(found_packages.length).to be == 1
+ end
+ end
+
+ context "removing a package" do
+ it "removes an installed package" do
+ subject.run_action(:install)
+ remove_package
+ found_packages = cab_provider.installed_packages.select { |p| p["package_identity"] =~ /^#{package_name}~/ }
+ expect(found_packages.length).to be == 0
+ end
+ end
+
+ context "when an invalid msu package is given" do
+ def package_name
+ "Package_for_KB2859903"
+ end
+
+ def package_source
+ "https://download.microsoft.com/download/5/2/B/52BE95BF-22D8-4415-B644-0FDF398F6D96/IE10-Windows6.1-KB2859903-x86.msu"
+ end
+
+ it "raises error while installing" do
+ expect { subject.run_action(:install) }.to raise_error(Chef::Exceptions::Package)
+ end
+
+ it "raises error while removing" do
+ expect { subject.run_action(:remove) }.to raise_error(Chef::Exceptions::Package)
+ end
+ end
+
+ def remove_package
+ pkg_to_remove = Chef::Resource::MsuPackage.new(package_name, run_context)
+ pkg_to_remove.source = package_source
+ pkg_to_remove.run_action(:remove)
+ end
+end
diff --git a/spec/functional/resource/registry_spec.rb b/spec/functional/resource/registry_spec.rb
index a7748fa4e7..5c97626c78 100644
--- a/spec/functional/resource/registry_spec.rb
+++ b/spec/functional/resource/registry_spec.rb
@@ -112,9 +112,9 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do
@node.name("windowsbox")
@rest_client = double("Chef::ServerAPI (mock)")
- allow(@rest_client).to receive(:create_url).and_return("reports/nodes/windowsbox/runs/#{@run_id}");
- allow(@rest_client).to receive(:raw_http_request).and_return({ "result" => "ok" });
- allow(@rest_client).to receive(:post_rest).and_return({ "uri" => "https://example.com/reports/nodes/windowsbox/runs/#{@run_id}" });
+ allow(@rest_client).to receive(:create_url).and_return("reports/nodes/windowsbox/runs/#{@run_id}")
+ allow(@rest_client).to receive(:raw_http_request).and_return({ "result" => "ok" })
+ allow(@rest_client).to receive(:post_rest).and_return({ "uri" => "https://example.com/reports/nodes/windowsbox/runs/#{@run_id}" })
@resource_reporter = Chef::ResourceReporter.new(@rest_client)
@events.register(@resource_reporter)
diff --git a/spec/functional/resource/user/dscl_spec.rb b/spec/functional/resource/user/dscl_spec.rb
index bedb37838c..ed96e31bac 100644
--- a/spec/functional/resource/user/dscl_spec.rb
+++ b/spec/functional/resource/user/dscl_spec.rb
@@ -28,11 +28,9 @@ describe "Chef::Resource::User with Chef::Provider::User::Dscl provider", metada
include Chef::Mixin::ShellOut
def clean_user
- begin
- shell_out!("/usr/bin/dscl . -delete '/Users/#{username}'")
- rescue Mixlib::ShellOut::ShellCommandFailed
+ shell_out!("/usr/bin/dscl . -delete '/Users/#{username}'")
+ rescue Mixlib::ShellOut::ShellCommandFailed
# Raised when the user is already cleaned
- end
end
def user_should_exist
diff --git a/spec/functional/resource/user/useradd_spec.rb b/spec/functional/resource/user/useradd_spec.rb
index 874155c107..497cb0b043 100644
--- a/spec/functional/resource/user/useradd_spec.rb
+++ b/spec/functional/resource/user/useradd_spec.rb
@@ -119,7 +119,7 @@ describe Chef::Provider::User::Useradd, metadata do
break if status.exitstatus != 8
sleep 1
- max_retries = max_retries - 1
+ max_retries -= 1
rescue UserNotFound
break
end
@@ -645,6 +645,15 @@ describe Chef::Provider::User::Useradd, metadata do
expect(@error).to be_a(Mixlib::ShellOut::ShellCommandFailed)
expect(@error.message).to include("Cannot unlock the password")
end
+ elsif %w{rhel}.include?(OHAI_SYSTEM["platform_family"]) &&
+ OHAI_SYSTEM["platform_version"].to_f == 6.8
+ # usermod -U returns following message for rhel68 on s390x platforms
+ # usermod: unlocking the user's password would result in a passwordless account.
+ #You should set a password with usermod -p to unlock this user's password.
+ it "errors out trying to unlock the user" do
+ expect(@error).to be_a(Mixlib::ShellOut::ShellCommandFailed)
+ expect(@error.message).to include("You should set a password")
+ end
else
# borked on all other platforms:
diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb
index da3a2b98e4..7a8059066a 100644
--- a/spec/integration/client/client_spec.rb
+++ b/spec/integration/client/client_spec.rb
@@ -46,6 +46,7 @@ describe "chef-client" do
# we're running `chef-client` from the source tree and not the external one.
# cf. CHEF-4914
let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" }
+ let(:chef_solo) { "ruby '#{chef_dir}/chef-solo' --minimal-ohai" }
let(:critical_env_vars) { %w{_ORIGINAL_GEM_PATH GEM_PATH GEM_HOME GEM_ROOT BUNDLE_BIN_PATH BUNDLE_GEMFILE RUBYLIB RUBYOPT RUBY_ENGINE RUBY_ROOT RUBY_VERSION PATH}.map { |o| "#{o}=#{ENV[o]}" } .join(" ") }
@@ -499,4 +500,36 @@ EOM
expect(result.exitstatus).not_to eq(0)
end
end
+
+ when_the_repository "has a cookbook with broken metadata.rb, but has metadata.json" do
+ before do
+ file "cookbooks/x/recipes/default.rb", ""
+ file "cookbooks/x/metadata.rb", <<EOM
+name 'x'
+version '0.0.1'
+raise "TEH SADNESS"
+EOM
+ file "cookbooks/x/metadata.json", <<EOM
+{
+ "name": "x",
+ "version": "0.0.1"
+}
+EOM
+
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+EOM
+ end
+
+ it "the chef client run should succeed" do
+ command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir)
+ command.error!
+ end
+
+ it "a chef-solo run should succeed" do
+ command = shell_out("#{chef_solo} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir)
+ command.error!
+ end
+ end
end
diff --git a/spec/integration/knife/chef_repo_path_spec.rb b/spec/integration/knife/chef_repo_path_spec.rb
index 1388aa8716..e609fa60b3 100644
--- a/spec/integration/knife/chef_repo_path_spec.rb
+++ b/spec/integration/knife/chef_repo_path_spec.rb
@@ -843,7 +843,7 @@ EOM
context "when data_bag_path and chef_repo_path are set, and nothing else" do
before :each do
- %w{client cookbook environment node role user}.each do |object_name|
+ %w{client cookbook environment node role user}.each do |object_name|
Chef::Config.delete("#{object_name}_path".to_sym)
end
Chef::Config.data_bag_path = File.join(Chef::Config.chef_repo_path, "data_bags")
@@ -903,7 +903,7 @@ EOM
include_context "default config options"
before :each do
- %w{client cookbook environment node role user}.each do |object_name|
+ %w{client cookbook environment node role user}.each do |object_name|
Chef::Config.delete("#{object_name}_path".to_sym)
end
Chef::Config.delete(:chef_repo_path)
diff --git a/spec/integration/recipes/recipe_dsl_spec.rb b/spec/integration/recipes/recipe_dsl_spec.rb
index 456319c306..e2fa7df1fc 100644
--- a/spec/integration/recipes/recipe_dsl_spec.rb
+++ b/spec/integration/recipes/recipe_dsl_spec.rb
@@ -861,9 +861,9 @@ describe "Recipe DSL methods" do
before { resource_class_a } # pull on it so it gets defined before the recipe runs
it "two_classes_one_dsl resolves to A (alphabetically earliest)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_resource).to eq resource_class_a
@@ -891,9 +891,9 @@ describe "Recipe DSL methods" do
before { resource_class_z } # pull on it so it gets defined before the recipe runs
it "two_classes_one_dsl resolves to B (alphabetically earliest)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_resource).to eq resource_class
@@ -909,9 +909,9 @@ describe "Recipe DSL methods" do
end
it "two_classes_one_dsl resolves to Z (respects the priority array)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_resource).to eq resource_class_z
@@ -927,9 +927,9 @@ describe "Recipe DSL methods" do
end
it "two_classes_one_dsl resolves to B (picks the next thing in the priority array)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_resource).to eq resource_class
@@ -948,9 +948,9 @@ describe "Recipe DSL methods" do
end
it "two_classes_one_dsl resolves to Z (respects the most recent priority array)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_resource).to eq resource_class_z
@@ -966,9 +966,9 @@ describe "Recipe DSL methods" do
end
it "two_classes_one_dsl resolves to B (picks the first match from the other priority array)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_resource).to eq resource_class
@@ -991,9 +991,9 @@ describe "Recipe DSL methods" do
end
it "two_classes_one_dsl resolves to B (picks the first match outside the priority array)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_resource).to eq resource_class
@@ -1044,9 +1044,9 @@ describe "Recipe DSL methods" do
before { provider_class_a.provides two_classes_one_dsl }
it "two_classes_one_dsl resolves to A (alphabetically earliest)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class_a
@@ -1056,9 +1056,9 @@ describe "Recipe DSL methods" do
before { provider_class_a.provides(two_classes_one_dsl) { false } }
it "two_classes_one_dsl resolves to B (since A declined)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class
@@ -1085,9 +1085,9 @@ describe "Recipe DSL methods" do
before { provider_class_z.provides two_classes_one_dsl }
it "two_classes_one_dsl resolves to B (alphabetically earliest)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class
@@ -1097,9 +1097,9 @@ describe "Recipe DSL methods" do
before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class_z, provider_class ] }
it "two_classes_one_dsl resolves to Z (respects the priority map)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class_z
@@ -1114,9 +1114,9 @@ describe "Recipe DSL methods" do
before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class_z, provider_class ] }
it "two_classes_one_dsl resolves to B (the next one in the priority map)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class
@@ -1128,9 +1128,9 @@ describe "Recipe DSL methods" do
before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class ] }
it "two_classes_one_dsl resolves to B (the one in the next priority map)" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
- instance_eval("#{two_classes_one_dsl} 'blah'")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class
@@ -1158,22 +1158,22 @@ describe "Recipe DSL methods" do
before { resource_class_blarghle } # pull on it so it gets defined before the recipe runs
it "on os = blarghle, two_classes_one_dsl resolves to Blarghle" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
# this is an ugly way to test, make Cheffish expose node attrs
run_context.node.automatic[:os] = "blarghle"
- instance_eval("#{two_classes_one_dsl} 'blah' do; end")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah' do; end")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_resource).to eq resource_class_blarghle
end
it "on os = linux, two_classes_one_dsl resolves to B" do
- two_classes_one_dsl = self.two_classes_one_dsl
+ temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
# this is an ugly way to test, make Cheffish expose node attrs
run_context.node.automatic[:os] = "linux"
- instance_eval("#{two_classes_one_dsl} 'blah' do; end")
+ instance_eval("#{temp_two_classes_one_dsl} 'blah' do; end")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_resource).to eq resource_class
@@ -1202,15 +1202,15 @@ describe "Recipe DSL methods" do
context "with provides? returning true to my_resource" do
before do
- my_resource = self.my_resource
+ temp_my_resource = my_resource
resource_class.define_singleton_method(:provides?) do |node, resource_name|
@called_provides = true
- resource_name == my_resource
+ resource_name == temp_my_resource
end
end
it "my_resource returns the resource and calls provides?, but does not emit a warning" do
- dsl_name = self.my_resource
+ dsl_name = my_resource
recipe = converge do
instance_eval("#{dsl_name} 'foo'")
end
@@ -1222,15 +1222,15 @@ describe "Recipe DSL methods" do
context "with provides? returning true to blarghle_blarghle_little_star and not resource_name" do
before do
- blarghle_blarghle_little_star = self.blarghle_blarghle_little_star
+ temp_blarghle_blarghle_little_star = blarghle_blarghle_little_star
resource_class.define_singleton_method(:provides?) do |node, resource_name|
@called_provides = true
- resource_name == blarghle_blarghle_little_star
+ resource_name == temp_blarghle_blarghle_little_star
end
end
it "my_resource does not return the resource" do
- dsl_name = self.my_resource
+ dsl_name = my_resource
expect_converge do
instance_eval("#{dsl_name} 'foo'")
end.to raise_error(Chef::Exceptions::NoSuchResourceType)
@@ -1239,7 +1239,7 @@ describe "Recipe DSL methods" do
it "blarghle_blarghle_little_star 'foo' returns the resource and emits a warning" do
Chef::Config[:treat_deprecation_warnings_as_errors] = false
- dsl_name = self.blarghle_blarghle_little_star
+ dsl_name = blarghle_blarghle_little_star
recipe = converge do
instance_eval("#{dsl_name} 'foo'")
end
@@ -1281,9 +1281,9 @@ describe "Recipe DSL methods" do
end
it "my_resource runs the provider and does not emit a warning" do
- my_resource = self.my_resource
+ temp_my_resource = my_resource
recipe = converge do
- instance_eval("#{my_resource} 'foo'")
+ instance_eval("#{temp_my_resource} 'foo'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class
@@ -1311,9 +1311,9 @@ describe "Recipe DSL methods" do
end
it "my_resource runs the first provider" do
- my_resource = self.my_resource
+ temp_my_resource = my_resource
recipe = converge do
- instance_eval("#{my_resource} 'foo'")
+ instance_eval("#{temp_my_resource} 'foo'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class
@@ -1328,9 +1328,9 @@ describe "Recipe DSL methods" do
# TODO no warning? ick
it "my_resource runs the provider anyway" do
- my_resource = self.my_resource
+ temp_my_resource = my_resource
recipe = converge do
- instance_eval("#{my_resource} 'foo'")
+ instance_eval("#{temp_my_resource} 'foo'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class
@@ -1338,7 +1338,7 @@ describe "Recipe DSL methods" do
context "and another provider supporting :my_resource with supports? true" do
let(:provider_class2) do
- my_resource = self.my_resource
+ temp_my_resource = my_resource
Class.new(BaseThingy::Provider) do
def self.name
"MyProvider2"
@@ -1351,7 +1351,7 @@ describe "Recipe DSL methods" do
def self.called_provides
@called_provides
end
- provides my_resource
+ provides temp_my_resource
def self.supports?(resource, action)
true
end
@@ -1360,9 +1360,9 @@ describe "Recipe DSL methods" do
before { provider_class2 } # make sure the provider class shows up
it "my_resource runs the other provider" do
- my_resource = self.my_resource
+ temp_my_resource = my_resource
recipe = converge do
- instance_eval("#{my_resource} 'foo'")
+ instance_eval("#{temp_my_resource} 'foo'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class2
@@ -1373,10 +1373,10 @@ describe "Recipe DSL methods" do
context "with provides? returning true" do
before do
- my_resource = self.my_resource
+ temp_my_resource = my_resource
provider_class.define_singleton_method(:provides?) do |node, resource|
@called_provides = true
- resource.declared_type == my_resource
+ resource.declared_type == temp_my_resource
end
end
@@ -1386,9 +1386,9 @@ describe "Recipe DSL methods" do
end
it "my_resource calls the provider (and calls provides?), but does not emit a warning" do
- my_resource = self.my_resource
+ temp_my_resource = my_resource
recipe = converge do
- instance_eval("#{my_resource} 'foo'")
+ instance_eval("#{temp_my_resource} 'foo'")
end
expect(recipe.logged_warnings).to eq ""
expect(BaseThingy.created_provider).to eq provider_class
@@ -1399,9 +1399,9 @@ describe "Recipe DSL methods" do
context "that does not call provides :my_resource" do
it "my_resource calls the provider (and calls provides?), and emits a warning" do
Chef::Config[:treat_deprecation_warnings_as_errors] = false
- my_resource = self.my_resource
+ temp_my_resource = my_resource
recipe = converge do
- instance_eval("#{my_resource} 'foo'")
+ instance_eval("#{temp_my_resource} 'foo'")
end
expect(recipe.logged_warnings).to include("WARN: #{provider_class}.provides? returned true when asked if it provides DSL #{my_resource}, but provides :#{my_resource} was never called!")
expect(BaseThingy.created_provider).to eq provider_class
@@ -1412,7 +1412,7 @@ describe "Recipe DSL methods" do
context "with provides? returning false to my_resource" do
before do
- my_resource = self.my_resource
+ temp_my_resource = my_resource
provider_class.define_singleton_method(:provides?) do |node, resource|
@called_provides = true
false
@@ -1425,9 +1425,10 @@ describe "Recipe DSL methods" do
end
it "my_resource fails to find a provider (and calls provides)" do
- my_resource = self.my_resource
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ temp_my_resource = my_resource
expect_converge do
- instance_eval("#{my_resource} 'foo'")
+ instance_eval("#{temp_my_resource} 'foo'")
end.to raise_error(Chef::Exceptions::ProviderNotFound)
expect(provider_class.called_provides).to be_truthy
end
@@ -1435,9 +1436,10 @@ describe "Recipe DSL methods" do
context "that does not provide :my_resource" do
it "my_resource fails to find a provider (and calls provides)" do
- my_resource = self.my_resource
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ temp_my_resource = my_resource
expect_converge do
- instance_eval("#{my_resource} 'foo'")
+ instance_eval("#{temp_my_resource} 'foo'")
end.to raise_error(Chef::Exceptions::ProviderNotFound)
expect(provider_class.called_provides).to be_truthy
end
@@ -1510,6 +1512,7 @@ describe "Recipe DSL methods" do
end
it "looks up the provider in Chef::Provider converting the resource name from snake case to camel case" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
resource = nil
recipe = converge do
resource = lw_resource_with_hw_provider_test_case("blah") {}
diff --git a/spec/integration/recipes/resource_load_spec.rb b/spec/integration/recipes/resource_load_spec.rb
index 954fbf53a4..791b83c23a 100644
--- a/spec/integration/recipes/resource_load_spec.rb
+++ b/spec/integration/recipes/resource_load_spec.rb
@@ -48,7 +48,7 @@ describe "Resource.load_current_value" do
x "loaded #{Namer.incrementing_value} (#{self.class.properties.sort_by { |name, p| name }.
select { |name, p| p.is_set?(self) }.
map { |name, p| "#{name}=#{p.get(self)}" }.
- join(", ") })"
+ join(", ")})"
end
end
@@ -175,7 +175,7 @@ describe "Resource.load_current_value" do
y "loaded_y #{Namer.incrementing_value} (#{self.class.properties.sort_by { |name, p| name }.
select { |name, p| p.is_set?(self) }.
map { |name, p| "#{name}=#{p.get(self)}" }.
- join(", ") })"
+ join(", ")})"
end
end
@@ -193,7 +193,7 @@ describe "Resource.load_current_value" do
y "loaded_y #{Namer.incrementing_value} (#{self.class.properties.sort_by { |name, p| name }.
select { |name, p| p.is_set?(self) }.
map { |name, p| "#{name}=#{p.get(self)}" }.
- join(", ") })"
+ join(", ")})"
end
end
diff --git a/spec/integration/solo/solo_spec.rb b/spec/integration/solo/solo_spec.rb
index e4228a7559..f6cb2e43ef 100644
--- a/spec/integration/solo/solo_spec.rb
+++ b/spec/integration/solo/solo_spec.rb
@@ -4,6 +4,7 @@ require "chef/run_lock"
require "chef/config"
require "timeout"
require "fileutils"
+require "chef/win32/security" if Chef::Platform.windows?
describe "chef-solo" do
include IntegrationSupport
@@ -17,6 +18,55 @@ describe "chef-solo" do
let(:chef_solo) { "ruby bin/chef-solo --legacy-mode --minimal-ohai" }
+ when_the_repository "creates nodes" do
+ let(:nodes_dir) { File.join(@repository_dir, "nodes") }
+ let(:node_file) { Dir[File.join(nodes_dir, "*.json")][0] }
+
+ before do
+ file "config/solo.rb", <<EOM
+chef_repo_path "#{@repository_dir}"
+EOM
+ result = shell_out("ruby bin/chef-solo -c \"#{path_to('config/solo.rb')}\" -l debug", :cwd => chef_dir)
+ result.error!
+ end
+
+ describe "on unix", :unix_only do
+ describe "the nodes directory" do
+ it "has the correct permissions" do
+ expect(File.stat(nodes_dir).mode.to_s(8)[2..5]).to eq("700")
+ end
+ end
+
+ describe "the node file" do
+ it "has the correct permissions" do
+ expect(File.stat(node_file).mode.to_s(8)[2..5]).to eq("0600")
+ end
+ end
+ end
+
+ describe "on windows", :windows_only do
+ let(:read_mask) { Chef::ReservedNames::Win32::API::Security::GENERIC_READ }
+ let(:write_mask) { Chef::ReservedNames::Win32::API::Security::GENERIC_WRITE }
+ let(:execute_mask) { Chef::ReservedNames::Win32::API::Security::GENERIC_EXECUTE }
+
+ describe "the nodes directory" do
+ it "has the correct permissions" do
+ expect(Chef::ReservedNames::Win32::File.file_access_check(nodes_dir, read_mask)).to be(true)
+ expect(Chef::ReservedNames::Win32::File.file_access_check(nodes_dir, write_mask)).to be(true)
+ expect(Chef::ReservedNames::Win32::File.file_access_check(nodes_dir, execute_mask)).to be(true)
+ end
+ end
+
+ describe "the node file" do
+ it "has the correct permissions" do
+ expect(Chef::ReservedNames::Win32::File.file_access_check(node_file, read_mask)).to be(true)
+ expect(Chef::ReservedNames::Win32::File.file_access_check(node_file, write_mask)).to be(true)
+ expect(Chef::ReservedNames::Win32::File.file_access_check(node_file, execute_mask)).to be(false)
+ end
+ end
+ end
+ end
+
when_the_repository "has a cookbook with a basic recipe" do
before do
file "cookbooks/x/metadata.rb", cookbook_x_100_metadata_rb
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 7559e797bc..50ad2a3fb6 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -68,6 +68,8 @@ require "chef/config"
require "chef/chef_fs/file_system_cache"
+require "chef/api_client_v1"
+
if ENV["CHEF_FIPS"] == "1"
Chef::Config.init_openssl
end
@@ -139,6 +141,7 @@ RSpec.configure do |config|
config.filter_run_excluding :not_supported_on_gce => true if gce?
config.filter_run_excluding :not_supported_on_nano => true if windows_nano_server?
config.filter_run_excluding :win2k3_only => true unless windows_win2k3?
+ config.filter_run_excluding :win2012r2_only => true unless windows_2012r2?
config.filter_run_excluding :windows_2008r2_or_later => true unless windows_2008r2_or_later?
config.filter_run_excluding :windows64_only => true unless windows64?
config.filter_run_excluding :windows32_only => true unless windows32?
@@ -149,6 +152,10 @@ RSpec.configure do |config|
config.filter_run_excluding :windows_powershell_no_dsc_only => true unless ! windows_powershell_dsc?
config.filter_run_excluding :windows_domain_joined_only => true unless windows_domain_joined?
config.filter_run_excluding :windows_not_domain_joined_only => true if windows_domain_joined?
+ # We think this line was causing rspec tests to not run on the Jenkins windows
+ # testers. If we ever fix it we should restore it.
+ # config.filter_run_excluding :windows_service_requires_assign_token => true if !STDOUT.isatty && !windows_user_right?("SeAssignPrimaryTokenPrivilege")
+ config.filter_run_excluding :windows_service_requires_assign_token => true
config.filter_run_excluding :solaris_only => true unless solaris?
config.filter_run_excluding :system_windows_service_gem_only => true unless system_windows_service_gem?
config.filter_run_excluding :unix_only => true unless unix?
@@ -215,9 +222,11 @@ RSpec.configure do |config|
end
# raise if anyone commits any test to CI with :focus set on it
- config.before(:example, :focus) do
- raise "This example was committed with `:focus` and should not have been"
- end if ENV["CI"]
+ if ENV["CI"]
+ config.before(:example, :focus) do
+ raise "This example was committed with `:focus` and should not have been"
+ end
+ end
config.before(:suite) do
ARGV.clear
diff --git a/spec/support/chef_helpers.rb b/spec/support/chef_helpers.rb
index d0b5ad0bfd..444e5a30c8 100644
--- a/spec/support/chef_helpers.rb
+++ b/spec/support/chef_helpers.rb
@@ -53,13 +53,11 @@ end
# This is a temporary fix to get tests passing on systems that have no `diff`
# until we can replace shelling out to `diff` with ruby diff-lcs
def has_diff?
- begin
- diff_cmd = Mixlib::ShellOut.new("diff -v")
- diff_cmd.run_command
- true
- rescue Errno::ENOENT
- false
- end
+ diff_cmd = Mixlib::ShellOut.new("diff -v")
+ diff_cmd.run_command
+ true
+rescue Errno::ENOENT
+ false
end
# This is a helper to determine if the ruby in the PATH contains
diff --git a/spec/support/lib/chef/provider/snakeoil.rb b/spec/support/lib/chef/provider/snakeoil.rb
index a42f889e74..f7769ebfc8 100644
--- a/spec/support/lib/chef/provider/snakeoil.rb
+++ b/spec/support/lib/chef/provider/snakeoil.rb
@@ -19,6 +19,7 @@
class Chef
class Provider
class SnakeOil < Chef::Provider
+ provides :cat
def load_current_resource
true
diff --git a/spec/support/lib/chef/resource/cat.rb b/spec/support/lib/chef/resource/cat.rb
index f62db4d2cd..38cbd60f0b 100644
--- a/spec/support/lib/chef/resource/cat.rb
+++ b/spec/support/lib/chef/resource/cat.rb
@@ -19,6 +19,7 @@
class Chef
class Resource
class Cat < Chef::Resource
+ provides :cat
attr_accessor :action
diff --git a/spec/support/lib/chef/resource/one_two_three_four.rb b/spec/support/lib/chef/resource/one_two_three_four.rb
index e46bede0fa..ef03a1133e 100644
--- a/spec/support/lib/chef/resource/one_two_three_four.rb
+++ b/spec/support/lib/chef/resource/one_two_three_four.rb
@@ -19,6 +19,7 @@
class Chef
class Resource
class OneTwoThreeFour < Chef::Resource
+ provides :one_two_three_four
attr_reader :i_can_count
diff --git a/spec/support/lib/chef/resource/openldap_includer.rb b/spec/support/lib/chef/resource/openldap_includer.rb
index 5a7651b10d..356d622e38 100644
--- a/spec/support/lib/chef/resource/openldap_includer.rb
+++ b/spec/support/lib/chef/resource/openldap_includer.rb
@@ -19,6 +19,8 @@
class Chef
class Resource
class OpenldapIncluder < Chef::Resource::LWRPBase
+ provides :openldap_includer
+
allowed_actions :run
default_action :run
end
diff --git a/spec/support/lib/chef/resource/with_state.rb b/spec/support/lib/chef/resource/with_state.rb
index f256bf4984..444191da62 100644
--- a/spec/support/lib/chef/resource/with_state.rb
+++ b/spec/support/lib/chef/resource/with_state.rb
@@ -22,6 +22,8 @@ require "chef/json_compat"
class Chef
class Resource
class WithState < Chef::Resource
+ provides :with_state
+
attr_accessor :state
end
end
diff --git a/spec/support/lib/chef/resource/zen_master.rb b/spec/support/lib/chef/resource/zen_master.rb
index f5137c18ec..99d761c8cf 100644
--- a/spec/support/lib/chef/resource/zen_master.rb
+++ b/spec/support/lib/chef/resource/zen_master.rb
@@ -22,6 +22,7 @@ require "chef/json_compat"
class Chef
class Resource
class ZenMaster < Chef::Resource
+ provides :zen_master
allowed_actions :win, :score
attr_reader :peace
diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb
index 62b262b8a7..fb50ee2298 100644
--- a/spec/support/platform_helpers.rb
+++ b/spec/support/platform_helpers.rb
@@ -50,23 +50,31 @@ end
def windows_win2k3?
return false unless windows?
- wmi = WmiLite::Wmi.new
- host = wmi.first_of("Win32_OperatingSystem")
- (host["version"] && host["version"].start_with?("5.2"))
+ (host_version && host_version.start_with?("5.2"))
end
def windows_2008r2_or_later?
return false unless windows?
- wmi = WmiLite::Wmi.new
- host = wmi.first_of("Win32_OperatingSystem")
- version = host["version"]
- return false unless version
- components = version.split(".").map do |component|
+ return false unless host_version
+ components = host_version.split(".").map do |component|
component.to_i
end
components.length >= 2 && components[0] >= 6 && components[1] >= 1
end
+def windows_2012r2?
+ return false unless windows?
+ (host_version && host_version.start_with?("6.3"))
+end
+
+def host_version
+ @host_version ||= begin
+ wmi = WmiLite::Wmi.new
+ host = wmi.first_of("Win32_OperatingSystem")
+ host["version"]
+ end
+end
+
def windows_powershell_dsc?
return false unless windows?
supports_dsc = false
@@ -84,6 +92,12 @@ def windows_nano_server?
Chef::Platform.windows_nano_server?
end
+def windows_user_right?(right)
+ return false unless windows?
+ require "chef/win32/security"
+ Chef::ReservedNames::Win32::Security.get_account_right(ENV["USERNAME"]).include?(right)
+end
+
def mac_osx_106?
if File.exists? "/usr/bin/sw_vers"
result = ShellHelpers.shell_out("/usr/bin/sw_vers")
diff --git a/spec/support/platforms/prof/gc.rb b/spec/support/platforms/prof/gc.rb
index 2e1b45c294..b494ff9646 100644
--- a/spec/support/platforms/prof/gc.rb
+++ b/spec/support/platforms/prof/gc.rb
@@ -35,12 +35,10 @@ module RSpec
end
def working_set_size
- begin
- ::GC.start
- ::GC::Profiler.result.scan(LINE_PATTERN)[-1][2].to_i if ::GC::Profiler.enabled?
- ensure
- ::GC::Profiler.clear
- end
+ ::GC.start
+ ::GC::Profiler.result.scan(LINE_PATTERN)[-1][2].to_i if ::GC::Profiler.enabled?
+ ensure
+ ::GC::Profiler.clear
end
def handle_count
diff --git a/spec/support/shared/context/client.rb b/spec/support/shared/context/client.rb
index 295bd6ce5f..c65650e6b1 100644
--- a/spec/support/shared/context/client.rb
+++ b/spec/support/shared/context/client.rb
@@ -95,7 +95,7 @@ shared_context "a client run" do
def stub_for_data_collector_init
expect(Chef::ServerAPI).to receive(:new).
- with(Chef::Config[:data_collector][:server_url]).
+ with(Chef::Config[:data_collector][:server_url], validate_utf8: false).
exactly(:once).
and_return(http_data_collector)
end
diff --git a/spec/support/shared/functional/execute_resource.rb b/spec/support/shared/functional/execute_resource.rb
new file mode 100644
index 0000000000..4f7cea1cd1
--- /dev/null
+++ b/spec/support/shared/functional/execute_resource.rb
@@ -0,0 +1,150 @@
+#
+# Author:: Adam Edwards (<adamed@chef.io>)
+# Copyright:: Copyright (c) 2015 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.
+#
+
+shared_context "a non-admin Windows user" do
+ include Chef::Mixin::ShellOut
+
+ let(:windows_nonadmin_user_domain) { ENV["COMPUTERNAME"] }
+ let(:windows_nonadmin_user_qualified) { "#{windows_nonadmin_user_domain}\\#{windows_nonadmin_user}" }
+ let(:temp_profile_path) { "#{ENV['USERPROFILE']}\\..\\cheftesttempuser" }
+ before do
+ shell_out!("net.exe user /delete #{windows_nonadmin_user}", returns: [0, 2])
+
+ # Supply a profile path when creating a user to avoid an apparent Windows bug where deleting
+ # the user actually creates the profile when it did not immediately exist before executing
+ # net user /delete! For some reason, specifying an explicit path ensures that the path
+ # profile doesn't get created at deletion.
+ shell_out!("net.exe user /add #{windows_nonadmin_user} \"#{windows_nonadmin_user_password}\" /profilepath:#{temp_profile_path}")
+ end
+
+ after do
+ shell_out!("net.exe user /delete #{windows_nonadmin_user}", returns: [0, 2])
+ end
+end
+
+shared_context "alternate user identity" do
+ let(:windows_alternate_user) { "chef%02d%02d%02d" % [Time.now.year % 100, Time.now.month, Time.now.day] }
+ let(:windows_alternate_user_password) { "lj28;fx3T!x,2" }
+ let(:windows_alternate_user_qualified) { "#{ENV['COMPUTERNAME']}\\#{windows_alternate_user}" }
+
+ let(:windows_nonadmin_user) { windows_alternate_user }
+ let(:windows_nonadmin_user_password) { windows_alternate_user_password }
+
+ include_context "a non-admin Windows user"
+end
+
+shared_context "a command that can be executed as an alternate user" do
+ include_context "alternate user identity"
+
+ let(:script_output_dir) { Dir.mktmpdir }
+ let(:script_output_path) { File.join(script_output_dir, make_tmpname("chef_execute_identity_test")) }
+ let(:script_output) { File.read(script_output_path) }
+
+ include Chef::Mixin::ShellOut
+
+ before do
+ shell_out!("icacls \"#{script_output_dir.gsub(/\//, '\\')}\" /grant \"authenticated users:(F)\"")
+ end
+
+ after do
+ File.delete(script_output_path) if File.exists?(script_output_path)
+ Dir.rmdir(script_output_dir) if Dir.exists?(script_output_dir)
+ end
+end
+
+shared_examples_for "an execute resource that supports alternate user identity" do
+ context "when running on Windows", :windows_only, :windows_service_requires_assign_token do
+
+ include_context "a command that can be executed as an alternate user"
+
+ let(:windows_current_user) { ENV["USERNAME"] }
+ let(:windows_current_user_qualified) { "#{ENV['USERDOMAIN'] || ENV['COMPUTERNAME']}\\#{windows_current_user}" }
+ let(:resource_identity_command) { "powershell.exe -noprofile -command \"import-module microsoft.powershell.utility;([Security.Principal.WindowsPrincipal]([Security.Principal.WindowsIdentity]::GetCurrent())).identity.name | out-file -encoding ASCII '#{script_output_path}'\"" }
+
+ let(:execute_resource) do
+ resource.user(windows_alternate_user)
+ resource.password(windows_alternate_user_password)
+ resource.send(resource_command_property, resource_identity_command)
+ resource
+ end
+
+ it "executes the process as an alternate user" do
+ expect(windows_current_user.length).to be > 0
+ expect { execute_resource.run_action(:run) }.not_to raise_error
+ expect(script_output.chomp.length).to be > 0
+ expect(script_output.chomp.downcase).to eq(windows_alternate_user_qualified.downcase)
+ expect(script_output.chomp.downcase).not_to eq(windows_current_user.downcase)
+ expect(script_output.chomp.downcase).not_to eq(windows_current_user_qualified.downcase)
+ end
+
+ let(:windows_alternate_user_password_invalid) { "#{windows_alternate_user_password}x" }
+
+ it "raises an exception if the user's password is invalid" do
+ execute_resource.password(windows_alternate_user_password_invalid)
+ expect { execute_resource.run_action(:run) }.to raise_error(SystemCallError)
+ end
+ end
+end
+
+shared_examples_for "a resource with a guard specifying an alternate user identity" do
+ context "when running on Windows", :windows_only, :windows_service_requires_assign_token do
+ include_context "alternate user identity"
+
+ let(:resource_command_property) { :command }
+
+ let(:powershell_equal_to_alternate_user) { "-eq" }
+ let(:powershell_not_equal_to_alternate_user) { "-ne" }
+ let(:guard_identity_command) { "powershell.exe -noprofile -command \"import-module microsoft.powershell.utility;exit @(392,0)[[int32](([Security.Principal.WindowsPrincipal]([Security.Principal.WindowsIdentity]::GetCurrent())).Identity.Name #{comparison_to_alternate_user} '#{windows_alternate_user_qualified}')]\"" }
+
+ before do
+ resource.guard_interpreter(guard_interpreter_resource)
+ end
+
+ context "when the guard expression is true if the user is alternate and false otherwise" do
+ let(:comparison_to_alternate_user) { powershell_equal_to_alternate_user }
+
+ it "causes the resource to be updated for only_if" do
+ resource.only_if(guard_identity_command, { user: windows_alternate_user, password: windows_alternate_user_password })
+ resource.run_action(:run)
+ expect(resource).to be_updated_by_last_action
+ end
+
+ it "causes the resource to not be updated for not_if" do
+ resource.not_if(guard_identity_command, { user: windows_alternate_user, password: windows_alternate_user_password })
+ resource.run_action(:run)
+ expect(resource).not_to be_updated_by_last_action
+ end
+ end
+
+ context "when the guard expression is false if the user is alternate and true otherwise" do
+ let(:comparison_to_alternate_user) { powershell_not_equal_to_alternate_user }
+
+ it "causes the resource not to be updated for only_if" do
+ resource.only_if(guard_identity_command, { user: windows_alternate_user, password: windows_alternate_user_password })
+ resource.run_action(:run)
+ expect(resource).not_to be_updated_by_last_action
+ end
+
+ it "causes the resource to be updated for not_if" do
+ resource.not_if(guard_identity_command, { user: windows_alternate_user, password: windows_alternate_user_password })
+ resource.run_action(:run)
+ expect(resource).to be_updated_by_last_action
+ end
+ end
+ end
+end
diff --git a/spec/support/shared/functional/windows_script.rb b/spec/support/shared/functional/windows_script.rb
index 908198add4..e5ac0741bd 100644
--- a/spec/support/shared/functional/windows_script.rb
+++ b/spec/support/shared/functional/windows_script.rb
@@ -46,10 +46,6 @@ shared_context Chef::Resource::WindowsScript do
File.delete(script_output_path) if File.exists?(script_output_path)
end
- let!(:resource) do
- Chef::Resource::WindowsScript::Batch.new("Batch resource functional test", @run_context)
- end
-
shared_examples_for "a script resource with architecture attribute" do
context "with the given architecture attribute value" do
let(:expected_architecture) do
@@ -125,6 +121,55 @@ shared_context Chef::Resource::WindowsScript do
end
shared_examples_for "a Windows script running on Windows" do
+ shared_examples_for "a script that cannot be accessed by other users if they are not administrators" do
+ include Chef::Mixin::ShellOut
+
+ let(:script_provider) { resource.provider_for_action(:run) }
+ let(:script_file) { script_provider.script_file }
+ let(:script_file_path) { script_file.to_path }
+
+ let(:read_access_denied_command) { "::File.read('#{script_file_path}')" }
+ let(:modify_access_denied_command) { "::File.write('#{script_file_path}', 'stuff')" }
+ let(:delete_access_denied_command) { "::File.delete('#{script_file_path}')" }
+ let(:access_denied_sentinel) { 7334 }
+ let(:access_allowed_sentinel) { 1586 }
+ let(:access_command_invalid) { 0 }
+
+ let(:ruby_interpreter_path) { RbConfig.ruby }
+ let(:ruby_command_template) { "require 'FileUtils';status = 0;begin; #{ruby_access_command};rescue Exception => e; puts e; status = e.class == Errno::EACCES ? #{access_denied_sentinel} : #{access_allowed_sentinel};end;exit status" }
+ let(:command_template) { "set BUNDLE_GEMFILE=&#{ruby_interpreter_path} -e \"#{ruby_command_template}\"" }
+ let(:access_command) { command_template }
+
+ before do
+ expect(script_provider).to receive(:unlink_script_file)
+ resource.code("echo hi")
+ script_provider.action_run
+ end
+
+ after do
+ script_file.close! if script_file
+ ::File.delete(script_file.to_path) if script_file && ::File.exists?(script_file.to_path)
+ end
+
+ include_context "alternate user identity"
+
+ shared_examples_for "a script whose file system location cannot be accessed by other non-admin users" do
+ let(:ruby_access_command) { file_access_command }
+ it "generates a script in the local file system that prevents read access to other non-admin users" do
+ shell_out!(access_command, { user: windows_nonadmin_user, password: windows_nonadmin_user_password, returns: [access_denied_sentinel] })
+ end
+ end
+
+ context "when a different non-admin user attempts write (modify) to access the script" do
+ let(:file_access_command) { modify_access_denied_command }
+ it_behaves_like "a script whose file system location cannot be accessed by other non-admin users"
+ end
+
+ context "when a different non-admin user attempts write (delete) to access the script" do
+ let(:file_access_command) { delete_access_denied_command }
+ it_behaves_like "a script whose file system location cannot be accessed by other non-admin users"
+ end
+ end
describe "when the run action is invoked on Windows" do
it "executes the script code" do
@@ -132,6 +177,21 @@ shared_context Chef::Resource::WindowsScript do
resource.returns(0)
resource.run_action(:run)
end
+
+ context "the script is executed with the identity of the current user", :windows_service_requires_assign_token do
+ it_behaves_like "a script that cannot be accessed by other users if they are not administrators"
+ end
+
+ context "the script is executed with an alternate non-admin identity", :windows_service_requires_assign_token do
+ include_context "alternate user identity"
+
+ before do
+ resource.user(windows_alternate_user)
+ resource.password(windows_alternate_user_password)
+ end
+
+ it_behaves_like "a script that cannot be accessed by other users if they are not administrators"
+ end
end
context "when $env:TMP has a space" do
@@ -165,6 +225,11 @@ shared_context Chef::Resource::WindowsScript do
expect(resource.class).to receive(:new).and_call_original
expect(resource.should_skip?(:run)).to be_falsey
end
+
+ context "when this resource is used as a guard and it is specified with an alternate user identity" do
+ let(:guard_interpreter_resource) { resource.resource_name }
+ it_behaves_like "a resource with a guard specifying an alternate user identity"
+ end
end
context "when the architecture attribute is not set" do
@@ -181,6 +246,11 @@ shared_context Chef::Resource::WindowsScript do
let(:resource_architecture) { :x86_64 }
it_behaves_like "a script resource with architecture attribute"
end
+
+ describe "when running with an alternate user identity" do
+ let(:resource_command_property) { :code }
+ it_behaves_like "an execute resource that supports alternate user identity"
+ end
end
def get_windows_script_output(suffix = "")
diff --git a/spec/support/shared/unit/execute_resource.rb b/spec/support/shared/unit/execute_resource.rb
index e33247da42..ab6ed2b86b 100644
--- a/spec/support/shared/unit/execute_resource.rb
+++ b/spec/support/shared/unit/execute_resource.rb
@@ -106,6 +106,16 @@ shared_examples_for "an execute resource" do
expect(@resource.user).to eql(1)
end
+ it "should accept a string for the domain" do
+ @resource.domain "mothership"
+ expect(@resource.domain).to eql("mothership")
+ end
+
+ it "should accept a string for the password" do
+ @resource.password "we.funk!"
+ expect(@resource.password).to eql("we.funk!")
+ end
+
it "should accept a string for creates" do
@resource.creates "something"
expect(@resource.creates).to eql("something")
@@ -116,6 +126,33 @@ shared_examples_for "an execute resource" do
expect(@resource.live_stream).to be true
end
+ describe "the resource's sensitive attribute" do
+ it "should be false by default" do
+ expect(@resource.sensitive).to eq(false)
+ end
+
+ it "should be true if set to true" do
+ expect(@resource.sensitive).to eq(false)
+ @resource.sensitive true
+ expect(@resource.sensitive).to eq(true)
+ end
+
+ it "should be true if the password is non-nil" do
+ expect(@resource.sensitive).to eq(false)
+ @resource.password("we.funk!")
+ expect(@resource.sensitive).to eq(true)
+ end
+
+ it "should be true if the password is non-nil but the value is explicitly set to false" do
+ expect(@resource.sensitive).to eq(false)
+ @resource.password("we.funk!")
+ expect(@resource.sensitive).to eq(true)
+ @resource.sensitive false
+ expect(@resource.sensitive).to eq(true)
+ end
+
+ end
+
describe "when it has cwd, environment, group, path, return value, and a user" do
before do
@resource.command("grep")
diff --git a/spec/support/shared/unit/provider/file.rb b/spec/support/shared/unit/provider/file.rb
index 394fdaa02f..b58159fcc9 100644
--- a/spec/support/shared/unit/provider/file.rb
+++ b/spec/support/shared/unit/provider/file.rb
@@ -683,6 +683,16 @@ shared_examples_for Chef::Provider::File do
end
end
+ context "in why run mode" do
+ before { Chef::Config[:why_run] = true }
+ after { Chef::Config[:why_run] = false }
+
+ it "does not modify new_resource" do
+ setup_missing_file
+ expect(provider).not_to receive(:load_resource_attributes_from_file).with(provider.new_resource)
+ provider.run_action(:create)
+ end
+ end
end
context "action delete" do
diff --git a/spec/unit/application/exit_code_spec.rb b/spec/unit/application/exit_code_spec.rb
index 59ee400c23..5abf19fc02 100644
--- a/spec/unit/application/exit_code_spec.rb
+++ b/spec/unit/application/exit_code_spec.rb
@@ -77,11 +77,7 @@ describe Chef::Application::ExitCode do
end
it "writes a deprecation warning" do
- warn = "Chef RFC 062 (https://github.com/chef/chef-rfc/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."
- expect(Chef).to receive(:log_deprecation).with(warn)
+ expect(Chef).to receive(:deprecated).with(:exit_code, /^Chef RFC 062/)
expect(exit_codes.normalize_exit_code(151)).to eq(151)
end
@@ -118,11 +114,7 @@ describe Chef::Application::ExitCode do
end
it "does not write a deprecation warning" do
- warn = "Chef RFC 062 (https://github.com/chef/chef-rfc/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."
- expect(Chef).not_to receive(:log_deprecation).with(warn)
+ expect(Chef).not_to receive(:deprecated).with(:exit_code, /^Chef RFC 062/)
expect(exit_codes.normalize_exit_code(151)).to eq(151)
end
@@ -163,11 +155,7 @@ describe Chef::Application::ExitCode do
end
it "does write a deprecation warning" do
- warn = "Chef RFC 062 (https://github.com/chef/chef-rfc/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."
- expect(Chef).to receive(:log_deprecation).with(warn)
+ expect(Chef).to receive(:deprecated).with(:exit_code, /^Chef RFC 062/)
expect(exit_codes.normalize_exit_code(151)).to eq(1)
end
diff --git a/spec/unit/cookbook/cookbook_version_loader_spec.rb b/spec/unit/cookbook/cookbook_version_loader_spec.rb
index 87d0f1e032..786e17f35b 100644
--- a/spec/unit/cookbook/cookbook_version_loader_spec.rb
+++ b/spec/unit/cookbook/cookbook_version_loader_spec.rb
@@ -104,6 +104,15 @@ describe Chef::Cookbook::CookbookVersionLoader do
end
+ context "when a cookbook's metadata.rb does not parse but the compiled metadata.json is present" do
+ let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "prefer_metadata_json") }
+
+ it "reads the cookbook" do
+ expect(loaded_cookbook.metadata.name.to_s).to eq("prefer_metadata_json")
+ expect(loaded_cookbook.metadata.version.to_s).to eq("1.2.3")
+ end
+ end
+
context "when the given path is not actually a cookbook" do
let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks/NOTHING_HERE_FOLKS") }
diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb
index 389f02501a..d1117127f1 100644
--- a/spec/unit/cookbook/metadata_spec.rb
+++ b/spec/unit/cookbook/metadata_spec.rb
@@ -206,7 +206,7 @@ describe Chef::Cookbook::Metadata do
:issues_url => "http://example.com/issues",
:privacy => true,
}
- params.sort { |a, b| a.to_s <=> b.to_s }.each do |field, field_value|
+ params.sort_by(&:to_s).each do |field, field_value|
describe field do
it "should be set-able via #{field}" do
expect(metadata.send(field, field_value)).to eql(field_value)
@@ -240,7 +240,7 @@ describe Chef::Cookbook::Metadata do
:provides => [ :providing, "foo::bar", "<= 0.2" ],
:replaces => [ :replacing, "foo::bar", "= 0.2.1" ],
}
- dep_types.sort { |a, b| a.to_s <=> b.to_s }.each do |dep, dep_args|
+ dep_types.sort_by(&:to_s).each do |dep, dep_args|
check_with = dep_args.shift
describe dep do
it "should be set-able via #{dep}" do
@@ -261,7 +261,7 @@ describe Chef::Cookbook::Metadata do
:provides => [ :providing, "foo::bar", "<=0.2", "<= 0.2" ],
:replaces => [ :replacing, "foo::bar", "=0.2.1", "= 0.2.1" ],
}
- dep_types.sort { |a, b| a.to_s <=> b.to_s }.each do |dep, dep_args|
+ dep_types.sort_by(&:to_s).each do |dep, dep_args|
check_with = dep_args.shift
normalized_version = dep_args.pop
describe dep do
diff --git a/spec/unit/cookbook/syntax_check_spec.rb b/spec/unit/cookbook/syntax_check_spec.rb
index 228f695106..aa6fe49eb9 100644
--- a/spec/unit/cookbook/syntax_check_spec.rb
+++ b/spec/unit/cookbook/syntax_check_spec.rb
@@ -25,6 +25,7 @@ describe Chef::Cookbook::SyntaxCheck do
end
let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks", "openldap") }
+ let(:unsafe_cookbook_path) { 'C:\AGENT-HOME\xml-data\build-dir\76808194-76906499\artifact\cookbooks/java' }
let(:syntax_check) { Chef::Cookbook::SyntaxCheck.new(cookbook_path) }
let(:open_ldap_cookbook_files) do
@@ -53,7 +54,7 @@ describe Chef::Cookbook::SyntaxCheck do
@recipes = %w{default.rb gigantor.rb one.rb return.rb}.map { |f| File.join(cookbook_path, "recipes", f) }
@spec_files = [ File.join(cookbook_path, "spec", "spec_helper.rb") ]
@ruby_files = @attr_files + @libr_files + @defn_files + @recipes + @spec_files + [File.join(cookbook_path, "metadata.rb")]
- basenames = %w{ helpers_via_partial_test.erb
+ @basenames = %w{ helpers_via_partial_test.erb
helper_test.erb
helpers.erb
openldap_stuff.conf.erb
@@ -64,7 +65,7 @@ describe Chef::Cookbook::SyntaxCheck do
some_windows_line_endings.erb
all_windows_line_endings.erb
no_windows_line_endings.erb }
- @template_files = basenames.map { |f| File.join(cookbook_path, "templates", "default", f) }
+ @template_files = @basenames.map { |f| File.join(cookbook_path, "templates", "default", f) }
end
after do
@@ -94,6 +95,11 @@ describe Chef::Cookbook::SyntaxCheck do
end
end
+ it "safely handles a path containing control characters" do
+ syntax_check = Chef::Cookbook::SyntaxCheck.new(unsafe_cookbook_path)
+ expect { syntax_check.remove_uninteresting_ruby_files(@basenames) }.not_to raise_error
+ end
+
describe "when first created" do
it "has the path to the cookbook to syntax check" do
expect(syntax_check.cookbook_path).to eq(cookbook_path)
diff --git a/spec/unit/data_collector/messages/helpers_spec.rb b/spec/unit/data_collector/messages/helpers_spec.rb
index b0d9f4d09d..a241bda699 100644
--- a/spec/unit/data_collector/messages/helpers_spec.rb
+++ b/spec/unit/data_collector/messages/helpers_spec.rb
@@ -72,6 +72,13 @@ describe Chef::DataCollector::Messages::Helpers do
expect(TestMessage.chef_server_organization).to eq("unknown_organization")
end
end
+
+ context "when the organization in the URL contains hyphens" do
+ it "returns the full org name" do
+ Chef::Config[:chef_server_url] = "http://mycompany.com/organizations/myorg-test"
+ expect(TestMessage.chef_server_organization).to eq("myorg-test")
+ end
+ end
end
describe "#collector_source" do
diff --git a/spec/unit/data_collector_spec.rb b/spec/unit/data_collector_spec.rb
index b3e2d931a7..f3f7ffb30f 100644
--- a/spec/unit/data_collector_spec.rb
+++ b/spec/unit/data_collector_spec.rb
@@ -371,12 +371,10 @@ describe Chef::DataCollector::Reporter do
end
context "when resource is not a nested resource" do
- it "creates the resource report and stores it as the current one" do
+ it "initializes the resource report" do
allow(reporter).to receive(:nested_resource?).and_return(false)
- expect(reporter).to receive(:create_resource_report)
+ expect(reporter).to receive(:initialize_resource_report_if_needed)
.with(new_resource, action, current_resource)
- .and_return(resource_report)
- expect(reporter).to receive(:update_current_resource_report).with(resource_report)
reporter.resource_current_state_loaded(new_resource, action, current_resource)
end
end
@@ -418,7 +416,6 @@ describe Chef::DataCollector::Reporter do
before do
allow(reporter).to receive(:nested_resource?)
- allow(reporter).to receive(:create_resource_report).and_return(resource_report)
allow(resource_report).to receive(:skipped)
end
@@ -431,17 +428,10 @@ describe Chef::DataCollector::Reporter do
end
context "when the resource is not a nested resource" do
- it "creates the resource report and stores it as the current one" do
+ it "initializes the resource report and marks it as skipped" do
allow(reporter).to receive(:nested_resource?).and_return(false)
- expect(reporter).to receive(:create_resource_report)
- .with(new_resource, action)
- .and_return(resource_report)
- expect(reporter).to receive(:update_current_resource_report).with(resource_report)
- reporter.resource_skipped(new_resource, action, conditional)
- end
-
- it "marks the resource report as skipped" do
- allow(reporter).to receive(:nested_resource?).with(new_resource).and_return(false)
+ allow(reporter).to receive(:current_resource_report).and_return(resource_report)
+ expect(reporter).to receive(:initialize_resource_report_if_needed).with(new_resource, action)
expect(resource_report).to receive(:skipped).with(conditional)
reporter.resource_skipped(new_resource, action, conditional)
end
@@ -548,7 +538,7 @@ describe Chef::DataCollector::Reporter do
end
it "nils out the current resource report" do
- expect(reporter).to receive(:update_current_resource_report).with(nil)
+ expect(reporter).to receive(:clear_current_resource_report)
reporter.resource_completed(new_resource)
end
end
@@ -692,4 +682,60 @@ describe Chef::DataCollector::Reporter do
end
end
end
+
+ describe "#detect_unprocessed_resources" do
+ context "when resources do not override core methods" do
+ it "adds resource reports for any resources that have not yet been processed" do
+ resource_a = Chef::Resource::Service.new("processed service")
+ resource_b = Chef::Resource::Service.new("unprocessed service")
+
+ resource_a.action = [ :enable, :start ]
+ resource_b.action = :start
+
+ run_context = Chef::RunContext.new(Chef::Node.new, Chef::CookbookCollection.new, nil)
+ run_context.resource_collection.insert(resource_a)
+ run_context.resource_collection.insert(resource_b)
+
+ allow(reporter).to receive(:run_context).and_return(run_context)
+
+ # process the actions for resource_a, but not resource_b
+ reporter.resource_up_to_date(resource_a, :enable)
+ reporter.resource_completed(resource_a)
+ reporter.resource_up_to_date(resource_a, :start)
+ reporter.resource_completed(resource_a)
+ expect(reporter.all_resource_reports.size).to eq(2)
+
+ # detect unprocessed resources, which should find that resource_b has not yet been processed
+ reporter.send(:detect_unprocessed_resources)
+ expect(reporter.all_resource_reports.size).to eq(3)
+ end
+ end
+
+ context "when a resource overrides a core method, such as #hash" do
+ it "does not raise an exception" do
+ resource_a = Chef::Resource::Service.new("processed service")
+ resource_b = Chef::Resource::Service.new("unprocessed service")
+
+ resource_a.action = :start
+ resource_b.action = :start
+
+ run_context = Chef::RunContext.new(Chef::Node.new, Chef::CookbookCollection.new, nil)
+ run_context.resource_collection.insert(resource_a)
+ run_context.resource_collection.insert(resource_b)
+
+ allow(reporter).to receive(:run_context).and_return(run_context)
+
+ # override the #hash method on resource_a to return a String instead of
+ # a Fixnum. Without the fix in chef/chef#5604, this would raise an
+ # exception when getting added to the Set/Hash.
+ resource_a.define_singleton_method(:hash) { "a string" }
+
+ # process the actions for resource_a, but not resource_b
+ reporter.resource_up_to_date(resource_a, :start)
+ reporter.resource_completed(resource_a)
+
+ expect { reporter.send(:detect_unprocessed_resources) }.not_to raise_error
+ end
+ end
+ end
end
diff --git a/spec/unit/decorator/lazy_spec.rb b/spec/unit/decorator/lazy_spec.rb
index 4ea8301b63..46c8955ae8 100644
--- a/spec/unit/decorator/lazy_spec.rb
+++ b/spec/unit/decorator/lazy_spec.rb
@@ -21,7 +21,7 @@ require "spec_helper"
describe Chef::Decorator::Lazy do
let(:decorator) do
@a = 0
- Chef::Decorator::Lazy.new { @a = @a + 1 }
+ Chef::Decorator::Lazy.new { @a += 1 }
end
it "decorates an object" do
diff --git a/spec/unit/deprecated_spec.rb b/spec/unit/deprecated_spec.rb
new file mode 100644
index 0000000000..9be792ab20
--- /dev/null
+++ b/spec/unit/deprecated_spec.rb
@@ -0,0 +1,59 @@
+#
+# Copyright:: Copyright 2013-2016, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+require "chef/deprecated"
+
+describe Chef::Deprecated do
+ class TestDeprecation < Chef::Deprecated::Base
+ def id; 999; end
+
+ def target; "test.html"; end
+
+ def link; "#{Chef::Deprecated::Base::BASE_URL}test.html"; end
+ end
+
+ context "loading a deprecation class" do
+ it "loads the correct class" do
+ expect(Chef::Deprecated.create(:test_deprecation)).to be_an_instance_of(Chef::Deprecated::TestDeprecation)
+ end
+
+ it "optionally sets a message" do
+ deprecation = Chef::Deprecated.create(:test_deprecation, "A test message")
+ expect(deprecation.message).to eql("A test message")
+ end
+
+ it "optionally sets the location" do
+ deprecation = Chef::Deprecated.create(:test_deprecation, nil, "A test location")
+ expect(deprecation.location).to eql("A test location")
+ end
+ end
+
+ context "formatting deprecation warnings" do
+ let(:base_url) { Chef::Deprecated::Base::BASE_URL }
+ let(:message) { "A test message" }
+ let(:location) { "the location" }
+
+ it "displays the full URL" do
+ expect(Chef::Deprecated::TestDeprecation.new().url).to eql("#{base_url}test.html")
+ end
+
+ it "formats a complete deprecation message" do
+ expect(Chef::Deprecated::TestDeprecation.new(message, location).inspect).to eql("#{message} (CHEF-999)#{location}.\nhttps://docs.chef.io/deprecations_test.html")
+ end
+ end
+end
diff --git a/spec/unit/deprecation_spec.rb b/spec/unit/deprecation_spec.rb
index af8e34850b..41c1724e5b 100644
--- a/spec/unit/deprecation_spec.rb
+++ b/spec/unit/deprecation_spec.rb
@@ -65,15 +65,8 @@ describe Chef::Deprecation do
end
context "deprecation warning messages" do
- RSpec::Matchers.define_negated_matcher :a_non_empty_array, :be_empty
-
it "should be enabled for deprecated methods" do
- expect(Chef::Log).to receive(:warn).with(a_non_empty_array)
- TestClass.new.deprecated_method(10)
- end
-
- it "should contain stack trace" do
- expect(Chef::Log).to receive(:warn).with(a_string_including(".rb"))
+ expect(Chef).to receive(:deprecated).with(:internal_api, /Method.*of 'TestClass'/)
TestClass.new.deprecated_method(10)
end
end
diff --git a/spec/unit/environment_spec.rb b/spec/unit/environment_spec.rb
index 63c96ad93e..3daae16749 100644
--- a/spec/unit/environment_spec.rb
+++ b/spec/unit/environment_spec.rb
@@ -295,7 +295,7 @@ describe Chef::Environment do
Chef::Config[:solo_legacy_mode] = false
end
- it "should raise and exception" do
+ it "should raise an exception" do
expect do
Chef::Environment.validate_cookbook_version("= 1.2.3.4")
end.to raise_error Chef::Exceptions::IllegalVersionConstraint,
diff --git a/spec/unit/handler_spec.rb b/spec/unit/handler_spec.rb
index a56645fa78..09dd99d1ee 100644
--- a/spec/unit/handler_spec.rb
+++ b/spec/unit/handler_spec.rb
@@ -37,7 +37,7 @@ describe Chef::Handler do
@run_status.exception = @exception
@run_context = Chef::RunContext.new(@node, {}, @events)
@all_resources = [Chef::Resource::Cat.new("lolz"), Chef::Resource::ZenMaster.new("tzu")]
- @all_resources.first.updated = true
+ @all_resources.first.updated_by_last_action true
@run_context.resource_collection.all_resources.replace(@all_resources)
@run_status.run_context = @run_context
@start_time = Time.now
@@ -118,7 +118,7 @@ describe Chef::Handler do
before do
@run_context = Chef::RunContext.new(@node, {}, @events)
@all_resources = [Chef::Resource::Cat.new("foo"), Chef::Resource::ZenMaster.new("moo")]
- @all_resources.first.updated = true
+ @all_resources.first.updated_by_last_action true
@run_context.resource_collection.all_resources.replace(@all_resources)
@run_status.run_context = @run_context
@start_time = Time.now
diff --git a/spec/unit/http/api_versions_spec.rb b/spec/unit/http/api_versions_spec.rb
new file mode 100644
index 0000000000..79c97a1b69
--- /dev/null
+++ b/spec/unit/http/api_versions_spec.rb
@@ -0,0 +1,69 @@
+#
+# 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"
+
+describe Chef::HTTP::APIVersions do
+ class TestVersionClient < Chef::HTTP
+ use Chef::HTTP::APIVersions
+ end
+
+ before do
+ Chef::ServerAPIVersions.instance.reset!
+ end
+
+ let(:method) { "GET" }
+ let(:url) { "http://dummy.com" }
+ let(:headers) { {} }
+ let(:data) { false }
+
+ let(:request) {}
+ let(:return_value) { "200" }
+
+ # Test Variables
+ let(:response_body) { "Thanks for checking in." }
+ let(:response_headers) do
+ {
+ "x-ops-server-api-version" => { "min_version" => 0, "max_version" => 2 },
+ }
+ end
+
+ let(:response) do
+ m = double("HttpResponse", :body => response_body)
+ allow(m).to receive(:key?).with("x-ops-server-api-version").and_return(true)
+ allow(m).to receive(:[]) do |key|
+ response_headers[key]
+ end
+
+ m
+ end
+
+ let(:middleware) do
+ client = TestVersionClient.new(url)
+ client.middlewares[0]
+ end
+
+ def run_api_version_handler
+ middleware.handle_request(method, url, headers, data)
+ middleware.handle_response(response, request, return_value)
+ end
+
+ it "correctly stores server api versions" do
+ run_api_version_handler
+ expect(Chef::ServerAPIVersions.instance.min_server_version).to eq(0)
+ end
+end
diff --git a/spec/unit/knife/client_delete_spec.rb b/spec/unit/knife/client_delete_spec.rb
index 82ef902e09..f20b25f5e6 100644
--- a/spec/unit/knife/client_delete_spec.rb
+++ b/spec/unit/knife/client_delete_spec.rb
@@ -34,6 +34,22 @@ describe Chef::Knife::ClientDelete do
@knife.run
end
+ context "receives multiple clients" do
+ let(:clients) { %w{ "adam", "ben", "charlie" } }
+
+ before(:each) do
+ @knife.name_args = clients
+ end
+
+ it "deletes all clients" do
+ clients.each do |client|
+ expect(@knife).to receive(:delete_object).with(Chef::ApiClientV1, client, "client")
+ end
+
+ @knife.run
+ end
+ end
+
it "should print usage and exit when a client name is not provided" do
@knife.name_args = []
expect(@knife).to receive(:show_usage)
diff --git a/spec/unit/knife/configure_spec.rb b/spec/unit/knife/configure_spec.rb
index e96115c056..b7802d3890 100644
--- a/spec/unit/knife/configure_spec.rb
+++ b/spec/unit/knife/configure_spec.rb
@@ -38,7 +38,7 @@ describe Chef::Knife::Configure do
let(:default_validator_key) { "/etc/chef-server/chef-validator.pem" }
let(:default_validator_key_win32) { File.expand_path(default_validator_key) }
- let(:default_server_url) { "https://#{fqdn}:443" }
+ let(:default_server_url) { "https://#{fqdn}/organizations/myorg" }
it "asks the user for the URL of the chef server" do
@knife.ask_user_for_config
diff --git a/spec/unit/knife/cookbook_metadata_spec.rb b/spec/unit/knife/cookbook_metadata_spec.rb
index 4b405d0842..c19fc5ae2d 100644
--- a/spec/unit/knife/cookbook_metadata_spec.rb
+++ b/spec/unit/knife/cookbook_metadata_spec.rb
@@ -19,63 +19,96 @@
require "spec_helper"
describe Chef::Knife::CookbookMetadata do
+ let(:knife) do
+ knife = Chef::Knife::CookbookMetadata.new
+ knife.name_args = ["foobar"]
+ knife
+ end
+
+ let(:cookbook_dir) { Dir.mktmpdir }
+
+ let(:stdout) { StringIO.new }
+
+ let(:stderr) { StringIO.new }
+
before(:each) do
- @knife = Chef::Knife::CookbookMetadata.new
- @knife.name_args = ["foobar"]
- @cookbook_dir = Dir.mktmpdir
- @json_data = '{ "version": "1.0.0" }'
- @stdout = StringIO.new
- @stderr = StringIO.new
- allow(@knife.ui).to receive(:stdout).and_return(@stdout)
- allow(@knife.ui).to receive(:stderr).and_return(@stderr)
+ allow(knife.ui).to receive(:stdout).and_return(stdout)
+ allow(knife.ui).to receive(:stderr).and_return(stderr)
+ end
+
+ def create_metadata_rb(**kwargs)
+ name = kwargs[:name]
+ Dir.mkdir("#{cookbook_dir}/#{name}")
+ File.open("#{cookbook_dir}/#{name}/metadata.rb", "w+") do |f|
+ kwargs.each do |key, value|
+ if value.is_a?(Array)
+ f.puts "#{key} #{value.map { |v| "\"#{v}\"" }.join(", ")}"
+ else
+ f.puts "#{key} \"#{value}\""
+ end
+ end
+ end
+ end
+
+ def create_metadata_json(**kwargs)
+ name = kwargs[:name]
+ Dir.mkdir("#{cookbook_dir}/#{name}")
+ File.open("#{cookbook_dir}/#{name}/metadata.json", "w+") do |f|
+ f.write(FFI_Yajl::Encoder.encode(kwargs))
+ end
+ end
+
+ def create_invalid_json
+ Dir.mkdir("#{cookbook_dir}/foobar")
+ File.open("#{cookbook_dir}/foobar/metadata.json", "w+") do |f|
+ f.write <<-EOH
+ { "version": "1.0.0", {ImInvalid}}
+ EOH
+ end
end
describe "run" do
it "should print an error and exit if a cookbook name was not provided" do
- @knife.name_args = []
- expect(@knife.ui).to receive(:error).with(/you must specify the cookbook.+use the --all/i)
- expect { @knife.run }.to raise_error(SystemExit)
+ knife.name_args = []
+ expect(knife.ui).to receive(:error).with(/you must specify the cookbook.+use the --all/i)
+ expect { knife.run }.to raise_error(SystemExit)
end
it "should print an error and exit if an empty cookbook name was provided" do
- @knife.name_args = [""]
- expect(@knife.ui).to receive(:error).with(/you must specify the cookbook.+use the --all/i)
- expect { @knife.run }.to raise_error(SystemExit)
+ knife.name_args = [""]
+ expect(knife.ui).to receive(:error).with(/you must specify the cookbook.+use the --all/i)
+ expect { knife.run }.to raise_error(SystemExit)
end
it "should generate the metadata for the cookbook" do
- expect(@knife).to receive(:generate_metadata).with("foobar")
- @knife.run
+ expect(knife).to receive(:generate_metadata).with("foobar")
+ knife.run
end
describe "with -a or --all" do
before(:each) do
- @knife.config[:all] = true
- @foo = Chef::CookbookVersion.new("foo", "/tmp/blah")
- @foo.version = "1.0.0"
- @bar = Chef::CookbookVersion.new("bar", "/tmp/blah")
- @bar.version = "2.0.0"
- @cookbook_loader = {
- "foo" => @foo,
- "bar" => @bar,
- }
- expect(@cookbook_loader).to receive(:load_cookbooks).and_return(@cookbook_loader)
- expect(@knife).to receive(:generate_metadata).with("foo")
- expect(@knife).to receive(:generate_metadata).with("bar")
+ Chef::Config[:cookbook_path] = cookbook_dir
+ knife.config[:all] = true
+ create_metadata_rb(name: "foo", version: "1.0.0")
+ create_metadata_rb(name: "bar", version: "2.0.0")
+ expect(knife).to receive(:generate_metadata).with("foo").and_call_original
+ expect(knife).to receive(:generate_metadata).with("bar").and_call_original
end
it "should generate the metadata for each cookbook" do
- Chef::Config[:cookbook_path] = @cookbook_dir
- expect(Chef::CookbookLoader).to receive(:new).with(@cookbook_dir).and_return(@cookbook_loader)
- @knife.run
+ expect(Chef::CookbookLoader).to receive(:new).with(cookbook_dir).and_call_original
+ knife.run
+ expect(stderr.string).to match /generating metadata for foo from #{cookbook_dir}\/foo\/metadata\.rb/im
+ expect(stderr.string).to match /generating metadata for bar from #{cookbook_dir}\/bar\/metadata\.rb/im
end
- describe "and with -o or --cookbook-path" do
- it "should look in the provided path and generate cookbook metadata" do
- @knife.config[:cookbook_path] = "/opt/chef/cookbooks"
- expect(Chef::CookbookLoader).to receive(:new).with("/opt/chef/cookbooks").and_return(@cookbook_loader)
- @knife.run
- end
+ it "with -o or --cookbook_path should look in the provided path and generate cookbook metadata" do
+ Chef::Config[:cookbook_path] = "/dev/null"
+ knife.config[:cookbook_path] = cookbook_dir
+ expect(Chef::CookbookLoader).to receive(:new).with(cookbook_dir).and_call_original
+ knife.run
+ expect(stderr.string).to match /generating metadata for foo from #{cookbook_dir}\/foo\/metadata\.rb/im
+ expect(stderr.string).to match /generating metadata for bar from #{cookbook_dir}\/bar\/metadata\.rb/im
end
end
@@ -83,97 +116,67 @@ describe Chef::Knife::CookbookMetadata do
describe "generate_metadata" do
before(:each) do
- @knife.config[:cookbook_path] = @cookbook_dir
- allow(File).to receive(:expand_path).with("#{@cookbook_dir}/foobar/metadata.rb").
- and_return("#{@cookbook_dir}/foobar/metadata.rb")
+ Chef::Config[:cookbook_path] = cookbook_dir
end
it "should generate the metadata from metadata.rb if it exists" do
- expect(File).to receive(:exists?).with("#{@cookbook_dir}/foobar/metadata.rb").
- and_return(true)
- expect(@knife).to receive(:generate_metadata_from_file).with("foobar", "#{@cookbook_dir}/foobar/metadata.rb")
- @knife.run
+ create_metadata_rb(name: "foobar", version: "1.0.0")
+ expect(knife).to receive(:generate_metadata_from_file).with("foobar", "#{cookbook_dir}/foobar/metadata.rb").and_call_original
+ knife.run
+ expect(File.exist?("#{cookbook_dir}/foobar/metadata.json")).to be true
+ json = FFI_Yajl::Parser.parse(IO.read("#{cookbook_dir}/foobar/metadata.json"))
+ expect(json["name"]).to eql("foobar")
+ expect(json["version"]).to eql("1.0.0")
end
it "should validate the metadata json if metadata.rb does not exist" do
- expect(File).to receive(:exists?).with("#{@cookbook_dir}/foobar/metadata.rb").
- and_return(false)
- expect(@knife).to receive(:validate_metadata_json).with(@cookbook_dir, "foobar")
- @knife.run
+ create_metadata_json(name: "foobar", version: "1.0.0")
+ expect(knife).to receive(:validate_metadata_json).with(cookbook_dir, "foobar").and_call_original
+ knife.run
end
end
- describe "generate_metadata_from_file" do
+ describe "validation errors" do
before(:each) do
- @metadata_mock = double("metadata")
- @json_file_mock = double("json_file")
- end
-
- it "should generate the metatdata json from metatdata.rb" do
- allow(Chef::Cookbook::Metadata).to receive(:new).and_return(@metadata_mock)
- expect(@metadata_mock).to receive(:name).with("foobar")
- expect(@metadata_mock).to receive(:from_file).with("#{@cookbook_dir}/foobar/metadata.rb")
- expect(File).to receive(:open).with("#{@cookbook_dir}/foobar/metadata.json", "w").
- and_yield(@json_file_mock)
- expect(@json_file_mock).to receive(:write).with(@json_data)
- expect(Chef::JSONCompat).to receive(:to_json_pretty).with(@metadata_mock).
- and_return(@json_data)
- @knife.generate_metadata_from_file("foobar", "#{@cookbook_dir}/foobar/metadata.rb")
- expect(@stderr.string).to match /generating metadata for foobar from #{@cookbook_dir}\/foobar\/metadata\.rb/im
- end
-
- { Chef::Exceptions::ObsoleteDependencySyntax => "obsolote dependency",
- Chef::Exceptions::InvalidVersionConstraint => "invalid version constraint",
- }.each_pair do |klass, description|
- it "should print an error and exit when an #{description} syntax exception is encountered" do
- exception = klass.new("#{description} blah")
- allow(Chef::Cookbook::Metadata).to receive(:new).and_raise(exception)
- expect do
- @knife.generate_metadata_from_file("foobar", "#{@cookbook_dir}/foobar/metadata.rb")
- end.to raise_error(SystemExit)
- expect(@stderr.string).to match /error: the cookbook 'foobar' contains invalid or obsolete metadata syntax/im
- expect(@stderr.string).to match /in #{@cookbook_dir}\/foobar\/metadata\.rb/im
- expect(@stderr.string).to match /#{description} blah/im
- end
+ Chef::Config[:cookbook_path] = cookbook_dir
end
- end
- describe "validate_metadata_json" do
- it "should validate the metadata json" do
- expect(File).to receive(:exist?).with("#{@cookbook_dir}/foobar/metadata.json").
- and_return(true)
- expect(IO).to receive(:read).with("#{@cookbook_dir}/foobar/metadata.json").
- and_return(@json_data)
- expect(Chef::Cookbook::Metadata).to receive(:validate_json).with(@json_data)
- @knife.validate_metadata_json(@cookbook_dir, "foobar")
+ it "should fail for obsolete operators in metadata.rb" do
+ create_metadata_rb(name: "foobar", version: "1.0.0", depends: [ "foo:bar", ">> 0.2" ])
+ expect(Chef::Cookbook::Metadata).not_to receive(:validate_json)
+ expect { knife.run }.to raise_error(SystemExit)
+ expect(stderr.string).to match /error: the cookbook 'foobar' contains invalid or obsolete metadata syntax/im
end
- it "should not try to validate the metadata json if the file does not exist" do
- expect(File).to receive(:exist?).with("#{@cookbook_dir}/foobar/metadata.json").
- and_return(false)
- expect(IO).not_to receive(:read)
+ it "should fail for obsolete format in metadata.rb (sadly)" do
+ create_metadata_rb(name: "foobar", version: "1.0.0", depends: [ "foo:bar", "> 0.2", "< 1.0" ])
expect(Chef::Cookbook::Metadata).not_to receive(:validate_json)
- @knife.validate_metadata_json(@cookbook_dir, "foobar")
- end
-
- { Chef::Exceptions::ObsoleteDependencySyntax => "obsolote dependency",
- Chef::Exceptions::InvalidVersionConstraint => "invalid version constraint",
- }.each_pair do |klass, description|
- it "should print an error and exit when an #{description} syntax exception is encountered" do
- expect(File).to receive(:exist?).with("#{@cookbook_dir}/foobar/metadata.json").
- and_return(true)
- expect(IO).to receive(:read).with("#{@cookbook_dir}/foobar/metadata.json").
- and_return(@json_data)
- exception = klass.new("#{description} blah")
- allow(Chef::Cookbook::Metadata).to receive(:validate_json).and_raise(exception)
- expect do
- @knife.validate_metadata_json(@cookbook_dir, "foobar")
- end.to raise_error(SystemExit)
- expect(@stderr.string).to match /error: the cookbook 'foobar' contains invalid or obsolete metadata syntax/im
- expect(@stderr.string).to match /in #{@cookbook_dir}\/foobar\/metadata\.json/im
- expect(@stderr.string).to match /#{description} blah/im
- end
+ expect { knife.run }.to raise_error(SystemExit)
+ expect(stderr.string).to match /error: the cookbook 'foobar' contains invalid or obsolete metadata syntax/im
+ end
+
+ it "should fail for obsolete operators in metadata.json" do
+ create_metadata_json(name: "foobar", version: "1.0.0", dependencies: { "foo:bar" => ">> 0.2" })
+ expect { knife.run }.to raise_error(SystemExit)
+ expect(stderr.string).to match /error: the cookbook 'foobar' contains invalid or obsolete metadata syntax/im
end
- end
+ it "should not fail for unknown field in metadata.rb" do
+ create_metadata_rb(name: "sounders", version: "2.0.0", beats: "toronto")
+ expect(Chef::Cookbook::Metadata).not_to receive(:validate_json)
+ expect { knife.run }.not_to raise_error
+ expect(stderr.string).to eql("")
+ end
+
+ it "should not fail for unknown field in metadata.json" do
+ create_metadata_json(name: "sounders", version: "2.0.0", beats: "toronto")
+ expect { knife.run }.not_to raise_error
+ expect(stderr.string).to eql("")
+ end
+
+ it "should fail on unparsable json" do
+ create_invalid_json
+ expect { knife.run }.to raise_error(Chef::Exceptions::JSON::ParseError)
+ end
+ end
end
diff --git a/spec/unit/knife/core/bootstrap_context_spec.rb b/spec/unit/knife/core/bootstrap_context_spec.rb
index 6465e18ac9..515381cf6e 100644
--- a/spec/unit/knife/core/bootstrap_context_spec.rb
+++ b/spec/unit/knife/core/bootstrap_context_spec.rb
@@ -30,6 +30,8 @@ describe Chef::Knife::Core::BootstrapContext do
let(:run_list) { Chef::RunList.new("recipe[tmux]", "role[base]") }
let(:chef_config) do
{
+ :config_log_level => "info",
+ :config_log_location => "/tmp/log",
:validation_key => File.join(CHEF_SPEC_DATA, "ssl", "private_key.pem"),
:chef_server_url => "http://chef.example.com:4444",
:validation_client_name => "chef-validator-testing",
@@ -68,18 +70,15 @@ describe Chef::Knife::Core::BootstrapContext do
it "generates the config file data" do
expected = <<-EXPECTED
-log_location STDOUT
chef_server_url "http://chef.example.com:4444"
validation_client_name "chef-validator-testing"
+log_level :info
+log_location "/tmp/log"
# Using default node name (fqdn)
EXPECTED
expect(bootstrap_context.config_content).to eq expected
end
- it "does not set a default log_level" do
- expect(bootstrap_context.config_content).not_to match(/log_level/)
- end
-
describe "alternate chef-client path" do
let(:chef_config) { { :chef_client_path => "/usr/local/bin/chef-client" } }
it "runs chef-client from another path when specified" do
@@ -254,4 +253,55 @@ EXPECTED
end
end
+ describe "#config_log_location" do
+ context "when config_log_location is nil" do
+ let(:chef_config) { { :config_log_location => nil } }
+ it "sets the default config_log_location in the client.rb" do
+ expect(bootstrap_context.get_log_location).to eq "STDOUT"
+ end
+ end
+
+ context "when config_log_location is empty" do
+ let(:chef_config) { { :config_log_location => "" } }
+ it "sets the default config_log_location in the client.rb" do
+ expect(bootstrap_context.get_log_location).to eq "STDOUT"
+ end
+ end
+
+ context "when config_log_location is :win_evt" do
+ let(:chef_config) { { :config_log_location => :win_evt } }
+ it "raise error when config_log_location is :win_evt " do
+ expect { bootstrap_context.get_log_location }.to raise_error("The value :win_evt is not supported for config_log_location on Linux Platforms \n")
+ end
+ end
+
+ context "when config_log_location is :syslog" do
+ let(:chef_config) { { :config_log_location => :syslog } }
+ it "sets the config_log_location value as :syslog in the client.rb" do
+ expect(bootstrap_context.get_log_location).to eq ":syslog"
+ end
+ end
+
+ context "When config_log_location is STDOUT" do
+ let(:chef_config) { { :config_log_location => STDOUT } }
+ it "Sets the config_log_location value as STDOUT in the client.rb" do
+ expect(bootstrap_context.get_log_location).to eq "STDOUT"
+ end
+ end
+
+ context "when config_log_location is STDERR" do
+ let(:chef_config) { { :config_log_location => STDERR } }
+ it "sets the config_log_location value as STDERR in the client.rb" do
+ expect(bootstrap_context.get_log_location).to eq "STDERR"
+ end
+ end
+
+ context "when config_log_location is a path" do
+ let(:chef_config) { { :config_log_location => "/tmp/ChefLogFile" } }
+ it "sets the config_log_location path in the client.rb" do
+ expect(bootstrap_context.get_log_location).to eq "\"/tmp/ChefLogFile\""
+ end
+ end
+
+ end
end
diff --git a/spec/unit/knife/node_delete_spec.rb b/spec/unit/knife/node_delete_spec.rb
index d4ef32bccf..1a6b277dbb 100644
--- a/spec/unit/knife/node_delete_spec.rb
+++ b/spec/unit/knife/node_delete_spec.rb
@@ -25,12 +25,17 @@ describe Chef::Knife::NodeDelete do
@knife.config = {
:print_after => nil,
}
- @knife.name_args = [ "adam" ]
+ @knife.name_args = %w{ adam ben }
allow(@knife).to receive(:output).and_return(true)
allow(@knife).to receive(:confirm).and_return(true)
- @node = Chef::Node.new()
- allow(@node).to receive(:destroy).and_return(true)
- allow(Chef::Node).to receive(:load).and_return(@node)
+
+ @adam_node = Chef::Node.new()
+ @ben_node = Chef::Node.new()
+ allow(@ben_node).to receive(:destroy).and_return(true)
+ allow(@adam_node).to receive(:destroy).and_return(true)
+ allow(Chef::Node).to receive(:load).with("adam").and_return(@adam_node)
+ allow(Chef::Node).to receive(:load).with("ben").and_return(@ben_node)
+
@stdout = StringIO.new
allow(@knife.ui).to receive(:stdout).and_return(@stdout)
end
@@ -41,13 +46,15 @@ describe Chef::Knife::NodeDelete do
@knife.run
end
- it "should load the node" do
- expect(Chef::Node).to receive(:load).with("adam").and_return(@node)
+ it "should load the nodes" do
+ expect(Chef::Node).to receive(:load).with("adam").and_return(@adam_node)
+ expect(Chef::Node).to receive(:load).with("ben").and_return(@ben_node)
@knife.run
end
- it "should delete the node" do
- expect(@node).to receive(:destroy).and_return(@node)
+ it "should delete the nodes" do
+ expect(@adam_node).to receive(:destroy).and_return(@adam_node)
+ expect(@ben_node).to receive(:destroy).and_return(@ben_node)
@knife.run
end
@@ -59,8 +66,10 @@ describe Chef::Knife::NodeDelete do
describe "with -p or --print-after" do
it "should pretty print the node, formatted for display" do
@knife.config[:print_after] = true
- expect(@knife).to receive(:format_for_display).with(@node).and_return("poop")
- expect(@knife).to receive(:output).with("poop")
+ expect(@knife).to receive(:format_for_display).with(@adam_node).and_return("adam")
+ expect(@knife).to receive(:format_for_display).with(@ben_node).and_return("ben")
+ expect(@knife).to receive(:output).with("adam")
+ expect(@knife).to receive(:output).with("ben")
@knife.run
end
end
diff --git a/spec/unit/knife/ssh_spec.rb b/spec/unit/knife/ssh_spec.rb
index 44a133d858..6141a8a6df 100644
--- a/spec/unit/knife/ssh_spec.rb
+++ b/spec/unit/knife/ssh_spec.rb
@@ -21,54 +21,53 @@ require "net/ssh"
require "net/ssh/multi"
describe Chef::Knife::Ssh do
- before(:each) do
- Chef::Config[:client_key] = CHEF_SPEC_DATA + "/ssl/private_key.pem"
- end
+ let(:query_result) { double("chef search results") }
before do
+ Chef::Config[:client_key] = CHEF_SPEC_DATA + "/ssl/private_key.pem"
@knife = Chef::Knife::Ssh.new
@knife.merge_configs
- @node_foo = Chef::Node.new
- @node_foo.automatic_attrs[:fqdn] = "foo.example.org"
- @node_foo.automatic_attrs[:ipaddress] = "10.0.0.1"
+ @node_foo = {}
+ @node_foo["fqdn"] = "foo.example.org"
+ @node_foo["ipaddress"] = "10.0.0.1"
+ @node_foo["cloud"] = {}
+
+ @node_bar = {}
+ @node_bar["fqdn"] = "bar.example.org"
+ @node_bar["ipaddress"] = "10.0.0.2"
+ @node_bar["cloud"] = {}
- @node_bar = Chef::Node.new
- @node_bar.automatic_attrs[:fqdn] = "bar.example.org"
- @node_bar.automatic_attrs[:ipaddress] = "10.0.0.2"
end
describe "#configure_session" do
context "manual is set to false (default)" do
before do
@knife.config[:manual] = false
- @query = Chef::Search::Query.new
- end
-
- def configure_query(node_array)
- allow(@query).to receive(:search).and_return([node_array])
- allow(Chef::Search::Query).to receive(:new).and_return(@query)
+ allow(query_result).to receive(:search).with(any_args).and_yield(@node_foo).and_yield(@node_bar)
+ allow(Chef::Search::Query).to receive(:new).and_return(query_result)
end
def self.should_return_specified_attributes
it "returns an array of the attributes specified on the command line OR config file, if only one is set" do
+ @node_bar["config"] = "10.0.0.2"
+ @node_foo["config"] = "10.0.0.1"
@knife.config[:attribute] = "ipaddress"
Chef::Config[:knife][:ssh_attribute] = "ipaddress" # this value will be in the config file
- configure_query([@node_foo, @node_bar])
expect(@knife).to receive(:session_from_list).with([["10.0.0.1", nil], ["10.0.0.2", nil]])
@knife.configure_session
end
it "returns an array of the attributes specified on the command line even when a config value is set" do
+ @node_bar["config"] = "10.0.0.2"
+ @node_foo["config"] = "10.0.0.1"
Chef::Config[:knife][:ssh_attribute] = "config_file" # this value will be in the config file
@knife.config[:attribute] = "ipaddress" # this is the value of the command line via #configure_attribute
- configure_query([@node_foo, @node_bar])
expect(@knife).to receive(:session_from_list).with([["10.0.0.1", nil], ["10.0.0.2", nil]])
@knife.configure_session
end
end
it "searchs for and returns an array of fqdns" do
- configure_query([@node_foo, @node_bar])
expect(@knife).to receive(:session_from_list).with([
["foo.example.org", nil],
["bar.example.org", nil],
@@ -80,11 +79,10 @@ describe Chef::Knife::Ssh do
context "when cloud hostnames are available" do
before do
- @node_foo.automatic_attrs[:cloud][:public_hostname] = "ec2-10-0-0-1.compute-1.amazonaws.com"
- @node_bar.automatic_attrs[:cloud][:public_hostname] = "ec2-10-0-0-2.compute-1.amazonaws.com"
+ @node_foo["cloud"]["public_hostname"] = "ec2-10-0-0-1.compute-1.amazonaws.com"
+ @node_bar["cloud"]["public_hostname"] = "ec2-10-0-0-2.compute-1.amazonaws.com"
end
it "returns an array of cloud public hostnames" do
- configure_query([@node_foo, @node_bar])
expect(@knife).to receive(:session_from_list).with([
["ec2-10-0-0-1.compute-1.amazonaws.com", nil],
["ec2-10-0-0-2.compute-1.amazonaws.com", nil],
@@ -97,12 +95,11 @@ describe Chef::Knife::Ssh do
context "when cloud hostnames are available but empty" do
before do
- @node_foo.automatic_attrs[:cloud][:public_hostname] = ""
- @node_bar.automatic_attrs[:cloud][:public_hostname] = ""
+ @node_foo["cloud"]["public_hostname"] = ""
+ @node_bar["cloud"]["public_hostname"] = ""
end
it "returns an array of fqdns" do
- configure_query([@node_foo, @node_bar])
expect(@knife).to receive(:session_from_list).with([
["foo.example.org", nil],
["bar.example.org", nil],
@@ -114,7 +111,7 @@ describe Chef::Knife::Ssh do
end
it "should raise an error if no host are found" do
- configure_query([ ])
+ allow(query_result).to receive(:search).with(any_args)
expect(@knife.ui).to receive(:fatal)
expect(@knife).to receive(:exit).with(10)
@knife.configure_session
@@ -122,10 +119,8 @@ describe Chef::Knife::Ssh do
context "when there are some hosts found but they do not have an attribute to connect with" do
before do
- allow(@query).to receive(:search).and_return([[@node_foo, @node_bar]])
- @node_foo.automatic_attrs[:fqdn] = nil
- @node_bar.automatic_attrs[:fqdn] = nil
- allow(Chef::Search::Query).to receive(:new).and_return(@query)
+ @node_foo["fqdn"] = nil
+ @node_bar["fqdn"] = nil
end
it "should raise a specific error (CHEF-3402)" do
@@ -158,31 +153,34 @@ describe Chef::Knife::Ssh do
before do
Chef::Config[:knife][:ssh_attribute] = nil
@knife.config[:attribute] = nil
- @node_foo.automatic_attrs[:cloud][:public_hostname] = "ec2-10-0-0-1.compute-1.amazonaws.com"
- @node_bar.automatic_attrs[:cloud][:public_hostname] = ""
+ @node_foo["cloud"]["public_hostname"] = "ec2-10-0-0-1.compute-1.amazonaws.com"
+ @node_bar["cloud"]["public_hostname"] = ""
end
it "should return fqdn by default" do
- expect(@knife.get_ssh_attribute(Chef::Node.new)).to eq("fqdn")
+ expect(@knife.get_ssh_attribute({ "fqdn" => "fqdn" })).to eq("fqdn")
end
it "should return cloud.public_hostname attribute if available" do
- expect(@knife.get_ssh_attribute(@node_foo)).to eq("cloud.public_hostname")
+ expect(@knife.get_ssh_attribute(@node_foo)).to eq("ec2-10-0-0-1.compute-1.amazonaws.com")
end
it "should favor to attribute_from_cli over config file and cloud" do
@knife.config[:attribute] = "command_line"
Chef::Config[:knife][:ssh_attribute] = "config_file"
+ @node_foo["config"] = "command_line"
+ @node_foo["knife_config"] = "config_file"
expect( @knife.get_ssh_attribute(@node_foo)).to eq("command_line")
end
it "should favor config file over cloud and default" do
Chef::Config[:knife][:ssh_attribute] = "config_file"
+ @node_foo["knife_config"] = "config_file"
expect( @knife.get_ssh_attribute(@node_foo)).to eq("config_file")
end
it "should return fqdn if cloud.hostname is empty" do
- expect( @knife.get_ssh_attribute(@node_bar)).to eq("fqdn")
+ expect( @knife.get_ssh_attribute(@node_bar)).to eq("bar.example.org")
end
end
@@ -190,7 +188,7 @@ describe Chef::Knife::Ssh do
before :each do
@knife.instance_variable_set(:@longest, 0)
ssh_config = { :timeout => 50, :user => "locutus", :port => 23 }
- allow(Net::SSH).to receive(:configuration_for).with("the.b.org").and_return(ssh_config)
+ allow(Net::SSH).to receive(:configuration_for).with("the.b.org", true).and_return(ssh_config)
end
it "uses the port from an ssh config file" do
@@ -294,7 +292,7 @@ describe Chef::Knife::Ssh do
describe "#run" do
before do
@query = Chef::Search::Query.new
- expect(@query).to receive(:search).and_return([[@node_foo]])
+ expect(@query).to receive(:search).and_yield(@node_foo)
allow(Chef::Search::Query).to receive(:new).and_return(@query)
allow(@knife).to receive(:ssh_command).and_return(exit_code)
@knife.name_args = ["*:*", "false"]
diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb
index 0689d99647..9700b8ef2b 100644
--- a/spec/unit/lwrp_spec.rb
+++ b/spec/unit/lwrp_spec.rb
@@ -413,8 +413,7 @@ describe "LWRP" do
resource = get_lwrp(:lwrp_foo).new("morpheus", run_context)
resource.monkey("bob")
resource.provider(get_lwrp_provider(:lwrp_monkey_name_printer))
-
- provider = Chef::Platform.provider_for_resource(resource, :twiddle_thumbs)
+ provider = resource.provider_for_action(:twiddle_thumbs)
provider.action_twiddle_thumbs
end
@@ -520,7 +519,7 @@ describe "LWRP" do
resource.monkey("bob")
resource.provider(get_lwrp_provider(:lwrp_monkey_name_printer))
- provider = Chef::Platform.provider_for_resource(resource, :twiddle_thumbs)
+ provider = resource.provider_for_action(:twiddle_thumbs)
provider.action_twiddle_thumbs
expect(provider.monkey_name).to eq("my monkey's name is 'bob'")
@@ -531,7 +530,7 @@ describe "LWRP" do
resource.monkey("bob")
resource.provider(get_lwrp_provider(:lwrp_embedded_resource_accesses_providers_scope))
- provider = Chef::Platform.provider_for_resource(resource, :twiddle_thumbs)
+ provider = resource.provider_for_action(:twiddle_thumbs)
#provider = @runner.build_provider(resource)
provider.action_twiddle_thumbs
diff --git a/spec/unit/mixin/shell_out_spec.rb b/spec/unit/mixin/shell_out_spec.rb
index bf74ff410e..aa38639c1c 100644
--- a/spec/unit/mixin/shell_out_spec.rb
+++ b/spec/unit/mixin/shell_out_spec.rb
@@ -59,7 +59,6 @@ describe Chef::Mixin::ShellOut do
it "should emit a deprecation warning" do
assume_deprecation_log_level && capture_log_output
subject
- expect(output.string).to match /DEPRECATION:/
expect(output.string).to match Regexp.escape(old_option.to_s)
expect(output.string).to match Regexp.escape(new_option.to_s)
end
diff --git a/spec/unit/mixin/versioned_api_spec.rb b/spec/unit/mixin/versioned_api_spec.rb
new file mode 100644
index 0000000000..4f2418ca24
--- /dev/null
+++ b/spec/unit/mixin/versioned_api_spec.rb
@@ -0,0 +1,107 @@
+#
+# Copyright:: Copyright 2015-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/mixin/versioned_api"
+
+describe Chef::Mixin::VersionedAPI do
+ let(:dummy_class) { Class.new { extend Chef::Mixin::VersionedAPI } }
+
+ it "allows a class to declare the minimum supported API version" do
+ dummy_class.minimum_api_version 3
+ expect(dummy_class.minimum_api_version).to eq(3)
+ end
+end
+
+describe Chef::Mixin::VersionedAPIFactory do
+ class V1Class; extend Chef::Mixin::VersionedAPI; minimum_api_version 1; end
+ class V2Class; extend Chef::Mixin::VersionedAPI; minimum_api_version 2; end
+ class V3Class; extend Chef::Mixin::VersionedAPI; minimum_api_version 3; end
+
+ let(:factory_class) { Class.new { extend Chef::Mixin::VersionedAPIFactory } }
+
+ before do
+ Chef::ServerAPIVersions.instance.reset!
+ end
+
+ describe "#add_versioned_api_class" do
+ it "adds a target class" do
+ factory_class.add_versioned_api_class V1Class
+ expect(factory_class.versioned_interfaces).to eq([V1Class])
+ end
+
+ it "can be called many times" do
+ factory_class.add_versioned_api_class V1Class
+ factory_class.add_versioned_api_class V2Class
+ expect(factory_class.versioned_interfaces).to eq([V1Class, V2Class])
+ end
+ end
+
+ describe "#versioned_api_class" do
+ describe "with no known versions" do
+ it "with one class it returns that class" do
+ factory_class.add_versioned_api_class V2Class
+ expect(factory_class.versioned_api_class.minimum_api_version).to eq(2)
+ end
+
+ it "with many classes it returns the highest minimum version" do
+ factory_class.add_versioned_api_class V1Class
+ factory_class.add_versioned_api_class V2Class
+ factory_class.add_versioned_api_class V3Class
+ expect(factory_class.versioned_api_class.minimum_api_version).to eq(3)
+ end
+ end
+
+ describe "with a known version" do
+ it "with one class it returns that class" do
+ Chef::ServerAPIVersions.instance.set_versions({ "min_version" => 0, "max_version" => 2 })
+ factory_class.add_versioned_api_class V2Class
+ expect(factory_class.versioned_api_class.minimum_api_version).to eq(2)
+ end
+
+ it "with a maximum version it returns the highest possible versioned class" do
+ Chef::ServerAPIVersions.instance.set_versions({ "min_version" => 0, "max_version" => 2 })
+ factory_class.add_versioned_api_class V1Class
+ factory_class.add_versioned_api_class V2Class
+ factory_class.add_versioned_api_class V3Class
+ expect(factory_class.versioned_api_class.minimum_api_version).to eq(2)
+ end
+ end
+
+ it "with no classes it returns nil" do
+ expect(factory_class.versioned_api_class).to be_nil
+ end
+ end
+
+ describe "#new" do
+ it "creates an instance of the versioned class" do
+ factory_class.add_versioned_api_class V2Class
+ expect { factory_class.new }.to_not raise_error
+ expect(factory_class.new.class).to eq(V2Class)
+ end
+ end
+
+ describe "#def_versioned_delegator" do
+ it "delegates the method to the correct class" do
+ factory_class.add_versioned_api_class V2Class
+ factory_class.def_versioned_delegator("test_method")
+ expect(V2Class).to receive(:test_method).with("test message").and_return(true)
+
+ factory_class.test_method("test message")
+ end
+ end
+end
diff --git a/spec/unit/mixin/which.rb b/spec/unit/mixin/which.rb
new file mode 100644
index 0000000000..1764b3b89f
--- /dev/null
+++ b/spec/unit/mixin/which.rb
@@ -0,0 +1,160 @@
+#
+# Copyright:: Copyright 2011-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"
+
+class TestClass
+ include Chef::Mixin::Which
+end
+
+describe Chef::Mixin::Which do
+
+ let(:test) { TestClass.new }
+
+ describe "#which" do
+ def self.test_which(description, *args, finds: nil, others: [], directory: false, &block)
+ it description do
+ # stub the ENV['PATH']
+ expect(test).to receive(:env_path).and_return(["/dir1", "/dir2" ].join(File::PATH_SEPARATOR))
+
+ # most files should not be found
+ allow(File).to receive(:executable?).and_return(false)
+ allow(File).to receive(:directory?).and_return(false)
+
+ # stub the expectation
+ expect(File).to receive(:executable?).with(finds).and_return(true) if finds
+
+ # if the file we find is a directory
+ expect(File).to receive(:directory?).with(finds).and_return(true) if finds && directory
+
+ # allow for stubbing other paths to exist that we should not find
+ others.each do |other|
+ allow(File).to receive(:executable?).with(other).and_return(true)
+ end
+
+ # setup the actual expectation on the return value
+ if finds && !directory
+ expect(test.which(*args, &block)).to eql(finds)
+ else
+ expect(test.which(*args, &block)).to eql(false)
+ end
+ end
+ end
+
+ context "simple usage" do
+ test_which("returns false when it does not find anything", "foo1")
+
+ ["/dir1", "/dir2", "/bin", "/usr/bin", "/sbin", "/usr/sbin" ].each do |dir|
+ test_which("finds `foo1` in #{dir} when it is stubbed", "foo1", finds: "#{dir}/foo1")
+ end
+
+ test_which("does not find an executable directory", "foo1", finds: "/dir1/foo1", directory: true)
+ end
+
+ context "with an array of args" do
+ test_which("finds the first arg", "foo1", "foo2", finds: "/dir2/foo1")
+
+ test_which("finds the second arg", "foo1", "foo2", finds: "/dir2/foo2")
+
+ test_which("finds the first arg when there's both", "foo1", "foo2", finds: "/dir2/foo1", others: [ "/dir1/foo2" ])
+
+ test_which("and the directory order can be reversed", "foo1", "foo2", finds: "/dir1/foo1", others: [ "/dir2/foo2" ])
+
+ test_which("or be the same", "foo1", "foo2", finds: "/dir1/foo1", others: [ "/dir1/foo2" ])
+ end
+
+ context "with a block" do
+ test_which("doesnt find it if its false", "foo1", others: [ "/dir1/foo1" ]) do |f|
+ false
+ end
+
+ test_which("finds it if its true", "foo1", finds: "/dir1/foo1") do |f|
+ true
+ end
+
+ test_which("passes in the filename as the arg", "foo1", finds: "/dir1/foo1") do |f|
+ raise "bad arg to block" unless f == "/dir1/foo1"
+ true
+ end
+
+ test_which("arrays with blocks", "foo1", "foo2", finds: "/dir2/foo1", others: [ "/dir1/foo2" ]) do |f|
+ raise "bad arg to block" unless f == "/dir2/foo1" || f == "/dir1/foo2"
+ true
+ end
+ end
+ end
+
+ describe "#where" do
+ def self.test_where(description, *args, finds: [], others: [], &block)
+ it description do
+ # stub the ENV['PATH']
+ expect(test).to receive(:env_path).and_return(["/dir1", "/dir2" ].join(File::PATH_SEPARATOR))
+
+ # most files should not be found
+ allow(File).to receive(:executable?).and_return(false)
+ allow(File).to receive(:directory?).and_return(false)
+
+ # allow for stubbing other paths to exist that we should not return
+ others.each do |other|
+ allow(File).to receive(:executable?).with(other).and_return(true)
+ end
+
+ # stub the expectation
+ finds.each do |path|
+ expect(File).to receive(:executable?).with(path).and_return(true)
+ end
+
+ # setup the actual expectation on the return value
+ expect(test.where(*args, &block)).to eql(finds)
+ end
+ end
+
+ context "simple usage" do
+ test_where("returns empty array when it doesn't find anything", "foo1")
+
+ ["/dir1", "/dir2", "/bin", "/usr/bin", "/sbin", "/usr/sbin" ].each do |dir|
+ test_where("finds `foo1` in #{dir} when it is stubbed", "foo1", finds: [ "#{dir}/foo1" ])
+ end
+
+ test_where("finds `foo1` in all directories", "foo1", finds: [ "/dir1/foo1", "/dir2/foo1" ])
+ end
+
+ context "with an array of args" do
+ test_where("finds the first arg", "foo1", "foo2", finds: [ "/dir2/foo1" ])
+
+ test_where("finds the second arg", "foo1", "foo2", finds: [ "/dir2/foo2" ])
+
+ test_where("finds foo1 before foo2", "foo1", "foo2", finds: [ "/dir2/foo1", "/dir1/foo2" ])
+
+ test_where("finds foo1 before foo2 if the dirs are reversed", "foo1", "foo2", finds: [ "/dir1/foo1", "/dir2/foo2" ])
+
+ test_where("finds them both in the same directory", "foo1", "foo2", finds: [ "/dir1/foo1", "/dir1/foo2" ])
+
+ test_where("finds foo2 first if they're reversed", "foo2", "foo1", finds: [ "/dir1/foo2", "/dir1/foo1" ])
+ end
+
+ context "with a block do" do
+ test_where("finds foo1 and foo2 if they exist and the block is true", "foo1", "foo2", finds: [ "/dir1/foo2", "/dir2/foo2" ]) do
+ true
+ end
+
+ test_where("does not finds foo1 and foo2 if they exist and the block is false", "foo1", "foo2", others: [ "/dir1/foo2", "/dir2/foo2" ]) do
+ false
+ end
+ end
+ end
+end
diff --git a/spec/unit/node/immutable_collections_spec.rb b/spec/unit/node/immutable_collections_spec.rb
index fe4e50d1bd..81dd771df3 100644
--- a/spec/unit/node/immutable_collections_spec.rb
+++ b/spec/unit/node/immutable_collections_spec.rb
@@ -198,4 +198,9 @@ describe Chef::Node::ImmutableArray do
end
end
+ describe "#[]" do
+ it "works with array slices" do
+ expect(@immutable_array[1, 2]).to eql(%w{bar baz})
+ end
+ end
end
diff --git a/spec/unit/node/vivid_mash_spec.rb b/spec/unit/node/vivid_mash_spec.rb
index 017e6206fc..4898c22380 100644
--- a/spec/unit/node/vivid_mash_spec.rb
+++ b/spec/unit/node/vivid_mash_spec.rb
@@ -47,7 +47,18 @@ describe Chef::Node::VividMash do
end
end
+ context "#[]" do
+ it "works with array slices" do
+ expect(vivid["array"][1, 2]).to eql([1, 2])
+ end
+ end
+
context "#[]=" do
+ it "works with array slices" do
+ vivid["array"][3, 2] = [ 3, 4 ]
+ expect(vivid["array"]).to eql([0, 1, 2, 3, 4])
+ end
+
it "deep converts values through arrays" do
expect(root).to receive(:reset_cache).with("foo")
vivid["foo"] = [ { :bar => true } ]
diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb
index cfc19db480..ac227c5479 100644
--- a/spec/unit/node_spec.rb
+++ b/spec/unit/node_spec.rb
@@ -335,16 +335,37 @@ describe Chef::Node do
it "set is a deprecated alias for normal" do
Chef::Config[:treat_deprecation_warnings_as_errors] = false
- expect(Chef).to receive(:log_deprecation).with(/set is deprecated/)
+ expect(Chef).to receive(:deprecated).with(:attributes, /set is deprecated/)
node.set[:snoopy][:is_a_puppy] = true
- expect(node[:snoopy][:is_a_puppy]).to eq(true)
+ expect(node.normal[:snoopy][:is_a_puppy]).to eq(true)
end
it "set_unless is a deprecated alias for normal_unless" do
Chef::Config[:treat_deprecation_warnings_as_errors] = false
- expect(Chef).to receive(:log_deprecation).with(/set_unless is deprecated/)
+ expect(Chef).to receive(:deprecated).with(:attributes, /set_unless is deprecated/)
node.set_unless[:snoopy][:is_a_puppy] = false
- expect(node[:snoopy][:is_a_puppy]).to eq(false)
+ expect(node.normal[:snoopy][:is_a_puppy]).to eq(false)
+ end
+
+ it "normal_unless sets a value even if default or override attrs are set" do
+ node.default[:decontamination] = true
+ node.override[:decontamination] = false
+ node.normal_unless[:decontamination] = "foo"
+ expect(node.normal[:decontamination]).to eql("foo")
+ end
+
+ it "default_unless sets a value even if normal or override attrs are set" do
+ node.normal[:decontamination] = true
+ node.override[:decontamination] = false
+ node.default_unless[:decontamination] = "foo"
+ expect(node.default[:decontamination]).to eql("foo")
+ end
+
+ it "override_unless sets a value even if default or normal attrs are set" do
+ node.default[:decontamination] = true
+ node.normal[:decontamination] = false
+ node.override_unless[:decontamination] = "foo"
+ expect(node.override[:decontamination]).to eql("foo")
end
end
diff --git a/spec/unit/platform_spec.rb b/spec/unit/platform_spec.rb
index 0559229d62..3a562d3ce6 100644
--- a/spec/unit/platform_spec.rb
+++ b/spec/unit/platform_spec.rb
@@ -21,6 +21,14 @@ require "spec_helper"
describe Chef::Platform do
context "while testing with fake data" do
+ def expect_platform_warning(method_name, times: 1, recurse: true)
+ expect(Chef).to receive(:deprecated).with(:chef_platform_methods, "Chef::Platform.#{method_name} is deprecated").exactly(times).times
+ return unless recurse
+
+ expect_platform_warning(:find_provider_for_node, times: times) if method_name == :provider_for_resource
+ expect_platform_warning(:find_provider, times: times) if method_name == :find_provider_for_node
+ expect_platform_warning(:find, times: times) if method_name == :find_provider
+ end
before :all do
@original_platform_map = Chef::Platform.platforms
@@ -57,57 +65,67 @@ describe Chef::Platform do
end
it "should allow you to look up a platform by name and version, returning the provider map for it" do
+ expect_platform_warning(:find)
pmap = Chef::Platform.find("Darwin", "9.2.2")
expect(pmap).to be_a_kind_of(Hash)
expect(pmap[:file]).to eql("darwinian")
end
it "should allow you to look up a platform by name and version using \"greater than\" style operators" do
+ expect_platform_warning(:find)
pmap = Chef::Platform.find("Darwin", "11.1.0")
expect(pmap).to be_a_kind_of(Hash)
expect(pmap[:file]).to eql("new_darwinian")
end
it "should use the default providers for an os if the specific version does not exist" do
+ expect_platform_warning(:find)
pmap = Chef::Platform.find("Darwin", "1")
expect(pmap).to be_a_kind_of(Hash)
expect(pmap[:file]).to eql("old school")
end
it "should use the default providers if the os doesn't give me a default, but does exist" do
+ expect_platform_warning(:find)
pmap = Chef::Platform.find("mars_volta", "1")
expect(pmap).to be_a_kind_of(Hash)
expect(pmap[:file]).to eql(Chef::Provider::File)
end
it "should use the default provider if the os does not exist" do
+ expect_platform_warning(:find)
pmap = Chef::Platform.find("AIX", "1")
expect(pmap).to be_a_kind_of(Hash)
expect(pmap[:file]).to eql(Chef::Provider::File)
end
it "should merge the defaults for an os with the specific version" do
+ expect_platform_warning(:find)
pmap = Chef::Platform.find("Darwin", "9.2.2")
expect(pmap[:file]).to eql("darwinian")
expect(pmap[:snicker]).to eql("snack")
end
it "should merge the defaults for an os with the universal defaults" do
+ expect_platform_warning(:find)
pmap = Chef::Platform.find("Darwin", "9.2.2")
expect(pmap[:file]).to eql("darwinian")
expect(pmap[:pax]).to eql("brittania")
end
it "should allow you to look up a provider for a platform directly by symbol" do
+ expect_platform_warning(:find_provider)
expect(Chef::Platform.find_provider("Darwin", "9.2.2", :file)).to eql("darwinian")
end
it "should raise an exception if a provider cannot be found for a resource type" do
+ expect_platform_warning(:find_provider)
expect { Chef::Platform.find_provider("Darwin", "9.2.2", :coffee) }.to raise_error(Chef::Exceptions::ProviderNotFound)
end
it "should look up a provider for a resource with a Chef::Resource object" do
kitty = Chef::Resource::Cat.new("loulou")
+ expect_platform_warning(:find_provider)
expect(Chef::Platform.find_provider("Darwin", "9.2.2", kitty)).to eql("nice")
end
@@ -117,10 +135,12 @@ describe Chef::Platform do
node.name("Intel")
node.automatic_attrs[:platform] = "mac_os_x"
node.automatic_attrs[:platform_version] = "9.2.2"
+ expect_platform_warning(:find_provider_for_node)
expect(Chef::Platform.find_provider_for_node(node, kitty)).to eql("nice")
end
it "should not throw an exception when the platform version has an unknown format" do
+ expect_platform_warning(:find_provider)
expect(Chef::Platform.find_provider(:darwin, "bad-version", :file)).to eql("old school")
end
@@ -131,6 +151,8 @@ describe Chef::Platform do
node.name("Intel")
node.automatic_attrs[:platform] = "mac_os_x"
node.automatic_attrs[:platform_version] = "9.2.2"
+ expect_platform_warning(:find_provider_for_node, recurse: false)
+ expect_platform_warning(:find_provider, recurse: false)
expect(Chef::Platform.find_provider_for_node(node, kitty)).to eql(Chef::Provider::File)
end
@@ -142,6 +164,7 @@ describe Chef::Platform do
node.name("Intel")
node.automatic_attrs[:platform] = "mac_os_x"
node.automatic_attrs[:platform_version] = "8.5"
+ expect_platform_warning(:find_provider_for_node)
expect(Chef::Platform.find_provider_for_node(node, kitty)).to eql(Chef::Provider::Cat)
end
@@ -155,6 +178,7 @@ describe Chef::Platform do
it "returns a provider object given a Chef::Resource object which has a valid run context and an action" do
file, run_context = setup_file_resource
+ expect_platform_warning(:provider_for_resource)
provider = Chef::Platform.provider_for_resource(file, :foo)
expect(provider).to be_an_instance_of(Chef::Provider::File)
expect(provider.new_resource).to equal(file)
@@ -163,6 +187,7 @@ describe Chef::Platform do
it "returns a provider object given a Chef::Resource object which has a valid run context without an action" do
file, run_context = setup_file_resource
+ expect_platform_warning(:provider_for_resource)
provider = Chef::Platform.provider_for_resource(file)
expect(provider).to be_an_instance_of(Chef::Provider::File)
expect(provider.new_resource).to equal(file)
@@ -171,6 +196,7 @@ describe Chef::Platform do
it "raises an error when trying to find the provider for a resource with no run context" do
file = Chef::Resource::File.new("whateva")
+ expect_platform_warning(:provider_for_resource, recurse: false)
expect { Chef::Platform.provider_for_resource(file) }.to raise_error(ArgumentError)
end
@@ -179,6 +205,7 @@ describe Chef::Platform do
end
it "should update the provider map with map" do
+ expect_platform_warning(:set, times: 7)
Chef::Platform.set(
:platform => :darwin,
:version => "9.2.2",
@@ -227,6 +254,7 @@ describe Chef::Platform do
end
it "does not overwrite the platform map when using :default platform" do
+ expect_platform_warning(:set)
Chef::Platform.set(
:resource => :file,
:platform => :default,
diff --git a/spec/unit/provider/deploy_spec.rb b/spec/unit/provider/deploy_spec.rb
index b30ddb736a..b0ede7e260 100644
--- a/spec/unit/provider/deploy_spec.rb
+++ b/spec/unit/provider/deploy_spec.rb
@@ -595,7 +595,7 @@ describe Chef::Provider::Deploy do
callback_code = Proc.new do
snitch = 42
- temp_collection = self.resource_collection
+ temp_collection = resource_collection
run("tehMice")
snitch = temp_collection.lookup("execute[tehMice]")
end
diff --git a/spec/unit/provider/directory_spec.rb b/spec/unit/provider/directory_spec.rb
index aebbaa6e81..4672db7d8d 100644
--- a/spec/unit/provider/directory_spec.rb
+++ b/spec/unit/provider/directory_spec.rb
@@ -148,6 +148,16 @@ describe Chef::Provider::Directory do
directory.run_action(:create)
expect(new_resource).not_to be_updated
end
+
+ context "in why run mode" do
+ before { Chef::Config[:why_run] = true }
+ after { Chef::Config[:why_run] = false }
+
+ it "does not modify new_resource" do
+ expect(directory).not_to receive(:load_resource_attributes_from_file).with(new_resource)
+ directory.run_action(:create)
+ end
+ end
end
describe "when the directory does not exist" do
diff --git a/spec/unit/provider/dsc_resource_spec.rb b/spec/unit/provider/dsc_resource_spec.rb
index 34eb9727f8..96356e5d73 100644
--- a/spec/unit/provider/dsc_resource_spec.rb
+++ b/spec/unit/provider/dsc_resource_spec.rb
@@ -165,4 +165,179 @@ describe Chef::Provider::DscResource do
end
end
end
+
+ describe "define_resource_requirements" do
+ let (:node) do
+ set_node_object
+ end
+
+ context "module usage is valid" do
+ before do
+ allow(provider).to receive(:module_usage_valid?).and_return(true)
+ allow(provider).to receive(:action_run)
+ end
+
+ [:run].each do |action|
+ context "action #{action}" do
+ it "does not raise the exception" do
+ expect { provider.run_action(action) }.not_to raise_error
+ end
+ end
+ end
+ end
+
+ context "module usage is invalid" do
+ before do
+ allow(provider).to receive(:module_usage_valid?).and_return(false)
+ allow(provider).to receive(:action_run)
+ end
+
+ [:run].each do |action|
+ context "action #{action}" do
+ it "raises the exception" do
+ expect { provider.run_action(action) }.to raise_error(
+ Chef::Exceptions::DSCModuleNameMissing
+ )
+ end
+ end
+ end
+ end
+ end
+
+ describe "module_usage_valid?" do
+ let (:node) do
+ set_node_object
+ end
+
+ context "module_name and module_version both are not provided" do
+ before do
+ provider.instance_variable_set(:@module_name, nil)
+ provider.instance_variable_set(:@module_version, nil)
+ end
+
+ it "returns true" do
+ response = provider.send(:module_usage_valid?)
+ expect(response).to be == true
+ end
+ end
+
+ context "module_name and module_version both are provided" do
+ before do
+ provider.instance_variable_set(:@module_name, "my_module")
+ provider.instance_variable_set(:@module_version, "1.3")
+ end
+
+ it "returns true" do
+ response = provider.send(:module_usage_valid?)
+ expect(response).to be == true
+ end
+ end
+
+ context "module_name is given but module_version is not given" do
+ before do
+ provider.instance_variable_set(:@module_name, "my_module")
+ provider.instance_variable_set(:@module_version, nil)
+ end
+
+ it "returns true" do
+ response = provider.send(:module_usage_valid?)
+ expect(response).to be == true
+ end
+ end
+
+ context "module_name is not given but module_version is given" do
+ before do
+ provider.instance_variable_set(:@module_name, nil)
+ provider.instance_variable_set(:@module_version, "1.4.0.1")
+ end
+
+ it "returns false" do
+ response = provider.send(:module_usage_valid?)
+ expect(response).to be == false
+ end
+ end
+ end
+
+ describe "module_info_object" do
+ let (:node) do
+ set_node_object
+ end
+
+ context "module_version is not given" do
+ before do
+ provider.instance_variable_set(:@module_version, nil)
+ allow(provider).to receive(:module_name).and_return("my_module")
+ end
+
+ it "returns only name of the module" do
+ response = provider.send(:module_info_object)
+ expect(response).to be == "my_module"
+ end
+ end
+
+ context "module_version is given" do
+ before do
+ provider.instance_variable_set(:@module_version, "1.3.1")
+ allow(provider).to receive(:module_name).and_return("my_module")
+ end
+
+ it "returns the module info object" do
+ response = provider.send(:module_info_object)
+ expect(response).to be == "@{ModuleName='my_module';ModuleVersion='1.3.1'}"
+ end
+ end
+ end
+
+ describe "invoke_resource" do
+ let (:node) do
+ set_node_object
+ end
+
+ let(:cmdlet) { double(:run! => nil) }
+
+ before(:each) do
+ allow(provider).to receive(:translate_type).and_return("my_properties")
+ provider.instance_variable_set(:@new_resource, double(
+ :properties => "my_properties", :resource => "my_resource", :timeout => 123
+ ))
+ end
+
+ context "when module_version is not given" do
+ before do
+ allow(provider).to receive(:module_info_object).and_return("my_module")
+ end
+
+ it "invokes Invoke-DscResource command with module name" do
+ expect(Chef::Util::Powershell::Cmdlet).to receive(:new).with(
+ node,
+ "Invoke-DscResource -Method my_method -Name my_resource -Property my_properties -Module my_module -Verbose",
+ "my_output_format"
+ ).and_return(cmdlet)
+ provider.send(:invoke_resource, "my_method", "my_output_format")
+ end
+ end
+
+ context "when module_version is given" do
+ before do
+ allow(provider).to receive(:module_info_object).and_return(
+ "@{ModuleName='my_module';ModuleVersion='my_module_version'}"
+ )
+ end
+
+ it "invokes Invoke-DscResource command with module info object" do
+ expect(Chef::Util::Powershell::Cmdlet).to receive(:new).with(
+ node,
+ "Invoke-DscResource -Method my_method -Name my_resource -Property my_properties -Module @{ModuleName='my_module';ModuleVersion='my_module_version'} -Verbose",
+ "my_output_format"
+ ).and_return(cmdlet)
+ provider.send(:invoke_resource, "my_method", "my_output_format")
+ end
+ end
+ end
+end
+
+def set_node_object
+ node = Chef::Node.new
+ node.automatic[:languages][:powershell][:version] = "5.0.10586.0"
+ node
end
diff --git a/spec/unit/provider/execute_spec.rb b/spec/unit/provider/execute_spec.rb
index 4b0afcb928..1901e2ea03 100644
--- a/spec/unit/provider/execute_spec.rb
+++ b/spec/unit/provider/execute_spec.rb
@@ -238,6 +238,5 @@ describe Chef::Provider::Execute do
end
end
-
end
end
diff --git a/spec/unit/provider/group/dscl_spec.rb b/spec/unit/provider/group/dscl_spec.rb
index bc69d7580e..52d43f907d 100644
--- a/spec/unit/provider/group/dscl_spec.rb
+++ b/spec/unit/provider/group/dscl_spec.rb
@@ -28,12 +28,12 @@ describe Chef::Provider::Group::Dscl do
@provider = Chef::Provider::Group::Dscl.new(@new_resource, @run_context)
@provider.current_resource = @current_resource
- @status = double(:stdout => "\n", :stderr => "", :exitstatus => 0)
+ @status = double(stdout: "\n", stderr: "", exitstatus: 0)
allow(@provider).to receive(:shell_out).and_return(@status)
end
it "should run shell_out with the supplied array of arguments appended to the dscl command" do
- expect(@provider).to receive(:shell_out).with("dscl . -cmd /Path arg1 arg2")
+ expect(@provider).to receive(:shell_out).with("dscl", ".", "-cmd", "/Path", "arg1", "arg2")
@provider.dscl("cmd", "/Path", "arg1", "arg2")
end
@@ -51,24 +51,24 @@ describe Chef::Provider::Group::Dscl do
end
it "should run dscl with the supplied cmd /Path args" do
- expect(@provider).to receive(:dscl).with("cmd /Path args")
- @provider.safe_dscl("cmd /Path args")
+ expect(@provider).to receive(:dscl).with(*"cmd /Path args".split(" "))
+ @provider.safe_dscl(*"cmd /Path args".split(" "))
end
describe "with the dscl command returning a non zero exit status for a delete" do
before do
- @status = double("Process::Status", :exitstatus => 1)
+ @status = double("Process::Status", exitstatus: 1)
allow(@provider).to receive(:dscl).and_return(["cmd", @status, "stdout", "stderr"])
end
it "should return an empty string of standard output for a delete" do
- safe_dscl_retval = @provider.safe_dscl("delete /Path args")
+ safe_dscl_retval = @provider.safe_dscl(*"delete /Path args".split(" "))
expect(safe_dscl_retval).to be_a_kind_of(String)
expect(safe_dscl_retval).to eq("")
end
it "should raise an exception for any other command" do
- expect { @provider.safe_dscl("cmd /Path arguments") }.to raise_error(Chef::Exceptions::Group)
+ expect { @provider.safe_dscl(*"cmd /Path arguments".split(" ")) }.to raise_error(Chef::Exceptions::Group)
end
end
@@ -78,13 +78,13 @@ describe Chef::Provider::Group::Dscl do
end
it "should raise an exception" do
- expect { @provider.safe_dscl("cmd /Path arguments") }.to raise_error(Chef::Exceptions::Group)
+ expect { @provider.safe_dscl(*"cmd /Path arguments".split(" ")) }.to raise_error(Chef::Exceptions::Group)
end
end
describe "with the dscl command returning a zero exit status" do
it "should return the third array element, the string of standard output" do
- safe_dscl_retval = @provider.safe_dscl("cmd /Path args")
+ safe_dscl_retval = @provider.safe_dscl(*"cmd /Path args".split(" "))
expect(safe_dscl_retval).to be_a_kind_of(String)
expect(safe_dscl_retval).to eq("stdout")
end
@@ -99,7 +99,7 @@ describe Chef::Provider::Group::Dscl do
end
it "should run safe_dscl with list /Groups gid" do
- expect(@provider).to receive(:safe_dscl).with("list /Groups gid")
+ expect(@provider).to receive(:safe_dscl).with(*"list /Groups gid".split(" "))
@provider.get_free_gid
end
@@ -121,7 +121,7 @@ describe Chef::Provider::Group::Dscl do
end
it "should run safe_dscl with list /Groups gid" do
- expect(@provider).to receive(:safe_dscl).with("list /Groups gid")
+ expect(@provider).to receive(:safe_dscl).with(*"list /Groups gid".split(" "))
@provider.gid_used?(500)
end
@@ -171,8 +171,8 @@ describe Chef::Provider::Group::Dscl do
describe "with a valid gid number which is not already in use" do
it "should run safe_dscl with create /Groups/group PrimaryGroupID gid" do
allow(@provider).to receive(:get_free_gid).and_return(50)
- expect(@provider).to receive(:safe_dscl).with("list /Groups gid")
- expect(@provider).to receive(:safe_dscl).with("create /Groups/aj PrimaryGroupID 50").and_return(true)
+ expect(@provider).to receive(:safe_dscl).with(*"list /Groups gid".split(" "))
+ expect(@provider).to receive(:safe_dscl).with("create", "/Groups/aj", "PrimaryGroupID", 50).and_return(true)
@provider.set_gid
end
end
@@ -193,8 +193,8 @@ describe Chef::Provider::Group::Dscl do
end
it "should run safe_dscl with create /Groups/group GroupMembership to clear the Group's UID list" do
- expect(@provider).to receive(:safe_dscl).with("create /Groups/aj GroupMembers ''").and_return(true)
- expect(@provider).to receive(:safe_dscl).with("create /Groups/aj GroupMembership ''").and_return(true)
+ expect(@provider).to receive(:safe_dscl).with("create", "/Groups/aj", "GroupMembers", "").and_return(true)
+ expect(@provider).to receive(:safe_dscl).with("create", "/Groups/aj", "GroupMembership", "").and_return(true)
@provider.set_members
end
end
@@ -211,9 +211,9 @@ describe Chef::Provider::Group::Dscl do
end
it "should run safe_dscl with append /Groups/group GroupMembership and group members all, your, base" do
- expect(@provider).to receive(:safe_dscl).with("create /Groups/aj GroupMembers ''").and_return(true)
- expect(@provider).to receive(:safe_dscl).with("append /Groups/aj GroupMembership all your base").and_return(true)
- expect(@provider).to receive(:safe_dscl).with("create /Groups/aj GroupMembership ''").and_return(true)
+ expect(@provider).to receive(:safe_dscl).with("create", "/Groups/aj", "GroupMembers", "").and_return(true)
+ expect(@provider).to receive(:safe_dscl).with(*"append /Groups/aj GroupMembership all your base".split(" ")).and_return(true)
+ expect(@provider).to receive(:safe_dscl).with("create", "/Groups/aj", "GroupMembership", "").and_return(true)
@provider.set_members
end
end
@@ -232,20 +232,20 @@ describe Chef::Provider::Group::Dscl do
end
describe "when loading the current system state" do
- before (:each) do
+ before(:each) do
@provider.action = :create
@provider.load_current_resource
@provider.define_resource_requirements
end
it "raises an error if the required binary /usr/bin/dscl doesn't exist" do
- expect(File).to receive(:exists?).with("/usr/bin/dscl").and_return(false)
+ expect(File).to receive(:exist?).with("/usr/bin/dscl").and_return(false)
expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
end
it "doesn't raise an error if /usr/bin/dscl exists" do
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
expect { @provider.process_resource_requirements }.not_to raise_error
end
end
@@ -254,8 +254,8 @@ describe Chef::Provider::Group::Dscl do
it "creates the group, password field, gid, and sets group membership" do
expect(@provider).to receive(:set_gid).and_return(true)
expect(@provider).to receive(:set_members).and_return(true)
- expect(@provider).to receive(:safe_dscl).with("create /Groups/aj Password '*'")
- expect(@provider).to receive(:safe_dscl).with("create /Groups/aj")
+ expect(@provider).to receive(:safe_dscl).with(*"create /Groups/aj Password *".split(" "))
+ expect(@provider).to receive(:safe_dscl).with(*"create /Groups/aj".split(" "))
@provider.create_group
end
end
@@ -265,8 +265,8 @@ describe Chef::Provider::Group::Dscl do
@current_resource.group_name("oldval")
@new_resource.group_name("newname")
expect(@provider).to receive(:set_members).and_return(true)
- expect(@provider).to receive(:safe_dscl).with("create /Groups/newname")
- expect(@provider).to receive(:safe_dscl).with("create /Groups/newname Password '*'")
+ expect(@provider).to receive(:safe_dscl).with(*"create /Groups/newname".split(" "))
+ expect(@provider).to receive(:safe_dscl).with(*"create /Groups/newname Password *".split(" "))
@provider.manage_group
end
@@ -287,7 +287,7 @@ describe Chef::Provider::Group::Dscl do
describe "remove_group" do
it "should run safe_dscl with delete /Groups/group and with the new resources group name" do
- expect(@provider).to receive(:safe_dscl).with("delete /Groups/aj").and_return(true)
+ expect(@provider).to receive(:safe_dscl).with(*"delete /Groups/aj".split(" ")).and_return(true)
@provider.remove_group
end
end
@@ -315,17 +315,17 @@ RecordName: com.apple.aj
RecordType: dsRecTypeStandard:Groups
GroupMembership: waka bar
EOF
- allow(@provider).to receive(:safe_dscl).with("read /Groups/aj").and_return(@output)
+ allow(@provider).to receive(:safe_dscl).with(*"read /Groups/aj".split(" ")).and_return(@output)
@current_resource = @provider.load_current_resource
end
it "should parse gid properly" do
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
expect(@current_resource.gid).to eq("999")
end
it "should parse members properly" do
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
expect(@current_resource.members).to eq(%w{waka bar})
end
end
diff --git a/spec/unit/provider/group/gpasswd_spec.rb b/spec/unit/provider/group/gpasswd_spec.rb
index 16e6ad15ea..add87bf008 100644
--- a/spec/unit/provider/group/gpasswd_spec.rb
+++ b/spec/unit/provider/group/gpasswd_spec.rb
@@ -27,11 +27,11 @@ describe Chef::Provider::Group::Gpasswd, "modify_group_members" do
@new_resource.members %w{lobster rage fist}
@new_resource.append false
@provider = Chef::Provider::Group::Gpasswd.new(@new_resource, @run_context)
- #@provider.stub(:run_command).and_return(true)
+ # @provider.stub(:run_command).and_return(true)
end
describe "when determining the current group state" do
- before (:each) do
+ before(:each) do
@provider.action = :create
@provider.load_current_resource
@provider.define_resource_requirements
@@ -41,13 +41,13 @@ describe Chef::Provider::Group::Gpasswd, "modify_group_members" do
# for Chef::Provider::Group - no need to repeat it here. We'll
# include only what's specific to this provider.
it "should raise an error if the required binary /usr/bin/gpasswd doesn't exist" do
- allow(File).to receive(:exists?).and_return(true)
- expect(File).to receive(:exists?).with("/usr/bin/gpasswd").and_return(false)
+ allow(File).to receive(:exist?).and_return(true)
+ expect(File).to receive(:exist?).with("/usr/bin/gpasswd").and_return(false)
expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
end
it "shouldn't raise an error if the required binaries exist" do
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
expect { @provider.process_resource_requirements }.not_to raise_error
end
end
@@ -66,7 +66,7 @@ describe Chef::Provider::Group::Gpasswd, "modify_group_members" do
it "logs a message and sets group's members to 'none'" do
expect(Chef::Log).to receive(:debug).with("group[wheel] setting group members to: none")
- expect(@provider).to receive(:shell_out!).with("gpasswd -M \"\" wheel")
+ expect(@provider).to receive(:shell_out!).with("gpasswd", "-M", "", "wheel")
@provider.modify_group_members
end
end
@@ -91,7 +91,7 @@ describe Chef::Provider::Group::Gpasswd, "modify_group_members" do
end
it "should run gpasswd with the members joined by ',' followed by the target group" do
- expect(@provider).to receive(:shell_out!).with("gpasswd -M lobster,rage,fist wheel")
+ expect(@provider).to receive(:shell_out!).with("gpasswd", "-M", "lobster,rage,fist", "wheel")
@provider.modify_group_members
end
@@ -104,9 +104,9 @@ describe Chef::Provider::Group::Gpasswd, "modify_group_members" do
it "should run gpasswd individually for each user when the append option is set" do
@new_resource.append(true)
- expect(@provider).to receive(:shell_out!).with("gpasswd -a lobster wheel")
- expect(@provider).to receive(:shell_out!).with("gpasswd -a rage wheel")
- expect(@provider).to receive(:shell_out!).with("gpasswd -a fist wheel")
+ expect(@provider).to receive(:shell_out!).with("gpasswd", "-a", "lobster", "wheel")
+ expect(@provider).to receive(:shell_out!).with("gpasswd", "-a", "rage", "wheel")
+ expect(@provider).to receive(:shell_out!).with("gpasswd", "-a", "fist", "wheel")
@provider.modify_group_members
end
end
diff --git a/spec/unit/provider/group/groupadd_spec.rb b/spec/unit/provider/group/groupadd_spec.rb
index 054d953414..929dd00450 100644
--- a/spec/unit/provider/group/groupadd_spec.rb
+++ b/spec/unit/provider/group/groupadd_spec.rb
@@ -46,7 +46,7 @@ describe Chef::Provider::Group::Groupadd do
describe "#set_options" do
field_list = {
- :gid => "-g",
+ gid: "-g",
}
field_list.each do |attribute, option|
@@ -58,36 +58,37 @@ describe Chef::Provider::Group::Groupadd do
it "should set the option for #{attribute} if the new resources #{attribute} is not null" do
allow(new_resource).to receive(attribute).and_return("wowaweea")
- expect(provider.set_options).to eql(" #{option} '#{new_resource.send(attribute)}' #{new_resource.group_name}")
+ expect(provider.set_options).to eql([ option, new_resource.send(attribute), new_resource.group_name])
end
end
it "should combine all the possible options" do
- match_string = ""
+ match_array = []
field_list.sort { |a, b| a[0] <=> b[0] }.each do |attribute, option|
allow(new_resource).to receive(attribute).and_return("hola")
- match_string << " #{option} 'hola'"
+ match_array << option
+ match_array << "hola"
end
- match_string << " aj"
- expect(provider.set_options).to eql(match_string)
+ match_array << "aj"
+ expect(provider.set_options).to eql(match_array)
end
describe "when we want to create a system group" do
it "should not set groupadd_options '-r' when system is false" do
new_resource.system(false)
- expect(provider.groupadd_options).not_to match(/-r/)
+ expect(provider.groupadd_options).to eq([])
end
it "should set groupadd -r if system is true" do
new_resource.system(true)
- expect(provider.groupadd_options).to eq(" -r")
+ expect(provider.groupadd_options).to eq(["-r"])
end
context "on Solaris" do
before { node.automatic["platform"] = "solaris2" }
it "should not set groupadd -r if system is true" do
new_resource.system(true)
- expect(provider.groupadd_options).not_to match(/-r/)
+ expect(provider.groupadd_options).to eql([])
end
end
end
@@ -95,26 +96,26 @@ describe Chef::Provider::Group::Groupadd do
describe "when we want to create a non_unique gid group" do
it "should not set groupadd_options '-o' when non_unique is false" do
new_resource.non_unique(false)
- expect(provider.groupadd_options).not_to match(/-o/)
+ expect(provider.groupadd_options).to eq([])
end
it "should set groupadd -o if non_unique is true" do
new_resource.non_unique(true)
- expect(provider.groupadd_options).to eq(" -o")
+ expect(provider.groupadd_options).to eq(["-o"])
end
end
end
describe "#create_group" do
before do
- allow(provider).to receive(:run_command).and_return(true)
- allow(provider).to receive(:set_options).and_return(" monkey")
- allow(provider).to receive(:groupadd_options).and_return("")
+ allow(provider).to receive(:shell_out!).and_return(true)
+ allow(provider).to receive(:set_options).and_return("monkey")
+ allow(provider).to receive(:groupadd_options).and_return([])
allow(provider).to receive(:modify_group_members).and_return(true)
end
it "should run groupadd with the return of set_options" do
- expect(provider).to receive(:run_command).with({ :command => "groupadd monkey" }).and_return(true)
+ expect(provider).to receive(:shell_out!).with("groupadd", "monkey").and_return(true)
provider.create_group
end
@@ -126,13 +127,13 @@ describe Chef::Provider::Group::Groupadd do
describe "#manage_group" do
before do
- allow(provider).to receive(:run_command).and_return(true)
- allow(provider).to receive(:set_options).and_return(" monkey")
+ allow(provider).to receive(:shell_out!).and_return(true)
+ allow(provider).to receive(:set_options).and_return("monkey")
end
it "should run groupmod with the return of set_options" do
allow(provider).to receive(:modify_group_members).and_return(true)
- expect(provider).to receive(:run_command).with({ :command => "groupmod monkey" }).and_return(true)
+ expect(provider).to receive(:shell_out!).with("groupmod", "monkey").and_return(true)
provider.manage_group
end
@@ -144,12 +145,12 @@ describe Chef::Provider::Group::Groupadd do
describe "#remove_group" do
before do
- allow(provider).to receive(:run_command).and_return(true)
- allow(provider).to receive(:set_options).and_return(" monkey")
+ allow(provider).to receive(:shell_out!).and_return(true)
+ allow(provider).to receive(:set_options).and_return("monkey")
end
it "should run groupdel with the new resources group name" do
- expect(provider).to receive(:run_command).with({ :command => "groupdel aj" }).and_return(true)
+ expect(provider).to receive(:shell_out!).with("groupdel", "aj").and_return(true)
provider.remove_group
end
end
@@ -162,30 +163,30 @@ describe Chef::Provider::Group::Groupadd do
describe "#load_current_resource" do
before do
- allow(provider).to receive(:run_command).and_return(true)
- allow(provider).to receive(:set_options).and_return(" monkey")
+ allow(provider).to receive(:shell_out!).and_return(true)
+ allow(provider).to receive(:set_options).and_return("monkey")
end
before do
- allow(File).to receive(:exists?).and_return(false)
+ allow(File).to receive(:exist?).and_return(false)
provider.define_resource_requirements
end
it "should raise an error if the required binary /usr/sbin/groupadd doesn't exist" do
- expect(File).to receive(:exists?).with("/usr/sbin/groupadd").and_return(false)
+ expect(File).to receive(:exist?).with("/usr/sbin/groupadd").and_return(false)
expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
end
it "should raise an error if the required binary /usr/sbin/groupmod doesn't exist" do
- expect(File).to receive(:exists?).with("/usr/sbin/groupadd").and_return(true)
- expect(File).to receive(:exists?).with("/usr/sbin/groupmod").and_return(false)
+ expect(File).to receive(:exist?).with("/usr/sbin/groupadd").and_return(true)
+ expect(File).to receive(:exist?).with("/usr/sbin/groupmod").and_return(false)
expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
end
it "should raise an error if the required binary /usr/sbin/groupdel doesn't exist" do
- expect(File).to receive(:exists?).with("/usr/sbin/groupadd").and_return(true)
- expect(File).to receive(:exists?).with("/usr/sbin/groupmod").and_return(true)
- expect(File).to receive(:exists?).with("/usr/sbin/groupdel").and_return(false)
+ expect(File).to receive(:exist?).with("/usr/sbin/groupadd").and_return(true)
+ expect(File).to receive(:exist?).with("/usr/sbin/groupmod").and_return(true)
+ expect(File).to receive(:exist?).with("/usr/sbin/groupdel").and_return(false)
expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
end
diff --git a/spec/unit/provider/group/groupmod_spec.rb b/spec/unit/provider/group/groupmod_spec.rb
index 21d026409e..6629b718d0 100644
--- a/spec/unit/provider/group/groupmod_spec.rb
+++ b/spec/unit/provider/group/groupmod_spec.rb
@@ -33,17 +33,17 @@ describe Chef::Provider::Group::Groupmod do
describe "manage_group" do
describe "when determining the current group state" do
it "should raise an error if the required binary /usr/sbin/group doesn't exist" do
- expect(File).to receive(:exists?).with("/usr/sbin/group").and_return(false)
+ expect(File).to receive(:exist?).with("/usr/sbin/group").and_return(false)
expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Group)
end
it "should raise an error if the required binary /usr/sbin/user doesn't exist" do
- expect(File).to receive(:exists?).with("/usr/sbin/group").and_return(true)
- expect(File).to receive(:exists?).with("/usr/sbin/user").and_return(false)
+ expect(File).to receive(:exist?).with("/usr/sbin/group").and_return(true)
+ expect(File).to receive(:exist?).with("/usr/sbin/user").and_return(false)
expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Group)
end
it "shouldn't raise an error if the required binaries exist" do
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
expect { @provider.load_current_resource }.not_to raise_error
end
end
@@ -62,9 +62,9 @@ describe Chef::Provider::Group::Groupmod do
it "logs a message and sets group's members to 'none', then removes existing group members" do
expect(Chef::Log).to receive(:debug).with("group[wheel] setting group members to: none")
- expect(@provider).to receive(:shell_out!).with("group mod -n wheel_bak wheel")
- expect(@provider).to receive(:shell_out!).with("group add -g '123' -o wheel")
- expect(@provider).to receive(:shell_out!).with("group del wheel_bak")
+ expect(@provider).to receive(:shell_out!).with("group", "mod", "-n", "wheel_bak", "wheel")
+ expect(@provider).to receive(:shell_out!).with("group", "add", "-g", "123", "-o", "wheel")
+ expect(@provider).to receive(:shell_out!).with("group", "del", "wheel_bak")
@provider.manage_group
end
end
@@ -90,10 +90,10 @@ describe Chef::Provider::Group::Groupmod do
it "updates group membership correctly" do
allow(Chef::Log).to receive(:debug)
- expect(@provider).to receive(:shell_out!).with("group mod -n wheel_bak wheel")
- expect(@provider).to receive(:shell_out!).with("user mod -G wheel lobster")
- expect(@provider).to receive(:shell_out!).with("group add -g '123' -o wheel")
- expect(@provider).to receive(:shell_out!).with("group del wheel_bak")
+ expect(@provider).to receive(:shell_out!).with("group", "mod", "-n", "wheel_bak", "wheel")
+ expect(@provider).to receive(:shell_out!).with("user", "mod", "-G", "wheel", "lobster")
+ expect(@provider).to receive(:shell_out!).with("group", "add", "-g", "123", "-o", "wheel")
+ expect(@provider).to receive(:shell_out!).with("group", "del", "wheel_bak")
@provider.manage_group
end
end
@@ -108,10 +108,10 @@ describe Chef::Provider::Group::Groupmod do
end
it "should run a group add command and some user mod commands" do
- expect(@provider).to receive(:shell_out!).with("group add -g '123' wheel")
- expect(@provider).to receive(:shell_out!).with("user mod -G wheel lobster")
- expect(@provider).to receive(:shell_out!).with("user mod -G wheel rage")
- expect(@provider).to receive(:shell_out!).with("user mod -G wheel fist")
+ expect(@provider).to receive(:shell_out!).with("group", "add", "-g", "123", "wheel")
+ expect(@provider).to receive(:shell_out!).with("user", "mod", "-G", "wheel", "lobster")
+ expect(@provider).to receive(:shell_out!).with("user", "mod", "-G", "wheel", "rage")
+ expect(@provider).to receive(:shell_out!).with("user", "mod", "-G", "wheel", "fist")
@provider.create_group
end
end
@@ -125,7 +125,7 @@ describe Chef::Provider::Group::Groupmod do
end
it "should run a group del command" do
- expect(@provider).to receive(:shell_out!).with("group del wheel")
+ expect(@provider).to receive(:shell_out!).with("group", "del", "wheel")
@provider.remove_group
end
end
diff --git a/spec/unit/provider/group/pw_spec.rb b/spec/unit/provider/group/pw_spec.rb
index 97ffcb3c31..f109ba6ba1 100644
--- a/spec/unit/provider/group/pw_spec.rb
+++ b/spec/unit/provider/group/pw_spec.rb
@@ -37,19 +37,19 @@ describe Chef::Provider::Group::Pw do
describe "when setting options for the pw command" do
it "does not set the gid option if gids match or are unmanaged" do
- expect(@provider.set_options).to eq(" wheel")
+ expect(@provider.set_options).to eq(["wheel"])
end
it "sets the option for gid if it is not nil" do
@new_resource.gid(42)
- expect(@provider.set_options).to eql(" wheel -g '42'")
+ expect(@provider.set_options).to eql(["wheel", "-g", 42])
end
end
describe "when creating a group" do
it "should run pw groupadd with the return of set_options and set_members_option" do
@new_resource.gid(23)
- expect(@provider).to receive(:run_command).with({ :command => "pw groupadd wheel -g '23' -M root,aj" }).and_return(true)
+ expect(@provider).to receive(:shell_out!).with("pw", "groupadd", "wheel", "-g", "23", "-M", "root,aj").and_return(true)
@provider.create_group
end
end
@@ -59,8 +59,8 @@ describe Chef::Provider::Group::Pw do
it "should run pw groupmod with the return of set_options" do
@new_resource.gid(42)
@new_resource.members(["someone"])
- expect(@provider).to receive(:run_command).with({ :command => "pw groupmod wheel -g '42' -m someone" }).and_return(true)
- expect(@provider).to receive(:run_command).with({ :command => "pw groupmod wheel -g '42' -d root,aj" }).and_return(true)
+ expect(@provider).to receive(:shell_out!).with("pw", "groupmod", "wheel", "-g", "42", "-m", "someone").and_return(true)
+ expect(@provider).to receive(:shell_out!).with("pw", "groupmod", "wheel", "-g", "42", "-d", "root,aj").and_return(true)
@provider.manage_group
end
@@ -68,7 +68,7 @@ describe Chef::Provider::Group::Pw do
describe "when removing the group" do
it "should run pw groupdel with the new resources group name" do
- expect(@provider).to receive(:run_command).with({ :command => "pw groupdel wheel" }).and_return(true)
+ expect(@provider).to receive(:shell_out!).with("pw", "groupdel", "wheel").and_return(true)
@provider.remove_group
end
end
@@ -98,7 +98,7 @@ describe Chef::Provider::Group::Pw do
end
it "should set the -d option with the members joined by ','" do
- expect(@provider.set_members_options).to eql([ " -d all,your,base" ])
+ expect(@provider.set_members_options).to eql([ ["-d", "all,your,base"] ])
end
end
@@ -114,24 +114,24 @@ describe Chef::Provider::Group::Pw do
end
it "should set the -m option with the members joined by ','" do
- expect(@provider.set_members_options).to eql([ " -m all,your,base" ])
+ expect(@provider.set_members_options).to eql([[ "-m", "all,your,base" ]])
end
end
end
describe "load_current_resource" do
- before (:each) do
+ before(:each) do
@provider.action = :create
@provider.load_current_resource
@provider.define_resource_requirements
end
it "should raise an error if the required binary /usr/sbin/pw doesn't exist" do
- expect(File).to receive(:exists?).with("/usr/sbin/pw").and_return(false)
+ expect(File).to receive(:exist?).with("/usr/sbin/pw").and_return(false)
expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
end
it "shouldn't raise an error if /usr/sbin/pw exists" do
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
expect { @provider.process_resource_requirements }.not_to raise_error
end
end
diff --git a/spec/unit/provider/group/suse_spec.rb b/spec/unit/provider/group/suse_spec.rb
index da4e8e9155..e61d865b6d 100644
--- a/spec/unit/provider/group/suse_spec.rb
+++ b/spec/unit/provider/group/suse_spec.rb
@@ -7,7 +7,7 @@
# 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
+#      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,
@@ -47,7 +47,7 @@ describe Chef::Provider::Group::Suse do
describe "when determining the current group state" do
before(:each) do
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
provider.action = :create
provider.define_resource_requirements
end
@@ -56,7 +56,7 @@ describe Chef::Provider::Group::Suse do
# for Chef::Provider::Group - no need to repeat it here. We'll
# include only what's specific to this provider.
it "should raise an error if the required binary /usr/sbin/groupmod doesn't exist" do
- expect(File).to receive(:exists?).with("/usr/sbin/groupmod").and_return(false)
+ expect(File).to receive(:exist?).with("/usr/sbin/groupmod").and_return(false)
expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
end
@@ -76,14 +76,14 @@ describe Chef::Provider::Group::Suse do
describe "#add_member" do
it "should call out to groupmod to add user" do
- expect(provider).to receive(:shell_out!).with("groupmod -A new_user new_group")
+ expect(provider).to receive(:shell_out!).with("groupmod", "-A", "new_user", "new_group")
provider.add_member("new_user")
end
end
describe "#remove_member" do
it "should call out to groupmod to remove user" do
- expect(provider).to receive(:shell_out!).with("groupmod -R new_user new_group")
+ expect(provider).to receive(:shell_out!).with("groupmod", "-R", "new_user", "new_group")
provider.remove_member("new_user")
end
end
diff --git a/spec/unit/provider/group/usermod_spec.rb b/spec/unit/provider/group/usermod_spec.rb
index 7bd45c4f1b..c6422b12c9 100644
--- a/spec/unit/provider/group/usermod_spec.rb
+++ b/spec/unit/provider/group/usermod_spec.rb
@@ -46,18 +46,18 @@ describe Chef::Provider::Group::Usermod do
describe "with supplied members" do
platforms = {
- "openbsd" => "-G",
- "netbsd" => "-G",
- "solaris" => "-a -G",
- "suse" => "-a -G",
- "opensuse" => "-a -G",
- "smartos" => "-G",
- "omnios" => "-G",
+ "openbsd" => [ "-G" ],
+ "netbsd" => [ "-G" ],
+ "solaris" => [ "-a", "-G" ],
+ "suse" => [ "-a", "-G" ],
+ "opensuse" => [ "-a", "-G" ],
+ "smartos" => [ "-G" ],
+ "omnios" => [ "-G" ],
}
before do
allow(@new_resource).to receive(:members).and_return(%w{all your base})
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
end
it "should raise an error when setting the entire group directly" do
@@ -85,9 +85,9 @@ describe Chef::Provider::Group::Usermod do
@provider.current_resource = current_resource
@node.automatic_attrs[:platform] = platform
allow(@new_resource).to receive(:append).and_return(true)
- expect(@provider).to receive(:shell_out!).with("usermod #{flags} wheel all")
- expect(@provider).to receive(:shell_out!).with("usermod #{flags} wheel your")
- expect(@provider).to receive(:shell_out!).with("usermod #{flags} wheel base")
+ expect(@provider).to receive(:shell_out!).with("usermod", *flags, "wheel", "all")
+ expect(@provider).to receive(:shell_out!).with("usermod", *flags, "wheel", "your")
+ expect(@provider).to receive(:shell_out!).with("usermod", *flags, "wheel", "base")
@provider.modify_group_members
end
end
@@ -96,19 +96,19 @@ describe Chef::Provider::Group::Usermod do
describe "when loading the current resource" do
before(:each) do
- allow(File).to receive(:exists?).and_return(false)
+ allow(File).to receive(:exist?).and_return(false)
@provider.action = :create
@provider.define_resource_requirements
end
it "should raise an error if the required binary /usr/sbin/usermod doesn't exist" do
- allow(File).to receive(:exists?).and_return(true)
- expect(File).to receive(:exists?).with("/usr/sbin/usermod").and_return(false)
+ allow(File).to receive(:exist?).and_return(true)
+ expect(File).to receive(:exist?).with("/usr/sbin/usermod").and_return(false)
expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
end
it "shouldn't raise an error if the required binaries exist" do
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
expect { @provider.process_resource_requirements }.not_to raise_error
end
end
diff --git a/spec/unit/provider/ifconfig/aix_spec.rb b/spec/unit/provider/ifconfig/aix_spec.rb
index 7847fc9a5f..7f316c952b 100644
--- a/spec/unit/provider/ifconfig/aix_spec.rb
+++ b/spec/unit/provider/ifconfig/aix_spec.rb
@@ -48,7 +48,7 @@ IFCONFIG
describe "#load_current_resource" do
before do
- @status = double(:stdout => @ifconfig_output, :exitstatus => 0)
+ @status = double(stdout: @ifconfig_output, exitstatus: 0)
allow(@provider).to receive(:shell_out).and_return(@status)
@new_resource.device "en0"
end
@@ -68,11 +68,11 @@ IFCONFIG
it "should add an interface if it does not exist" do
@new_resource.device "en10"
allow(@provider).to receive(:load_current_resource) do
- @provider.instance_variable_set("@status", double("Status", :exitstatus => 0))
+ @provider.instance_variable_set("@status", double("Status", exitstatus: 0))
@provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context))
end
command = "chdev -l #{@new_resource.device} -a netaddr=#{@new_resource.name}"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
@provider.run_action(:add)
expect(@new_resource).to be_updated
@@ -82,7 +82,7 @@ IFCONFIG
@new_resource.device "en0"
@new_resource.metric "1"
allow(@provider).to receive(:load_current_resource) do
- @provider.instance_variable_set("@status", double("Status", :exitstatus => 0))
+ @provider.instance_variable_set("@status", double("Status", exitstatus: 0))
@provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context))
end
@@ -94,11 +94,11 @@ IFCONFIG
it "should enable an interface if it does not exist" do
@new_resource.device "en10"
allow(@provider).to receive(:load_current_resource) do
- @provider.instance_variable_set("@status", double("Status", :exitstatus => 0))
+ @provider.instance_variable_set("@status", double("Status", exitstatus: 0))
@provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context))
end
command = "ifconfig #{@new_resource.device} #{@new_resource.name}"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
@provider.run_action(:enable)
expect(@new_resource).to be_updated
@@ -110,11 +110,11 @@ IFCONFIG
it "should not disable an interface if it does not exist" do
@new_resource.device "en10"
allow(@provider).to receive(:load_current_resource) do
- @provider.instance_variable_set("@status", double("Status", :exitstatus => 0))
+ @provider.instance_variable_set("@status", double("Status", exitstatus: 0))
@provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context))
end
- expect(@provider).not_to receive(:run_command)
+ expect(@provider).not_to receive(:shell_out!)
@provider.run_action(:disable)
expect(@new_resource).not_to be_updated
@@ -124,7 +124,7 @@ IFCONFIG
before do
@new_resource.device "en10"
allow(@provider).to receive(:load_current_resource) do
- @provider.instance_variable_set("@status", double("Status", :exitstatus => 0))
+ @provider.instance_variable_set("@status", double("Status", exitstatus: 0))
current_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)
current_resource.device @new_resource.device
@provider.instance_variable_set("@current_resource", current_resource)
@@ -133,7 +133,7 @@ IFCONFIG
it "should disable an interface if it exists" do
command = "ifconfig #{@new_resource.device} down"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
@provider.run_action(:disable)
expect(@new_resource).to be_updated
@@ -147,11 +147,11 @@ IFCONFIG
it "should not delete an interface if it does not exist" do
@new_resource.device "en10"
allow(@provider).to receive(:load_current_resource) do
- @provider.instance_variable_set("@status", double("Status", :exitstatus => 0))
+ @provider.instance_variable_set("@status", double("Status", exitstatus: 0))
@provider.instance_variable_set("@current_resource", Chef::Resource::Ifconfig.new("10.0.0.1", @run_context))
end
- expect(@provider).not_to receive(:run_command)
+ expect(@provider).not_to receive(:shell_out!)
@provider.run_action(:delete)
expect(@new_resource).not_to be_updated
@@ -161,7 +161,7 @@ IFCONFIG
before do
@new_resource.device "en10"
allow(@provider).to receive(:load_current_resource) do
- @provider.instance_variable_set("@status", double("Status", :exitstatus => 0))
+ @provider.instance_variable_set("@status", double("Status", exitstatus: 0))
current_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)
current_resource.device @new_resource.device
@provider.instance_variable_set("@current_resource", current_resource)
@@ -170,7 +170,7 @@ IFCONFIG
it "should delete an interface if it exists" do
command = "chdev -l #{@new_resource.device} -a state=down"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
@provider.run_action(:delete)
expect(@new_resource).to be_updated
diff --git a/spec/unit/provider/ifconfig/debian_spec.rb b/spec/unit/provider/ifconfig/debian_spec.rb
index 1f61957721..9a90dc1e0a 100644
--- a/spec/unit/provider/ifconfig/debian_spec.rb
+++ b/spec/unit/provider/ifconfig/debian_spec.rb
@@ -40,12 +40,12 @@ describe Chef::Provider::Ifconfig::Debian do
let(:current_resource) { Chef::Resource::Ifconfig.new("10.0.0.1", run_context) }
let(:provider) do
- status = double("Status", :exitstatus => 0)
+ status = double("Status", exitstatus: 0)
provider = Chef::Provider::Ifconfig::Debian.new(new_resource, run_context)
provider.instance_variable_set("@status", status)
provider.current_resource = current_resource
allow(provider).to receive(:load_current_resource)
- allow(provider).to receive(:run_command)
+ allow(provider).to receive(:shell_out!)
provider
end
@@ -77,12 +77,12 @@ describe Chef::Provider::Ifconfig::Debian do
context "when the interface_dot_d directory does not exist" do
before do
FileUtils.rmdir tempdir_path
- expect(File.exists?(tempdir_path)).to be_falsey
+ expect(File.exist?(tempdir_path)).to be_falsey
end
it "should create the /etc/network/interfaces.d directory" do
provider.run_action(:add)
- expect(File.exists?(tempdir_path)).to be_truthy
+ expect(File.exist?(tempdir_path)).to be_truthy
expect(File.directory?(tempdir_path)).to be_truthy
end
@@ -94,7 +94,7 @@ describe Chef::Provider::Ifconfig::Debian do
context "when the interface_dot_d directory exists" do
before do
- expect(File.exists?(tempdir_path)).to be_truthy
+ expect(File.exist?(tempdir_path)).to be_truthy
end
it "should still mark the resource as updated (we still write a file to it)" do
@@ -114,13 +114,7 @@ describe Chef::Provider::Ifconfig::Debian do
before do
stub_const("Chef::Provider::Ifconfig::Debian::INTERFACES_FILE", tempfile.path)
stub_const("Chef::Provider::Ifconfig::Debian::INTERFACES_DOT_D_DIR", tempdir_path)
- config_file_ifcfg = StringIO.new(<<-EOF
-iface eth0 inet static
- address 10.0.0.1
- netmask 255.255.254.0
-EOF
- )
- expect(File.exists?(tempdir_path)).to be_truthy # since the file exists, the enclosing dir must also exist
+ expect(File.exist?(tempdir_path)).to be_truthy # since the file exists, the enclosing dir must also exist
end
context "when the /etc/network/interfaces file has the source line" do
@@ -210,12 +204,12 @@ EOF
context "when the interface_dot_d directory does not exist" do
before do
FileUtils.rmdir tempdir_path
- expect(File.exists?(tempdir_path)).to be_falsey
+ expect(File.exist?(tempdir_path)).to be_falsey
end
it "should not create the /etc/network/interfaces.d directory" do
provider.run_action(:add)
- expect(File.exists?(tempdir_path)).not_to be_truthy
+ expect(File.exist?(tempdir_path)).not_to be_truthy
end
it "should mark the resource as updated" do
@@ -226,7 +220,7 @@ EOF
context "when the interface_dot_d directory exists" do
before do
- expect(File.exists?(tempdir_path)).to be_truthy
+ expect(File.exist?(tempdir_path)).to be_truthy
end
it "should still mark the resource as updated (we still write a file to it)" do
@@ -246,14 +240,8 @@ EOF
before do
stub_const("Chef::Provider::Ifconfig::Debian::INTERFACES_FILE", tempfile.path)
stub_const("Chef::Provider::Ifconfig::Debian::INTERFACES_DOT_D_DIR", tempdir_path)
- config_file_ifcfg = StringIO.new(<<-EOF
-iface eth0 inet static
- address 10.0.0.1
- netmask 255.255.254.0
- EOF
- )
expect(File).not_to receive(:new).with(config_filename_ifcfg, "w")
- expect(File.exists?(tempdir_path)).to be_truthy # since the file exists, the enclosing dir must also exist
+ expect(File.exist?(tempdir_path)).to be_truthy # since the file exists, the enclosing dir must also exist
end
context "when the /etc/network/interfaces file has the source line" do
diff --git a/spec/unit/provider/ifconfig/redhat_spec.rb b/spec/unit/provider/ifconfig/redhat_spec.rb
index 0088cef9f9..2111de02fb 100644
--- a/spec/unit/provider/ifconfig/redhat_spec.rb
+++ b/spec/unit/provider/ifconfig/redhat_spec.rb
@@ -25,7 +25,7 @@ describe Chef::Provider::Ifconfig::Redhat do
@cookbook_collection = Chef::CookbookCollection.new([])
@events = Chef::EventDispatch::Dispatcher.new
@run_context = Chef::RunContext.new(@node, @cookbook_collection, @events)
- #This new_resource can be called anything --> it is not the same as in ifconfig.rb
+ # This new_resource can be called anything --> it is not the same as in ifconfig.rb
@new_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)
@new_resource.mask "255.255.254.0"
@new_resource.metric "1"
@@ -34,7 +34,7 @@ describe Chef::Provider::Ifconfig::Redhat do
@provider = Chef::Provider::Ifconfig::Redhat.new(@new_resource, @run_context)
@current_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)
- status = double("Status", :exitstatus => 0)
+ status = double("Status", exitstatus: 0)
@provider.instance_variable_set("@status", status)
@provider.current_resource = @current_resource
@@ -47,7 +47,7 @@ describe Chef::Provider::Ifconfig::Redhat do
it "should write network-script for centos" do
allow(@provider).to receive(:load_current_resource)
- allow(@provider).to receive(:run_command)
+ allow(@provider).to receive(:shell_out!)
expect(@config).to receive(:content) do |arg|
expect(arg).to match(/^\s*DEVICE=eth0\s*$/)
expect(arg).to match(/^\s*IPADDR=10\.0\.0\.1\s*$/)
@@ -64,7 +64,7 @@ describe Chef::Provider::Ifconfig::Redhat do
it "should delete network-script if it exists for centos" do
@current_resource.device @new_resource.device
allow(@provider).to receive(:load_current_resource)
- allow(@provider).to receive(:run_command)
+ allow(@provider).to receive(:shell_out!)
expect(@config).to receive(:run_action).with(:delete)
expect(@config).to receive(:updated?).and_return(true)
@provider.run_action(:delete)
diff --git a/spec/unit/provider/ifconfig_spec.rb b/spec/unit/provider/ifconfig_spec.rb
index db45640169..da27d647ee 100644
--- a/spec/unit/provider/ifconfig_spec.rb
+++ b/spec/unit/provider/ifconfig_spec.rb
@@ -16,7 +16,7 @@
# limitations under the License.
#
-#require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
+# require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
require "spec_helper"
require "chef/exceptions"
@@ -26,7 +26,7 @@ describe Chef::Provider::Ifconfig do
@cookbook_collection = Chef::CookbookCollection.new([])
@events = Chef::EventDispatch::Dispatcher.new
@run_context = Chef::RunContext.new(@node, @cookbook_collection, @events)
- #This new_resource can be called anything --> it is not the same as in ifconfig.rb
+ # This new_resource can be called anything --> it is not the same as in ifconfig.rb
@new_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)
@new_resource.mask "255.255.254.0"
@new_resource.metric "1"
@@ -35,14 +35,14 @@ describe Chef::Provider::Ifconfig do
@provider = Chef::Provider::Ifconfig.new(@new_resource, @run_context)
@current_resource = Chef::Resource::Ifconfig.new("10.0.0.1", @run_context)
- status = double("Status", :exitstatus => 0)
+ status = double("Status", exitstatus: 0)
@provider.instance_variable_set("@status", status)
@provider.current_resource = @current_resource
end
describe Chef::Provider::Ifconfig, "load_current_resource" do
before do
- @status = double(:stdout => "", :exitstatus => 1)
+ @status = double(stdout: "", exitstatus: 1)
allow(@provider).to receive(:shell_out).and_return(@status)
@provider.load_current_resource
end
@@ -57,11 +57,10 @@ describe Chef::Provider::Ifconfig do
describe Chef::Provider::Ifconfig, "action_add" do
it "should add an interface if it does not exist" do
- #@provider.stub(:run_command).and_return(true)
allow(@provider).to receive(:load_current_resource)
@current_resource.inet_addr nil
command = "ifconfig eth0 10.0.0.1 netmask 255.255.254.0 metric 1 mtu 1500"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
expect(@provider).to receive(:generate_config)
@provider.run_action(:add)
@@ -72,7 +71,7 @@ describe Chef::Provider::Ifconfig do
allow(@provider).to receive(:load_current_resource)
@new_resource.target "172.16.32.2"
command = "ifconfig eth0 172.16.32.2 netmask 255.255.254.0 metric 1 mtu 1500"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
@provider.run_action(:add)
expect(@new_resource).to be_updated
@@ -80,7 +79,7 @@ describe Chef::Provider::Ifconfig do
it "should not add an interface if it already exists" do
allow(@provider).to receive(:load_current_resource)
- expect(@provider).not_to receive(:run_command)
+ expect(@provider).not_to receive(:shell_out!)
@current_resource.inet_addr "10.0.0.1"
expect(@provider).to receive(:generate_config)
@@ -88,9 +87,9 @@ describe Chef::Provider::Ifconfig do
expect(@new_resource).not_to be_updated
end
- #We are not testing this case with the assumption that anyone writing the cookbook would not make a typo == lo
- #it "should add a blank command if the #{@new_resource.device} == lo" do
- #end
+ # We are not testing this case with the assumption that anyone writing the cookbook would not make a typo == lo
+ # it "should add a blank command if the #{@new_resource.device} == lo" do
+ # end
end
describe Chef::Provider::Ifconfig, "action_enable" do
@@ -99,7 +98,7 @@ describe Chef::Provider::Ifconfig do
allow(@provider).to receive(:load_current_resource)
@current_resource.inet_addr nil
command = "ifconfig eth0 10.0.0.1 netmask 255.255.254.0 metric 1 mtu 1500"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
expect(@provider).not_to receive(:generate_config)
@provider.run_action(:enable)
@@ -110,7 +109,7 @@ describe Chef::Provider::Ifconfig do
allow(@provider).to receive(:load_current_resource)
@new_resource.target "172.16.32.2"
command = "ifconfig eth0 172.16.32.2 netmask 255.255.254.0 metric 1 mtu 1500"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
@provider.run_action(:enable)
expect(@new_resource).to be_updated
@@ -133,7 +132,7 @@ describe Chef::Provider::Ifconfig do
allow(@provider).to receive(:load_current_resource)
@current_resource.device "eth0"
command = "ifconfig #{@new_resource.device} down"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
expect(@provider).to receive(:delete_config)
@provider.run_action(:delete)
@@ -142,7 +141,7 @@ describe Chef::Provider::Ifconfig do
it "should not delete interface if it does not exist" do
allow(@provider).to receive(:load_current_resource)
- expect(@provider).not_to receive(:run_command)
+ expect(@provider).not_to receive(:shell_out!)
expect(@provider).to receive(:delete_config)
@provider.run_action(:delete)
@@ -156,7 +155,7 @@ describe Chef::Provider::Ifconfig do
allow(@provider).to receive(:load_current_resource)
@current_resource.device "eth0"
command = "ifconfig #{@new_resource.device} down"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
expect(@provider).not_to receive(:delete_config)
@provider.run_action(:disable)
@@ -165,7 +164,7 @@ describe Chef::Provider::Ifconfig do
it "should not delete interface if it does not exist" do
allow(@provider).to receive(:load_current_resource)
- expect(@provider).not_to receive(:run_command)
+ expect(@provider).not_to receive(:shell_out!)
expect(@provider).not_to receive(:delete_config)
@provider.run_action(:disable)
@@ -179,7 +178,7 @@ describe Chef::Provider::Ifconfig do
allow(@provider).to receive(:load_current_resource)
@current_resource.device "eth0"
command = "ifconfig #{@new_resource.device} down"
- expect(@provider).to receive(:run_command).with(:command => command)
+ expect(@provider).to receive(:shell_out!).with(*command.split(" "))
expect(@provider).to receive(:delete_config)
@provider.run_action(:delete)
@@ -190,7 +189,7 @@ describe Chef::Provider::Ifconfig do
# This is so that our fake values do not get overwritten
allow(@provider).to receive(:load_current_resource)
# This is so that nothing actually runs
- expect(@provider).not_to receive(:run_command)
+ expect(@provider).not_to receive(:shell_out!)
expect(@provider).to receive(:delete_config)
@provider.run_action(:delete)
diff --git a/spec/unit/provider/launchd_spec.rb b/spec/unit/provider/launchd_spec.rb
index 2893044833..693801f99b 100644
--- a/spec/unit/provider/launchd_spec.rb
+++ b/spec/unit/provider/launchd_spec.rb
@@ -40,7 +40,7 @@ describe Chef::Provider::Launchd do
\t<string>/Library/scripts/call_mom.sh</string>
\t<key>StartCalendarInterval</key>
\t<dict>
-\t\t<key>Hourly</key>
+\t\t<key>Hour</key>
\t\t<integer>10</integer>
\t\t<key>Weekday</key>
\t\t<integer>7</integer>
@@ -50,13 +50,42 @@ describe Chef::Provider::Launchd do
</dict>
</plist>
XML
+ let(:test_plist_multiple_intervals) { String.new <<-XML }
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+\t<key>Label</key>
+\t<string>call.mom.weekly</string>
+\t<key>Program</key>
+\t<string>/Library/scripts/call_mom.sh</string>
+\t<key>StartCalendarInterval</key>
+\t<array>
+\t\t<dict>
+\t\t\t<key>Hour</key>
+\t\t\t<integer>11</integer>
+\t\t\t<key>Weekday</key>
+\t\t\t<integer>1</integer>
+\t\t</dict>
+\t\t<dict>
+\t\t\t<key>Hour</key>
+\t\t\t<integer>12</integer>
+\t\t\t<key>Weekday</key>
+\t\t\t<integer>2</integer>
+\t\t</dict>
+\t</array>
+\t<key>TimeOut</key>
+\t<integer>300</integer>
+</dict>
+</plist>
+XML
let(:test_hash) do
{
"Label" => "call.mom.weekly",
"Program" => "/Library/scripts/call_mom.sh",
"StartCalendarInterval" => {
- "Hourly" => 10,
+ "Hour" => 10,
"Weekday" => 7,
},
"TimeOut" => 300,
@@ -100,15 +129,64 @@ XML
it "should produce the test_plist from properties" do
new_resource.program "/Library/scripts/call_mom.sh"
new_resource.time_out 300
- new_resource.start_calendar_interval "Hourly" => 10, "Weekday" => 7
+ new_resource.start_calendar_interval "Hour" => 10, "Weekday" => 7
expect(provider.content?).to be_truthy
expect(provider.content).to eql(test_plist)
end
end
+ describe "start_calendar_interval is passed" do
+ it "should allow array of Hashes" do
+ allowed = (1..2).collect do |num|
+ {
+ "Hour" => 10 + num,
+ "Weekday" => num,
+ }
+ end
+ new_resource.program "/Library/scripts/call_mom.sh"
+ new_resource.time_out 300
+ new_resource.start_calendar_interval allowed
+ expect(provider.content?).to be_truthy
+ expect(provider.content).to eql(test_plist_multiple_intervals)
+ end
+
+ it "should allow all StartCalendarInterval keys" do
+ allowed = {
+ "Minute" => 1,
+ "Hour" => 1,
+ "Day" => 1,
+ "Weekday" => 1,
+ "Month" => 1,
+ }
+ new_resource.program "/Library/scripts/call_mom.sh"
+ new_resource.time_out 300
+ new_resource.start_calendar_interval allowed
+ expect(provider.content?).to be_truthy
+ %w{Minute Hour Day Weekday Month}.each do |key|
+ expect(provider.content).to include("<key>#{key}</key>")
+ end
+ end
+
+ it "should not allow invalid ShowCalendarInterval keys" do
+ new_resource.program "/Library/scripts/call_mom.sh"
+ new_resource.time_out 300
+ expect do
+ new_resource.start_calendar_interval "Hourly" => 1
+ end.to raise_error(/Hourly are invalid/)
+ end
+
+ it "should not allow non-integer values" do
+ new_resource.program "/Library/scripts/call_mom.sh"
+ new_resource.time_out 300
+ expect do
+ new_resource.start_calendar_interval "Weekday" => "1-2"
+ end.to raise_error(/Invalid value.*\(1-2\)/)
+ end
+ end
+
describe "hash is passed" do
- it "should produce the test_plist from the hash" do
- new_resource.hash test_hash
+ it "should produce the test_plist content from the plist_hash property" do
+ new_resource.plist_hash test_hash
expect(provider.content?).to be_truthy
expect(provider.content).to eql(test_plist)
end
diff --git a/spec/unit/provider/mount/mount_spec.rb b/spec/unit/provider/mount/mount_spec.rb
index 0b956d9bb9..20a4fd88dd 100644
--- a/spec/unit/provider/mount/mount_spec.rb
+++ b/spec/unit/provider/mount/mount_spec.rb
@@ -107,7 +107,7 @@ describe Chef::Provider::Mount::Mount do
expect { @provider.load_current_resource(); @provider.mountable? }.to raise_error(Chef::Exceptions::Mount)
end
- %w{tmpfs fuse cgroup}.each do |fstype|
+ %w{tmpfs fuse cgroup vboxsf zfs}.each do |fstype|
it "does not expect the device to exist for #{fstype}" do
@new_resource.fstype(fstype)
@new_resource.device("whatever")
diff --git a/spec/unit/provider/mount_spec.rb b/spec/unit/provider/mount_spec.rb
index 19967e8496..b2497cf1b2 100644
--- a/spec/unit/provider/mount_spec.rb
+++ b/spec/unit/provider/mount_spec.rb
@@ -70,6 +70,13 @@ describe Chef::Provider::Mount do
expect(new_resource).to be_updated_by_last_action
end
+ it "should unmount the filesystem if it is mounted" do
+ allow(current_resource).to receive(:mounted).and_return(true)
+ expect(provider).to receive(:umount_fs).and_return(true)
+ provider.run_action(:unmount)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
it "should not umount the filesystem if it is not mounted" do
allow(current_resource).to receive(:mounted).and_return(false)
expect(provider).not_to receive(:umount_fs)
diff --git a/spec/unit/provider/package/aix_spec.rb b/spec/unit/provider/package/aix_spec.rb
index 2b574bb7df..3e3853af28 100644
--- a/spec/unit/provider/package/aix_spec.rb
+++ b/spec/unit/provider/package/aix_spec.rb
@@ -28,7 +28,7 @@ describe Chef::Provider::Package::Aix do
@new_resource.source("/tmp/samba.base")
@provider = Chef::Provider::Package::Aix.new(@new_resource, @run_context)
- allow(::File).to receive(:exists?).and_return(true)
+ allow(::File).to receive(:exist?).with(@new_resource.source).and_return(true)
end
describe "assessing the current package status" do
@@ -41,23 +41,23 @@ describe Chef::Provider::Package::Aix do
it "should create a current resource with the name of new_resource" do
status = double("Status", :stdout => @bffinfo, :exitstatus => 0)
- expect(@provider).to receive(:shell_out).with("installp -L -d /tmp/samba.base", timeout: 900).and_return(status)
- expect(@provider).to receive(:shell_out).with("lslpp -lcq samba.base", timeout: 900).and_return(@empty_status)
+ expect(@provider).to receive(:shell_out).with("installp", "-L", "-d", "/tmp/samba.base", timeout: 900).and_return(status)
+ expect(@provider).to receive(:shell_out).with("lslpp", "-lcq", "samba.base", timeout: 900).and_return(@empty_status)
@provider.load_current_resource
expect(@provider.current_resource.name).to eq("samba.base")
end
it "should set the current resource bff package name to the new resource bff package name" do
status = double("Status", :stdout => @bffinfo, :exitstatus => 0)
- expect(@provider).to receive(:shell_out).with("installp -L -d /tmp/samba.base", timeout: 900).and_return(status)
- expect(@provider).to receive(:shell_out).with("lslpp -lcq samba.base", timeout: 900).and_return(@empty_status)
+ expect(@provider).to receive(:shell_out).with("installp", "-L", "-d", "/tmp/samba.base", timeout: 900).and_return(status)
+ expect(@provider).to receive(:shell_out).with("lslpp", "-lcq", "samba.base", timeout: 900).and_return(@empty_status)
@provider.load_current_resource
expect(@provider.current_resource.package_name).to eq("samba.base")
end
it "should raise an exception if a source is supplied but not found" do
allow(@provider).to receive(:shell_out).and_return(@empty_status)
- allow(::File).to receive(:exists?).and_return(false)
+ allow(::File).to receive(:exist?).with(@new_resource.source).and_return(false)
@provider.load_current_resource
@provider.define_resource_requirements
expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Package)
@@ -65,8 +65,8 @@ describe Chef::Provider::Package::Aix do
it "should get the source package version from lslpp if provided" do
status = double("Status", :stdout => @bffinfo, :exitstatus => 0)
- expect(@provider).to receive(:shell_out).with("installp -L -d /tmp/samba.base", timeout: 900).and_return(status)
- expect(@provider).to receive(:shell_out).with("lslpp -lcq samba.base", timeout: 900).and_return(@empty_status)
+ expect(@provider).to receive(:shell_out).with("installp", "-L", "-d", "/tmp/samba.base", timeout: 900).and_return(status)
+ expect(@provider).to receive(:shell_out).with("lslpp", "-lcq", "samba.base", timeout: 900).and_return(@empty_status)
@provider.load_current_resource
expect(@provider.current_resource.package_name).to eq("samba.base")
@@ -77,8 +77,8 @@ describe Chef::Provider::Package::Aix do
info = "samba.base:samba.base.samples:3.3.12.0::COMMITTED:I:Samba for AIX:
/etc/objrepos:samba.base:3.3.12.0::COMMITTED:I:Samba for AIX:"
status = double("Status", :stdout => info, :exitstatus => 0)
- expect(@provider).to receive(:shell_out).with("installp -L -d /tmp/samba.base", timeout: 900).and_return(status)
- expect(@provider).to receive(:shell_out).with("lslpp -lcq samba.base", timeout: 900).and_return(@empty_status)
+ expect(@provider).to receive(:shell_out).with("installp", "-L", "-d", "/tmp/samba.base", timeout: 900).and_return(status)
+ expect(@provider).to receive(:shell_out).with("lslpp", "-lcq", "samba.base", timeout: 900).and_return(@empty_status)
expect(Chef::Log).to receive(:warn).once.with(%r{bff package by product name})
@provider.load_current_resource
@@ -90,8 +90,8 @@ describe Chef::Provider::Package::Aix do
status = double("Status", :stdout => @bffinfo, :exitstatus => 0)
@stdout = StringIO.new(@bffinfo)
@stdin, @stderr = StringIO.new, StringIO.new
- expect(@provider).to receive(:shell_out).with("installp -L -d /tmp/samba.base", timeout: 900).and_return(status)
- expect(@provider).to receive(:shell_out).with("lslpp -lcq samba.base", timeout: 900).and_return(status)
+ expect(@provider).to receive(:shell_out).with("installp", "-L", "-d", "/tmp/samba.base", timeout: 900).and_return(status)
+ expect(@provider).to receive(:shell_out).with("lslpp", "-lcq", "samba.base", timeout: 900).and_return(status)
@provider.load_current_resource
expect(@provider.current_resource.version).to eq("3.3.12.0")
end
@@ -112,8 +112,8 @@ describe Chef::Provider::Package::Aix do
it "should return a current resource with a nil version if the package is not found" do
status = double("Status", :stdout => @bffinfo, :exitstatus => 0)
- expect(@provider).to receive(:shell_out).with("installp -L -d /tmp/samba.base", timeout: 900).and_return(status)
- expect(@provider).to receive(:shell_out).with("lslpp -lcq samba.base", timeout: 900).and_return(@empty_status)
+ expect(@provider).to receive(:shell_out).with("installp", "-L", "-d", "/tmp/samba.base", timeout: 900).and_return(status)
+ expect(@provider).to receive(:shell_out).with("lslpp", "-lcq", "samba.base", timeout: 900).and_return(@empty_status)
@provider.load_current_resource
expect(@provider.current_resource.version).to be_nil
end
@@ -122,7 +122,7 @@ describe Chef::Provider::Package::Aix do
wrongbffinfo = "/usr/lib/objrepos:openssl.base:0.9.8.2400::COMMITTED:I:Open Secure Socket Layer:
/etc/objrepos:openssl.base:0.9.8.2400::COMMITTED:I:Open Secure Socket Layer:"
status = double("Status", :stdout => wrongbffinfo, :exitstatus => 0)
- expect(@provider).to receive(:shell_out).with("installp -L -d /tmp/samba.base", timeout: 900).and_return(status)
+ expect(@provider).to receive(:shell_out).with("installp", "-L", "-d", "/tmp/samba.base", timeout: 900).and_return(status)
expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Package)
end
end
@@ -130,7 +130,7 @@ describe Chef::Provider::Package::Aix do
describe "candidate_version" do
it "should return the candidate_version variable if already setup" do
@provider.candidate_version = "3.3.12.0"
- expect(@provider).not_to receive(:shell_out )
+ expect(@provider).not_to receive(:shell_out)
@provider.candidate_version
end
@@ -150,34 +150,34 @@ describe Chef::Provider::Package::Aix do
describe "install and upgrade" do
it "should run installp -aYF -d with the package source to install" do
- expect(@provider).to receive(:shell_out!).with("installp -aYF -d /tmp/samba.base samba.base", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("installp", "-aYF", "-d", "/tmp/samba.base", "samba.base", timeout: 900)
@provider.install_package("samba.base", "3.3.12.0")
end
- it "should run when the package is a path to install" do
+ it "should run installp -aYF -d when the package is a path to install" do
@new_resource = Chef::Resource::Package.new("/tmp/samba.base")
@provider = Chef::Provider::Package::Aix.new(@new_resource, @run_context)
expect(@new_resource.source).to eq("/tmp/samba.base")
- expect(@provider).to receive(:shell_out!).with("installp -aYF -d /tmp/samba.base /tmp/samba.base", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("installp", "-aYF", "-d", "/tmp/samba.base", "/tmp/samba.base", timeout: 900)
@provider.install_package("/tmp/samba.base", "3.3.12.0")
end
it "should run installp with -eLogfile option." do
allow(@new_resource).to receive(:options).and_return("-e/tmp/installp.log")
- expect(@provider).to receive(:shell_out!).with("installp -aYF -e/tmp/installp.log -d /tmp/samba.base samba.base", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("installp", "-aYF", "-e/tmp/installp.log", "-d", "/tmp/samba.base", "samba.base", timeout: 900)
@provider.install_package("samba.base", "3.3.12.0")
end
end
describe "remove" do
it "should run installp -u samba.base to remove the package" do
- expect(@provider).to receive(:shell_out!).with("installp -u samba.base", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("installp", "-u", "samba.base", timeout: 900)
@provider.remove_package("samba.base", "3.3.12.0")
end
it "should run installp -u -e/tmp/installp.log with options -e/tmp/installp.log" do
allow(@new_resource).to receive(:options).and_return("-e/tmp/installp.log")
- expect(@provider).to receive(:shell_out!).with("installp -u -e/tmp/installp.log samba.base", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("installp", "-u", "-e/tmp/installp.log", "samba.base", timeout: 900)
@provider.remove_package("samba.base", "3.3.12.0")
end
diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb
index cf31c3d7cc..e14af488ac 100644
--- a/spec/unit/provider/package/apt_spec.rb
+++ b/spec/unit/provider/package/apt_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");
@@ -51,7 +51,7 @@ irssi:
it "should create a current resource with the name of the new_resource" do
expect(@provider).to receive(:shell_out!).with(
- "apt-cache policy #{@new_resource.package_name}",
+ "apt-cache", "policy", @new_resource.package_name,
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(@shell_out)
@@ -91,7 +91,7 @@ N: Unable to locate package conic-smarms
POLICY_STDOUT
policy = double(:stdout => policy_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
- "apt-cache policy conic-smarms",
+ "apt-cache", "policy", "conic-smarms",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(policy)
@@ -100,7 +100,7 @@ N: Unable to locate package conic-smarms
SHOWPKG_STDOUT
showpkg = double(:stdout => showpkg_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
- "apt-cache showpkg conic-smarms",
+ "apt-cache", "showpkg", "conic-smarms",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(showpkg)
@@ -119,7 +119,7 @@ libmysqlclient15-dev:
VPKG_STDOUT
virtual_package = double(:stdout => virtual_package_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
- "apt-cache policy libmysqlclient15-dev",
+ "apt-cache", "policy", "libmysqlclient15-dev",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(virtual_package)
@@ -143,7 +143,7 @@ libmysqlclient-dev 5.1.41-3ubuntu12
SHOWPKG_STDOUT
showpkg = double(:stdout => showpkg_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
- "apt-cache showpkg libmysqlclient15-dev",
+ "apt-cache", "showpkg", "libmysqlclient15-dev",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(showpkg)
@@ -162,7 +162,7 @@ libmysqlclient-dev:
RPKG_STDOUT
real_package = double(:stdout => real_package_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
- "apt-cache policy libmysqlclient-dev",
+ "apt-cache", "policy", "libmysqlclient-dev",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(real_package)
@@ -179,7 +179,7 @@ mp3-decoder:
VPKG_STDOUT
virtual_package = double(:stdout => virtual_package_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
- "apt-cache policy mp3-decoder",
+ "apt-cache", "policy", "mp3-decoder",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(virtual_package)
@@ -206,7 +206,7 @@ mpg123 1.12.1-0ubuntu1
SHOWPKG_STDOUT
showpkg = double(:stdout => showpkg_out, :exitstatus => 0)
expect(@provider).to receive(:shell_out!).with(
- "apt-cache showpkg mp3-decoder",
+ "apt-cache", "showpkg", "mp3-decoder",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(showpkg)
@@ -220,7 +220,7 @@ mpg123 1.12.1-0ubuntu1
allow(@new_resource).to receive(:default_release).and_return("lenny-backports")
allow(@new_resource).to receive(:provider).and_return(nil)
expect(@provider).to receive(:shell_out!).with(
- "apt-cache -o APT::Default-Release=lenny-backports policy irssi",
+ "apt-cache", "-o", "APT::Default-Release=lenny-backports", "policy", "irssi",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
).and_return(@shell_out)
@@ -230,7 +230,7 @@ mpg123 1.12.1-0ubuntu1
it "raises an exception if a source is specified (CHEF-5113)" do
@new_resource.source "pluto"
expect(@provider).to receive(:shell_out!).with(
- "apt-cache policy #{@new_resource.package_name}",
+ "apt-cache", "policy", @new_resource.package_name,
:env => { "DEBIAN_FRONTEND" => "noninteractive" } ,
:timeout => @timeout
).and_return(@shell_out)
@@ -259,7 +259,7 @@ mpg123 1.12.1-0ubuntu1
describe "install_package" do
it "should run apt-get install with the package name and version" do
expect(@provider).to receive(:shell_out!). with(
- "apt-get -q -y install irssi=0.8.12-7",
+ "apt-get", "-q", "-y", "install", "irssi=0.8.12-7",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -268,7 +268,7 @@ mpg123 1.12.1-0ubuntu1
it "should run apt-get install with the package name and version and options if specified" do
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y --force-yes install irssi=0.8.12-7",
+ "apt-get", "-q", "-y", "--force-yes", "install", "irssi=0.8.12-7",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -284,7 +284,7 @@ mpg123 1.12.1-0ubuntu1
@provider.new_resource = @new_resource
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y -o APT::Default-Release=lenny-backports install irssi=0.8.12-7",
+ "apt-get", "-q", "-y", "-o", "APT::Default-Release=lenny-backports", "install", "irssi=0.8.12-7",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -305,7 +305,7 @@ mpg123 1.12.1-0ubuntu1
it "should run apt-get remove with the package name" do
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y remove irssi",
+ "apt-get", "-q", "-y", "remove", "irssi",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -314,7 +314,7 @@ mpg123 1.12.1-0ubuntu1
it "should run apt-get remove with the package name and options if specified" do
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y --force-yes remove irssi",
+ "apt-get", "-q", "-y", "--force-yes", "remove", "irssi",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -328,7 +328,7 @@ mpg123 1.12.1-0ubuntu1
it "should run apt-get purge with the package name" do
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y purge irssi",
+ "apt-get", "-q", "-y", "purge", "irssi",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -337,7 +337,7 @@ mpg123 1.12.1-0ubuntu1
it "should run apt-get purge with the package name and options if specified" do
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y --force-yes purge irssi",
+ "apt-get", "-q", "-y", "--force-yes", "purge", "irssi",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -356,7 +356,7 @@ mpg123 1.12.1-0ubuntu1
file = "/tmp/irssi-0.8.12-7.seed"
expect(@provider).to receive(:shell_out!).with(
- "debconf-set-selections /tmp/irssi-0.8.12-7.seed",
+ "debconf-set-selections", "/tmp/irssi-0.8.12-7.seed",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -366,7 +366,7 @@ mpg123 1.12.1-0ubuntu1
it "should run debconf-set-selections on the preseed file if it has changed" do
expect(@provider).to receive(:shell_out!).with(
- "debconf-set-selections /tmp/irssi-0.8.12-7.seed",
+ "debconf-set-selections", "/tmp/irssi-0.8.12-7.seed",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -387,7 +387,7 @@ mpg123 1.12.1-0ubuntu1
describe "when reconfiguring a package" do
it "should run dpkg-reconfigure package" do
expect(@provider).to receive(:shell_out!).with(
- "dpkg-reconfigure irssi",
+ "dpkg-reconfigure", "irssi",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -398,7 +398,7 @@ mpg123 1.12.1-0ubuntu1
describe "when locking a package" do
it "should run apt-mark hold package" do
expect(@provider).to receive(:shell_out!).with(
- "apt-mark hold irssi",
+ "apt-mark", "hold", "irssi",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -409,7 +409,7 @@ mpg123 1.12.1-0ubuntu1
describe "when unlocking a package" do
it "should run apt-mark unhold package" do
expect(@provider).to receive(:shell_out!).with(
- "apt-mark unhold irssi",
+ "apt-mark", "unhold", "irssi",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -421,7 +421,7 @@ mpg123 1.12.1-0ubuntu1
it "should install the package without specifying a version" do
@provider.package_data["libmysqlclient15-dev"][:virtual] = true
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y install libmysqlclient15-dev",
+ "apt-get", "-q", "-y", "install", "libmysqlclient15-dev",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -433,7 +433,7 @@ mpg123 1.12.1-0ubuntu1
it "should remove the resolved name instead of the virtual package name" do
expect(@provider).to receive(:resolve_virtual_package_name).with("libmysqlclient15-dev").and_return("libmysqlclient-dev")
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y remove libmysqlclient-dev",
+ "apt-get", "-q", "-y", "remove", "libmysqlclient-dev",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -445,7 +445,7 @@ mpg123 1.12.1-0ubuntu1
it "should purge the resolved name instead of the virtual package name" do
expect(@provider).to receive(:resolve_virtual_package_name).with("libmysqlclient15-dev").and_return("libmysqlclient-dev")
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y purge libmysqlclient-dev",
+ "apt-get", "-q", "-y", "purge", "libmysqlclient-dev",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
@@ -457,7 +457,7 @@ mpg123 1.12.1-0ubuntu1
it "can install a virtual package followed by a non-virtual package" do
# https://github.com/chef/chef/issues/2914
expect(@provider).to receive(:shell_out!).with(
- "apt-get -q -y install libmysqlclient15-dev irssi=0.8.12-7",
+ "apt-get", "-q", "-y", "install", "libmysqlclient15-dev", "irssi=0.8.12-7",
:env => { "DEBIAN_FRONTEND" => "noninteractive" },
:timeout => @timeout
)
diff --git a/spec/unit/provider/package/cab_spec.rb b/spec/unit/provider/package/cab_spec.rb
index 5e16795aa8..5c86f781f3 100644
--- a/spec/unit/provider/package/cab_spec.rb
+++ b/spec/unit/provider/package/cab_spec.rb
@@ -49,7 +49,7 @@ The operation completed successfully
end
before do
- new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.cab"
+ new_resource.source = File.join("#{ENV['TEMP']}", "test6.1-kb2664825-v3-x64.cab")
installed_package_list_obj = double(stdout: installed_package_list_stdout)
allow(provider).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj)
package_version_obj = double(stdout: package_version_stdout)
@@ -126,6 +126,63 @@ The operation completed successfully.
end
end
+ describe "#source_resource" do
+ before do
+ new_resource.source = "https://www.something.com/Test6.1-KB2664825-v3-x64.cab"
+ new_resource.cookbook_name = "cab_package"
+ end
+
+ it "sets the desired parameters of downloades cab file" do
+ allow(provider).to receive(:default_download_cache_path).and_return("C:\\chef\\cache\\package")
+ source_resource = provider.source_resource
+ expect(source_resource.path).to be == "C:\\chef\\cache\\package"
+ expect(source_resource.name).to be == "windows_test_pkg"
+ expect(source_resource.source).to be == [new_resource.source]
+ expect(source_resource.cookbook_name).to be == "cab_package"
+ end
+ end
+
+ describe "#default_download_cache_path" do
+ before do
+ new_resource.source = "https://www.something.com/Test6.1-KB2664825-v3-x64.cab"
+ end
+
+ it "returns a clean cache path where the cab file is downloaded" do
+ allow(Chef::FileCache).to receive(:create_cache_path).and_return(ENV["TEMP"])
+ path = provider.default_download_cache_path
+ if windows?
+ expect(path).to be == File.join("#{ENV['TEMP']}", "\\", "Test6.1-KB2664825-v3-x64.cab")
+ else
+ expect(path).to be == File.join("#{ENV['TEMP']}", "Test6.1-KB2664825-v3-x64.cab")
+ end
+ end
+ end
+
+ describe "#cab_file_source" do
+ context "when local file path is set" do
+ it "returns local cab file source path" do
+ new_resource.source = File.join("#{ENV['TEMP']}", "test6.1-kb2664825-v3-x64.cab")
+ path = provider.cab_file_source
+ if windows?
+ expect(path).to be == File.join("#{ENV['TEMP'].downcase}", "\\", "test6.1-kb2664825-v3-x64.cab")
+ else
+ expect(path).to be == File.join("#{ENV['TEMP']}", "test6.1-kb2664825-v3-x64.cab")
+ end
+ end
+ end
+ context "when url is set" do
+ it "calls download_source_file method" do
+ new_resource.source = "https://www.something.com/test6.1-kb2664825-v3-x64.cab"
+ if windows?
+ expect(provider).to receive(:download_source_file).and_return(File.join("#{ENV['TEMP'].downcase}", "\\", "test6.1-kb2664825-v3-x64.cab"))
+ else
+ expect(provider).to receive(:download_source_file).and_return(File.join("#{ENV['TEMP']}", "test6.1-kb2664825-v3-x64.cab"))
+ end
+ provider.cab_file_source
+ end
+ end
+ end
+
describe "#initialize" do
it "returns the correct class" do
expect(provider).to be_kind_of(Chef::Provider::Package::Cab)
@@ -192,12 +249,9 @@ The operation completed successfully.
context "Invalid package source" do
def package_version_stdout
package_version_stdout = <<-EOF
-
Deployment Image Servicing and Management tool
Version: 6.1.7600.16385
-
Image Version: 6.1.7600.16385
-
An error occurred trying to open - c:\\temp\\test6.1-KB2664825-v3-x64.cab Error: 0x80070003
Error: 3
The system cannot find the path specified.
@@ -206,7 +260,7 @@ The DISM log file can be found at C:\\Windows\\Logs\\DISM\\dism.log.
end
before do
- new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.cab"
+ new_resource.source = "#{ENV['TEMP']}/test6.1-kb2664825-v3-x64.cab"
installed_package_list_obj = double(stdout: installed_package_list_stdout)
allow(provider).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj)
end
diff --git a/spec/unit/provider/package/chocolatey_spec.rb b/spec/unit/provider/package/chocolatey_spec.rb
index 704ef1aef2..68b121960c 100644
--- a/spec/unit/provider/package/chocolatey_spec.rb
+++ b/spec/unit/provider/package/chocolatey_spec.rb
@@ -46,7 +46,7 @@ ConEmu|15.10.25.0
allow(provider).to receive(:choco_install_path).and_return(choco_install_path)
allow(provider).to receive(:choco_exe).and_return(choco_exe)
local_list_obj = double(:stdout => local_list_stdout)
- allow(provider).to receive(:shell_out!).with("#{choco_exe} list -l -r", { :timeout => timeout }).and_return(local_list_obj)
+ allow(provider).to receive(:shell_out!).with("#{choco_exe} list -l -r", { :returns => [0], :timeout => timeout }).and_return(local_list_obj)
end
def allow_remote_list(package_names, args = nil)
@@ -59,7 +59,7 @@ Git|2.6.2
munin-node|1.6.1.20130823
EOF
remote_list_obj = double(stdout: remote_list_stdout)
- allow(provider).to receive(:shell_out!).with("#{choco_exe} list -r #{package_names.join ' '}#{args}", { timeout: timeout }).and_return(remote_list_obj)
+ allow(provider).to receive(:shell_out!).with("#{choco_exe} list -r #{package_names.join ' '}#{args}", { :returns => [0], timeout: timeout }).and_return(remote_list_obj)
end
describe "#initialize" do
@@ -180,7 +180,7 @@ munin-node|1.6.1.20130823
it "should install a single package" do
allow_remote_list(["git"])
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y git", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y git", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -191,7 +191,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["git"])
new_resource.timeout(timeout)
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y git", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y git", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -220,7 +220,7 @@ munin-node|1.6.1.20130823
new_resource.package_name("ConEmu")
new_resource.version("15.10.25.1")
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -233,7 +233,7 @@ munin-node|1.6.1.20130823
new_resource.package_name(%w{chocolatey ConEmu})
new_resource.version([nil, "15.10.25.1"])
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -243,7 +243,7 @@ munin-node|1.6.1.20130823
new_resource.package_name("conemu")
new_resource.version("15.10.25.1")
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -253,8 +253,8 @@ munin-node|1.6.1.20130823
new_resource.package_name(%w{ConEmu git})
new_resource.version(["15.10.25.1", nil])
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -version 15.10.25.1 conemu", { :timeout => timeout }).and_return(double)
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y git", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y --version 15.10.25.1 conemu", { :returns => [0], :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y git", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -263,7 +263,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["git", "munin-node"])
new_resource.package_name(["git", "munin-node"])
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y git munin-node", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y git munin-node", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -273,7 +273,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["git"], " -source localpackages")
new_resource.source("localpackages")
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -source localpackages git", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -source localpackages git", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -283,7 +283,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["git"])
new_resource.options("-force")
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -force git", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} install -y -force git", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -317,7 +317,7 @@ munin-node|1.6.1.20130823
it "should install a package that is not installed" do
allow_remote_list(["git"])
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y git", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y git", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:upgrade)
expect(new_resource).to be_updated_by_last_action
end
@@ -326,7 +326,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["ConEmu"])
new_resource.package_name("ConEmu")
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y conemu", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y conemu", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:upgrade)
expect(new_resource).to be_updated_by_last_action
end
@@ -335,7 +335,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["conemu"])
new_resource.package_name("conemu")
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y conemu", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y conemu", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:upgrade)
expect(new_resource).to be_updated_by_last_action
end
@@ -344,7 +344,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["chocolatey"])
new_resource.package_name("chocolatey")
provider.load_current_resource
- expect(provider).not_to receive(:shell_out!).with("#{choco_exe} upgrade -y chocolatey", { :timeout => timeout })
+ expect(provider).not_to receive(:shell_out!).with("#{choco_exe} upgrade -y chocolatey", { :returns => [0], :timeout => timeout })
provider.run_action(:upgrade)
expect(new_resource).not_to be_updated_by_last_action
end
@@ -353,7 +353,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["git"])
new_resource.version("2.6.2")
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y -version 2.6.2 git", { :timeout => timeout })
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y --version 2.6.2 git", { :returns => [0], :timeout => timeout })
provider.run_action(:upgrade)
expect(new_resource).to be_updated_by_last_action
end
@@ -361,7 +361,7 @@ munin-node|1.6.1.20130823
it "upgrading multiple packages uses a single command" do
allow_remote_list(%w{conemu git})
new_resource.package_name(%w{conemu git})
- expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y conemu git", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} upgrade -y conemu git", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:upgrade)
expect(new_resource).to be_updated_by_last_action
end
@@ -413,7 +413,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["ConEmu"])
new_resource.package_name("ConEmu")
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} uninstall -y ConEmu", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} uninstall -y ConEmu", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:remove)
expect(new_resource).to be_updated_by_last_action
end
@@ -422,7 +422,7 @@ munin-node|1.6.1.20130823
allow_remote_list(["conemu"])
new_resource.package_name("conemu")
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} uninstall -y conemu", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} uninstall -y conemu", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:remove)
expect(new_resource).to be_updated_by_last_action
end
@@ -432,7 +432,7 @@ munin-node|1.6.1.20130823
allow_remote_list(%w{git conemu})
new_resource.package_name(%w{git conemu})
provider.load_current_resource
- expect(provider).to receive(:shell_out!).with("#{choco_exe} uninstall -y conemu", { :timeout => timeout }).and_return(double)
+ expect(provider).to receive(:shell_out!).with("#{choco_exe} uninstall -y conemu", { :returns => [0], :timeout => timeout }).and_return(double)
provider.run_action(:remove)
expect(new_resource).to be_updated_by_last_action
end
diff --git a/spec/unit/provider/package/dnf/python_helper_spec.rb b/spec/unit/provider/package/dnf/python_helper_spec.rb
new file mode 100644
index 0000000000..505217bf90
--- /dev/null
+++ b/spec/unit/provider/package/dnf/python_helper_spec.rb
@@ -0,0 +1,29 @@
+#
+# Copyright:: Copyright 2017-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"
+
+# NOTE: most of the tests of this functionality are baked into the func tests for the dnf package provider
+
+describe Chef::Provider::Package::Dnf::PythonHelper do
+ let(:helper) { Chef::Provider::Package::Dnf::PythonHelper.instance }
+
+ it "propagates stacktraces on stderr from the forked subprocess" do
+ allow(helper).to receive(:dnf_command).and_return("ruby -e 'raise \"your hands in the air\"'")
+ expect { helper.query(:whatprovides, "tcpdump") }.to raise_error(/your hands in the air/)
+ end
+end
diff --git a/spec/unit/provider/package/dpkg_spec.rb b/spec/unit/provider/package/dpkg_spec.rb
index 613f7a326e..e01e1d9cce 100644
--- a/spec/unit/provider/package/dpkg_spec.rb
+++ b/spec/unit/provider/package/dpkg_spec.rb
@@ -51,8 +51,8 @@ Conflicts: wget-ssl
end
before(:each) do
- allow(provider).to receive(:shell_out!).with("dpkg-deb -W #{source}", timeout: 900).and_return(dpkg_deb_status)
- allow(provider).to receive(:shell_out!).with("dpkg -s #{package}", timeout: 900, returns: [0, 1]).and_return(double(stdout: "", exitstatus: 1))
+ allow(provider).to receive(:shell_out!).with("dpkg-deb", "-W", source, timeout: 900).and_return(dpkg_deb_status)
+ allow(provider).to receive(:shell_out!).with("dpkg", "-s", package, timeout: 900, returns: [0, 1]).and_return(double(stdout: "", exitstatus: 1))
allow(::File).to receive(:exist?).with(source).and_return(true)
end
@@ -113,7 +113,7 @@ Conflicts: wget-ssl
describe "gets the source package version from dpkg-deb" do
def check_version(version)
status = double(:stdout => "wget\t#{version}", :exitstatus => 0)
- expect(provider).to receive(:shell_out!).with("dpkg-deb -W #{source}", timeout: 900).and_return(status)
+ expect(provider).to receive(:shell_out!).with("dpkg-deb", "-W", source, timeout: 900).and_return(status)
provider.load_current_resource
expect(provider.current_resource.package_name).to eq(["wget"])
expect(provider.candidate_version).to eq([version])
@@ -165,7 +165,7 @@ Conflicts: wget-ssl
end
it "should return the current version installed if found by dpkg" do
- allow(provider).to receive(:shell_out!).with("dpkg -s #{package}", timeout: 900, returns: [0, 1]).and_return(dpkg_s_status)
+ allow(provider).to receive(:shell_out!).with("dpkg", "-s", package, timeout: 900, returns: [0, 1]).and_return(dpkg_s_status)
provider.load_current_resource
expect(provider.current_resource.version).to eq(["1.11.4-1ubuntu1"])
end
@@ -178,7 +178,7 @@ Use dpkg --info (= dpkg-deb --info) to examine archive files,
and dpkg --contents (= dpkg-deb --contents) to list their contents.
EOF
)
- expect(provider).to receive(:shell_out!).with("dpkg -s #{package}", returns: [0, 1], timeout: 900).and_return(dpkg_s_status)
+ expect(provider).to receive(:shell_out!).with("dpkg", "-s", package, returns: [0, 1], timeout: 900).and_return(dpkg_s_status)
provider.load_current_resource
expect(provider.current_resource.version).to eq([nil])
end
@@ -192,7 +192,7 @@ Priority: extra
Section: ruby
EOF
)
- expect(provider).to receive(:shell_out!).with("dpkg -s #{package}", returns: [0, 1], timeout: 900).and_return(dpkg_s_status)
+ expect(provider).to receive(:shell_out!).with("dpkg", "-s", package, returns: [0, 1], timeout: 900).and_return(dpkg_s_status)
provider.load_current_resource
expect(provider.current_resource.version).to eq([nil])
end
@@ -201,13 +201,13 @@ Section: ruby
dpkg_s_status = double(
exitstatus: 3, stderr: "i am very, very angry with you. i'm very, very cross. go to your room.", stdout: ""
)
- expect(provider).to receive(:shell_out!).with("dpkg -s #{package}", returns: [0, 1], timeout: 900).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ expect(provider).to receive(:shell_out!).with("dpkg", "-s", package, returns: [0, 1], timeout: 900).and_raise(Mixlib::ShellOut::ShellCommandFailed)
expect { provider.load_current_resource }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
end
it "should raise an exception if dpkg-deb -W fails to run" do
status = double(:stdout => "", :exitstatus => -1)
- expect(provider).to receive(:shell_out_with_timeout!).with("dpkg-deb -W /tmp/wget_1.11.4-1ubuntu1_amd64.deb").and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ expect(provider).to receive(:shell_out_compact_timeout!).with("dpkg-deb", "-W", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb").and_raise(Mixlib::ShellOut::ShellCommandFailed)
expect { provider.load_current_resource }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
end
end
@@ -215,7 +215,7 @@ Section: ruby
describe Chef::Provider::Package::Dpkg, "install and upgrade" do
it "should run dpkg -i with the package source" do
expect(provider).to receive(:run_noninteractive).with(
- "dpkg -i", nil, "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
+ "dpkg", "-i", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
)
provider.load_current_resource
provider.run_action(:install)
@@ -224,7 +224,7 @@ Section: ruby
it "should run dpkg -i if the package is a path and the source is nil" do
new_resource.name "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
expect(provider).to receive(:run_noninteractive).with(
- "dpkg -i", nil, "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
+ "dpkg", "-i", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
)
provider.run_action(:install)
end
@@ -232,7 +232,7 @@ Section: ruby
it "should run dpkg -i if the package is a path and the source is nil for an upgrade" do
new_resource.name "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
expect(provider).to receive(:run_noninteractive).with(
- "dpkg -i", nil, "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
+ "dpkg", "-i", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
)
provider.run_action(:upgrade)
end
@@ -240,7 +240,7 @@ Section: ruby
it "should run dpkg -i with the package source and options if specified" do
new_resource.options "--force-yes"
expect(provider).to receive(:run_noninteractive).with(
- "dpkg -i", "--force-yes", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
+ "dpkg", "-i", "--force-yes", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
)
provider.run_action(:install)
end
@@ -254,14 +254,14 @@ Section: ruby
describe Chef::Provider::Package::Dpkg, "remove and purge" do
it "should run dpkg -r to remove the package" do
expect(provider).to receive(:run_noninteractive).with(
- "dpkg -r", nil, "wget"
+ "dpkg", "-r", "wget"
)
provider.remove_package(["wget"], ["1.11.4-1ubuntu1"])
end
it "should run dpkg -r to remove the package with options if specified" do
expect(provider).to receive(:run_noninteractive).with(
- "dpkg -r", "--force-yes", "wget"
+ "dpkg", "-r", "--force-yes", "wget"
)
allow(new_resource).to receive(:options).and_return("--force-yes")
@@ -270,14 +270,14 @@ Section: ruby
it "should run dpkg -P to purge the package" do
expect(provider).to receive(:run_noninteractive).with(
- "dpkg -P", nil, "wget"
+ "dpkg", "-P", "wget"
)
provider.purge_package(["wget"], ["1.11.4-1ubuntu1"])
end
it "should run dpkg -P to purge the package with options if specified" do
expect(provider).to receive(:run_noninteractive).with(
- "dpkg -P", "--force-yes", "wget"
+ "dpkg", "-P", "--force-yes", "wget"
)
allow(new_resource).to receive(:options).and_return("--force-yes")
diff --git a/spec/unit/provider/package/easy_install_spec.rb b/spec/unit/provider/package/easy_install_spec.rb
index fa5eea00a2..910f01bfeb 100644
--- a/spec/unit/provider/package/easy_install_spec.rb
+++ b/spec/unit/provider/package/easy_install_spec.rb
@@ -61,52 +61,52 @@ describe Chef::Provider::Package::EasyInstall do
describe "actions_on_package" do
it "should run easy_install with the package name and version" do
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
- expect(@provider).to receive(:run_command).with({
- :command => "easy_install \"boto==1.8d\"",
- })
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
+ expect(@provider).to receive(:shell_out!).with(
+ "easy_install", "boto==1.8d", { timeout: 900 }
+ )
@provider.install_package("boto", "1.8d")
end
it "should run easy_install with the package name and version and specified options" do
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
- expect(@provider).to receive(:run_command).with({
- :command => "easy_install --always-unzip \"boto==1.8d\"",
- })
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
+ expect(@provider).to receive(:shell_out!).with(
+ "easy_install", "--always-unzip", "boto==1.8d", { timeout: 900 }
+ )
allow(@new_resource).to receive(:options).and_return("--always-unzip")
@provider.install_package("boto", "1.8d")
end
it "should run easy_install with the package name and version" do
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
- expect(@provider).to receive(:run_command).with({
- :command => "easy_install \"boto==1.8d\"",
- })
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
+ expect(@provider).to receive(:shell_out!).with(
+ "easy_install", "boto==1.8d", { timeout: 900 }
+ )
@provider.upgrade_package("boto", "1.8d")
end
it "should run easy_install -m with the package name and version" do
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
- expect(@provider).to receive(:run_command).with({
- :command => "easy_install -m boto",
- })
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
+ expect(@provider).to receive(:shell_out!).with(
+ "easy_install", "-m", "boto", { timeout: 900 }
+ )
@provider.remove_package("boto", "1.8d")
end
it "should run easy_install -m with the package name and version and specified options" do
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
- expect(@provider).to receive(:run_command).with({
- :command => "easy_install -x -m boto",
- })
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
+ expect(@provider).to receive(:shell_out!).with(
+ "easy_install", "-x", "-m", "boto", { timeout: 900 }
+ )
allow(@new_resource).to receive(:options).and_return("-x")
@provider.remove_package("boto", "1.8d")
end
it "should run easy_install -m with the package name and version" do
- expect(Chef).to receive(:log_deprecation).with(/easy_install package provider is deprecated/)
- expect(@provider).to receive(:run_command).with({
- :command => "easy_install -m boto",
- })
+ expect(Chef).to receive(:deprecated).with(:easy_install, /easy_install package provider is deprecated/)
+ expect(@provider).to receive(:shell_out!).with(
+ "easy_install", "-m", "boto", { timeout: 900 }
+ )
@provider.purge_package("boto", "1.8d")
end
diff --git a/spec/unit/provider/package/freebsd/pkg_spec.rb b/spec/unit/provider/package/freebsd/pkg_spec.rb
index 8890f62f73..4b3a94aa33 100644
--- a/spec/unit/provider/package/freebsd/pkg_spec.rb
+++ b/spec/unit/provider/package/freebsd/pkg_spec.rb
@@ -31,6 +31,8 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
@provider = Chef::Provider::Package::Freebsd::Pkg.new(@new_resource, @run_context)
@provider.current_resource = @current_resource
allow(::File).to receive(:exist?).with("/usr/ports/Makefile").and_return(false)
+ allow(::File).to receive(:exist?).with("/usr/ports/www/wordpress").and_return(false)
+ allow(::File).to receive(:exist?).with("www/wordpress").and_return(false)
end
describe "when determining the current package state" do
@@ -77,23 +79,21 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
it "should return the version number when it is installed" do
pkg_info = OpenStruct.new(:stdout => "zsh-4.3.6_7")
- expect(@provider).to receive(:shell_out!).with('pkg_info -E "zsh*"', env: nil, returns: [0, 1], timeout: 900).and_return(pkg_info)
- #@provider.should_receive(:popen4).with('pkg_info -E "zsh*"').and_yield(@pid, @stdin, ["zsh-4.3.6_7"], @stderr).and_return(@status)
+ expect(@provider).to receive(:shell_out!).with("pkg_info", "-E", "zsh*", env: nil, returns: [0, 1], timeout: 900).and_return(pkg_info)
allow(@provider).to receive(:package_name).and_return("zsh")
expect(@provider.current_installed_version).to eq("4.3.6_7")
end
it "does not set the current version number when the package is not installed" do
pkg_info = OpenStruct.new(:stdout => "")
- expect(@provider).to receive(:shell_out!).with('pkg_info -E "zsh*"', env: nil, returns: [0, 1], timeout: 900).and_return(pkg_info)
+ expect(@provider).to receive(:shell_out!).with("pkg_info", "-E", "zsh*", env: nil, returns: [0, 1], timeout: 900).and_return(pkg_info)
allow(@provider).to receive(:package_name).and_return("zsh")
expect(@provider.current_installed_version).to be_nil
end
it "should return the port path for a valid port name" do
whereis = OpenStruct.new(:stdout => "zsh: /usr/ports/shells/zsh")
- expect(@provider).to receive(:shell_out!).with("whereis -s zsh", env: nil, timeout: 900).and_return(whereis)
- #@provider.should_receive(:popen4).with("whereis -s zsh").and_yield(@pid, @stdin, ["zsh: /usr/ports/shells/zsh"], @stderr).and_return(@status)
+ expect(@provider).to receive(:shell_out!).with("whereis", "-s", "zsh", env: nil, timeout: 900).and_return(whereis)
allow(@provider).to receive(:port_name).and_return("zsh")
expect(@provider.port_path).to eq("/usr/ports/shells/zsh")
end
@@ -102,7 +102,7 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
it "should return the ports candidate version when given a valid port path" do
allow(@provider).to receive(:port_path).and_return("/usr/ports/shells/zsh")
make_v = OpenStruct.new(:stdout => "4.3.6\n", :exitstatus => 0)
- expect(@provider).to receive(:shell_out!).with("make -V PORTVERSION", { cwd: "/usr/ports/shells/zsh", returns: [0, 1], env: nil, timeout: 900 }).and_return(make_v)
+ expect(@provider).to receive(:shell_out!).with("make", "-V", "PORTVERSION", { cwd: "/usr/ports/shells/zsh", returns: [0, 1], env: nil, timeout: 900 }).and_return(make_v)
expect(@provider.ports_candidate_version).to eq("4.3.6")
end
@@ -110,7 +110,7 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
allow(::File).to receive(:exist?).with("/usr/ports/Makefile").and_return(true)
allow(@provider).to receive(:port_path).and_return("/usr/ports/shells/zsh")
make_v = OpenStruct.new(:stdout => "zsh-4.3.6_7\n", :exitstatus => 0)
- expect(@provider).to receive(:shell_out!).with("make -V PKGNAME", { cwd: "/usr/ports/shells/zsh", env: nil, returns: [0, 1], timeout: 900 }).and_return(make_v)
+ expect(@provider).to receive(:shell_out!).with("make", "-V", "PKGNAME", { cwd: "/usr/ports/shells/zsh", env: nil, returns: [0, 1], timeout: 900 }).and_return(make_v)
#@provider.should_receive(:ports_makefile_variable_value).with("PKGNAME").and_return("zsh-4.3.6_7")
expect(@provider.package_name).to eq("zsh")
end
@@ -127,7 +127,7 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
end
it "should run pkg_add -r with the package name" do
- expect(@provider).to receive(:shell_out!).with("pkg_add -r zsh", env: nil, timeout: 900).and_return(@cmd_result)
+ expect(@provider).to receive(:shell_out!).with("pkg_add", "-r", "zsh", env: nil, timeout: 900).and_return(@cmd_result)
@provider.install_package("zsh", "4.3.6_7")
end
end
@@ -142,7 +142,7 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
it "should figure out the port path from the package_name using whereis" do
whereis = OpenStruct.new(:stdout => "zsh: /usr/ports/shells/zsh")
- expect(@provider).to receive(:shell_out!).with("whereis -s zsh", env: nil, timeout: 900).and_return(whereis)
+ expect(@provider).to receive(:shell_out!).with("whereis", "-s", "zsh", env: nil, timeout: 900).and_return(whereis)
expect(@provider.port_path).to eq("/usr/ports/shells/zsh")
end
@@ -178,7 +178,7 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
end
it "should run pkg_add -r with the package name" do
- expect(@provider).to receive(:shell_out!).with("pkg_add -r ruby18-iconv", env: nil, timeout: 900).and_return(@install_result)
+ expect(@provider).to receive(:shell_out!).with("pkg_add", "-r", "ruby18-iconv", env: nil, timeout: 900).and_return(@install_result)
@provider.install_package("ruby-iconv", "1.0")
end
end
@@ -193,7 +193,7 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
end
it "should run pkg_delete with the package name and version" do
- expect(@provider).to receive(:shell_out!).with("pkg_delete zsh-4.3.6_7", env: nil, timeout: 900).and_return(@pkg_delete)
+ expect(@provider).to receive(:shell_out!).with("pkg_delete", "zsh-4.3.6_7", env: nil, timeout: 900).and_return(@pkg_delete)
@provider.remove_package("zsh", "4.3.6_7")
end
end
@@ -213,14 +213,14 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
it "should return the port path for a valid port name" do
whereis = OpenStruct.new(:stdout => "bonnie++: /usr/ports/benchmarks/bonnie++")
- expect(@provider).to receive(:shell_out!).with("whereis -s bonnie++", env: nil, timeout: 900).and_return(whereis)
+ expect(@provider).to receive(:shell_out!).with("whereis", "-s", "bonnie++", env: nil, timeout: 900).and_return(whereis)
allow(@provider).to receive(:port_name).and_return("bonnie++")
expect(@provider.port_path).to eq("/usr/ports/benchmarks/bonnie++")
end
it "should return the version number when it is installed" do
pkg_info = OpenStruct.new(:stdout => "bonnie++-1.96")
- expect(@provider).to receive(:shell_out!).with('pkg_info -E "bonnie++*"', env: nil, returns: [0, 1], timeout: 900).and_return(pkg_info)
+ expect(@provider).to receive(:shell_out!).with("pkg_info", "-E", "bonnie++*", env: nil, returns: [0, 1], timeout: 900).and_return(pkg_info)
allow(@provider).to receive(:package_name).and_return("bonnie++")
expect(@provider.current_installed_version).to eq("1.96")
end
@@ -253,7 +253,7 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
allow(@provider).to receive(:latest_link_name).and_return("perl")
cmd = OpenStruct.new(:status => true)
- expect(@provider).to receive(:shell_out!).with("pkg_add -r perl", env: nil, timeout: 900).and_return(cmd)
+ expect(@provider).to receive(:shell_out!).with("pkg_add", "-r", "perl", env: nil, timeout: 900).and_return(cmd)
@provider.install_package("perl5.8", "5.8.8_1")
end
@@ -267,7 +267,7 @@ describe Chef::Provider::Package::Freebsd::Pkg, "load_current_resource" do
allow(@provider).to receive(:latest_link_name).and_return("mysql50-server")
cmd = OpenStruct.new(:status => true)
- expect(@provider).to receive(:shell_out!).with("pkg_add -r mysql50-server", env: nil, timeout: 900).and_return(cmd)
+ expect(@provider).to receive(:shell_out!).with("pkg_add", "-r", "mysql50-server", env: nil, timeout: 900).and_return(cmd)
@provider.install_package("mysql50-server", "5.0.45_1")
end
end
diff --git a/spec/unit/provider/package/freebsd/pkgng_spec.rb b/spec/unit/provider/package/freebsd/pkgng_spec.rb
index a2bd833d9e..098052a057 100644
--- a/spec/unit/provider/package/freebsd/pkgng_spec.rb
+++ b/spec/unit/provider/package/freebsd/pkgng_spec.rb
@@ -67,7 +67,7 @@ describe Chef::Provider::Package::Freebsd::Port do
end
it "should query pkg database" do
- expect(@provider).to receive(:shell_out!).with('pkg info "zsh"', env: nil, returns: [0, 70], timeout: 900).and_return(@pkg_info)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "zsh", env: nil, returns: [0, 70], timeout: 900).and_return(@pkg_info)
expect(@provider.current_installed_version).to eq("3.1.7")
end
end
@@ -75,14 +75,14 @@ describe Chef::Provider::Package::Freebsd::Port do
describe "determining candidate version" do
it "should query repository" do
pkg_query = OpenStruct.new(:stdout => "5.0.5\n", :exitstatus => 0)
- expect(@provider).to receive(:shell_out!).with("pkg rquery '%v' zsh", env: nil, timeout: 900).and_return(pkg_query)
+ expect(@provider).to receive(:shell_out!).with("pkg", "rquery", "%v", "zsh", env: nil, timeout: 900).and_return(pkg_query)
expect(@provider.candidate_version).to eq("5.0.5")
end
it "should query specified repository when given option" do
@provider.new_resource.options("-r LocalMirror") # This requires LocalMirror repo configuration.
pkg_query = OpenStruct.new(:stdout => "5.0.3\n", :exitstatus => 0)
- expect(@provider).to receive(:shell_out!).with("pkg rquery -r LocalMirror '%v' zsh", env: nil, timeout: 900).and_return(pkg_query)
+ expect(@provider).to receive(:shell_out!).with("pkg", "rquery", "-r", "LocalMirror", "%v", "zsh", env: nil, timeout: 900).and_return(pkg_query)
expect(@provider.candidate_version).to eq("5.0.3")
end
@@ -100,7 +100,7 @@ describe Chef::Provider::Package::Freebsd::Port do
it "should handle package source from file" do
@provider.new_resource.source("/nas/pkg/repo/zsh-5.0.1.txz")
expect(@provider).to receive(:shell_out!).
- with("pkg add /nas/pkg/repo/zsh-5.0.1.txz", env: { "LC_ALL" => nil }, timeout: 900).
+ with("pkg", "add", "/nas/pkg/repo/zsh-5.0.1.txz", env: { "LC_ALL" => nil }, timeout: 900).
and_return(@install_result)
@provider.install_package("zsh", "5.0.1")
end
@@ -108,21 +108,21 @@ describe Chef::Provider::Package::Freebsd::Port do
it "should handle package source over ftp or http" do
@provider.new_resource.source("http://repo.example.com/zsh-5.0.1.txz")
expect(@provider).to receive(:shell_out!).
- with("pkg add http://repo.example.com/zsh-5.0.1.txz", env: { "LC_ALL" => nil }, timeout: 900).
+ with("pkg", "add", "http://repo.example.com/zsh-5.0.1.txz", env: { "LC_ALL" => nil }, timeout: 900).
and_return(@install_result)
@provider.install_package("zsh", "5.0.1")
end
it "should handle a package name" do
expect(@provider).to receive(:shell_out!).
- with("pkg install -y zsh", env: { "LC_ALL" => nil }, timeout: 900).and_return(@install_result)
+ with("pkg", "install", "-y", "zsh", env: { "LC_ALL" => nil }, timeout: 900).and_return(@install_result)
@provider.install_package("zsh", "5.0.1")
end
it "should handle a package name with a specified repo" do
@provider.new_resource.options("-r LocalMirror") # This requires LocalMirror repo configuration.
expect(@provider).to receive(:shell_out!).
- with("pkg install -y -r LocalMirror zsh", env: { "LC_ALL" => nil }, timeout: 900).and_return(@install_result)
+ with("pkg", "install", "-y", "-r", "LocalMirror", "zsh", env: { "LC_ALL" => nil }, timeout: 900).and_return(@install_result)
@provider.install_package("zsh", "5.0.1")
end
end
@@ -134,14 +134,14 @@ describe Chef::Provider::Package::Freebsd::Port do
it "should call pkg delete" do
expect(@provider).to receive(:shell_out!).
- with("pkg delete -y zsh-5.0.1", env: nil, timeout: 900).and_return(@install_result)
+ with("pkg", "delete", "-y", "zsh-5.0.1", env: nil, timeout: 900).and_return(@install_result)
@provider.remove_package("zsh", "5.0.1")
end
it "should not include repo option in pkg delete" do
@provider.new_resource.options("-r LocalMirror") # This requires LocalMirror repo configuration.
expect(@provider).to receive(:shell_out!).
- with("pkg delete -y zsh-5.0.1", env: nil, timeout: 900).and_return(@install_result)
+ with("pkg", "delete", "-y", "zsh-5.0.1", env: nil, timeout: 900).and_return(@install_result)
@provider.remove_package("zsh", "5.0.1")
end
end
diff --git a/spec/unit/provider/package/freebsd/port_spec.rb b/spec/unit/provider/package/freebsd/port_spec.rb
index 4ae8d960a2..5c87483fa6 100644
--- a/spec/unit/provider/package/freebsd/port_spec.rb
+++ b/spec/unit/provider/package/freebsd/port_spec.rb
@@ -68,7 +68,7 @@ describe Chef::Provider::Package::Freebsd::Port do
it "should check 'pkg_info' if system uses pkg_* tools" do
allow(@new_resource).to receive(:supports_pkgng?)
expect(@new_resource).to receive(:supports_pkgng?).and_return(false)
- expect(@provider).to receive(:shell_out!).with('pkg_info -E "zsh*"', env: nil, returns: [0, 1], timeout: 900).and_return(@pkg_info)
+ expect(@provider).to receive(:shell_out!).with("pkg_info", "-E", "zsh*", env: nil, returns: [0, 1], timeout: 900).and_return(@pkg_info)
expect(@provider.current_installed_version).to eq("3.1.7")
end
@@ -76,8 +76,8 @@ describe Chef::Provider::Package::Freebsd::Port do
pkg_enabled = OpenStruct.new(:stdout => "yes\n")
[1000016, 1000000, 901503, 902506, 802511].each do |freebsd_version|
@node.automatic_attrs[:os_version] = freebsd_version
- expect(@new_resource).to receive(:shell_out!).with("make -V WITH_PKGNG", env: nil).and_return(pkg_enabled)
- expect(@provider).to receive(:shell_out!).with('pkg info "zsh"', env: nil, returns: [0, 70], timeout: 900).and_return(@pkg_info)
+ expect(@new_resource).to receive(:shell_out!).with("make", "-V", "WITH_PKGNG", env: nil).and_return(pkg_enabled)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "zsh", env: nil, returns: [0, 70], timeout: 900).and_return(@pkg_info)
expect(@provider.current_installed_version).to eq("3.1.7")
end
end
@@ -85,7 +85,7 @@ describe Chef::Provider::Package::Freebsd::Port do
it "should check 'pkg info' if the freebsd version is greater than or equal to 1000017" do
freebsd_version = 1000017
@node.automatic_attrs[:os_version] = freebsd_version
- expect(@provider).to receive(:shell_out!).with('pkg info "zsh"', env: nil, returns: [0, 70], timeout: 900).and_return(@pkg_info)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "zsh", env: nil, returns: [0, 70], timeout: 900).and_return(@pkg_info)
expect(@provider.current_installed_version).to eq("3.1.7")
end
end
@@ -98,7 +98,7 @@ describe Chef::Provider::Package::Freebsd::Port do
it "should return candidate version if port exists" do
allow(::File).to receive(:exist?).with("/usr/ports/Makefile").and_return(true)
allow(@provider).to receive(:port_dir).and_return("/usr/ports/shells/zsh")
- expect(@provider).to receive(:shell_out!).with("make -V PORTVERSION", cwd: "/usr/ports/shells/zsh", env: nil, returns: [0, 1], timeout: 900).
+ expect(@provider).to receive(:shell_out!).with("make", "-V", "PORTVERSION", cwd: "/usr/ports/shells/zsh", env: nil, returns: [0, 1], timeout: 900).
and_return(@port_version)
expect(@provider.candidate_version).to eq("5.0.5")
end
@@ -122,13 +122,13 @@ describe Chef::Provider::Package::Freebsd::Port do
it "should query system for path given just a name" do
whereis = OpenStruct.new(:stdout => "zsh: /usr/ports/shells/zsh\n")
- expect(@provider).to receive(:shell_out!).with("whereis -s zsh", env: nil, timeout: 900).and_return(whereis)
+ expect(@provider).to receive(:shell_out!).with("whereis", "-s", "zsh", env: nil, timeout: 900).and_return(whereis)
expect(@provider.port_dir).to eq("/usr/ports/shells/zsh")
end
it "should raise exception if not found" do
whereis = OpenStruct.new(:stdout => "zsh:\n")
- expect(@provider).to receive(:shell_out!).with("whereis -s zsh", env: nil, timeout: 900).and_return(whereis)
+ expect(@provider).to receive(:shell_out!).with("whereis", "-s", "zsh", env: nil, timeout: 900).and_return(whereis)
expect { @provider.port_dir }.to raise_error(Chef::Exceptions::Package, "Could not find port with the name zsh")
end
end
@@ -141,7 +141,7 @@ describe Chef::Provider::Package::Freebsd::Port do
it "should run make install in port directory" do
allow(@provider).to receive(:port_dir).and_return("/usr/ports/shells/zsh")
expect(@provider).to receive(:shell_out!).
- with("make -DBATCH install clean", :timeout => 1800, :cwd => "/usr/ports/shells/zsh", :env => nil).
+ with("make", "-DBATCH", "install", "clean", :timeout => 1800, :cwd => "/usr/ports/shells/zsh", :env => nil).
and_return(@install_result)
@provider.install_package("zsh", "5.0.5")
end
@@ -155,7 +155,7 @@ describe Chef::Provider::Package::Freebsd::Port do
it "should run make deinstall in port directory" do
allow(@provider).to receive(:port_dir).and_return("/usr/ports/shells/zsh")
expect(@provider).to receive(:shell_out!).
- with("make deinstall", :timeout => 300, :cwd => "/usr/ports/shells/zsh", :env => nil).
+ with("make", "deinstall", :timeout => 300, :cwd => "/usr/ports/shells/zsh", :env => nil).
and_return(@install_result)
@provider.remove_package("zsh", "5.0.5")
end
diff --git a/spec/unit/provider/package/homebrew_spec.rb b/spec/unit/provider/package/homebrew_spec.rb
index 17ed5ccc41..572c54e83d 100644
--- a/spec/unit/provider/package/homebrew_spec.rb
+++ b/spec/unit/provider/package/homebrew_spec.rb
@@ -209,7 +209,7 @@ describe Chef::Provider::Package::Homebrew do
allow(provider.new_resource).to receive(:version).and_return("24.3")
allow(provider.current_resource).to receive(:version).and_return(nil)
allow(provider).to receive(:brew_info).and_return(uninstalled_brew_info)
- expect(provider).to receive(:get_response_from_command).with("brew install emacs")
+ expect(provider).to receive(:get_response_from_command).with("brew", "install", nil, "emacs")
provider.install_package("emacs", "24.3")
end
@@ -221,9 +221,9 @@ describe Chef::Provider::Package::Homebrew do
end
it "uses options to the brew command if specified" do
- allow(provider.new_resource).to receive(:options).and_return("--cocoa")
+ new_resource.options "--cocoa"
allow(provider.current_resource).to receive(:version).and_return("24.3")
- allow(provider).to receive(:get_response_from_command).with("brew install --cocoa emacs")
+ allow(provider).to receive(:get_response_from_command).with("brew", "install", "--cocoa", "emacs")
provider.install_package("emacs", "24.3")
end
end
@@ -232,7 +232,7 @@ describe Chef::Provider::Package::Homebrew do
it "uses brew upgrade to upgrade the package if it is installed" do
allow(provider.current_resource).to receive(:version).and_return("24")
allow(provider).to receive(:brew_info).and_return(installed_brew_info)
- expect(provider).to receive(:get_response_from_command).with("brew upgrade emacs")
+ expect(provider).to receive(:get_response_from_command).with("brew", "upgrade", nil, "emacs")
provider.upgrade_package("emacs", "24.3")
end
@@ -246,15 +246,15 @@ describe Chef::Provider::Package::Homebrew do
it "uses brew install to install the package if it is not installed" do
allow(provider.current_resource).to receive(:version).and_return(nil)
allow(provider).to receive(:brew_info).and_return(uninstalled_brew_info)
- expect(provider).to receive(:get_response_from_command).with("brew install emacs")
+ expect(provider).to receive(:get_response_from_command).with("brew", "install", nil, "emacs")
provider.upgrade_package("emacs", "24.3")
end
it "uses options to the brew command if specified" do
allow(provider.current_resource).to receive(:version).and_return("24")
allow(provider).to receive(:brew_info).and_return(installed_brew_info)
- allow(provider.new_resource).to receive(:options).and_return("--cocoa")
- expect(provider).to receive(:get_response_from_command).with("brew upgrade --cocoa emacs")
+ new_resource.options "--cocoa"
+ expect(provider).to receive(:get_response_from_command).with("brew", "upgrade", [ "--cocoa" ], "emacs")
provider.upgrade_package("emacs", "24.3")
end
end
@@ -263,7 +263,7 @@ describe Chef::Provider::Package::Homebrew do
it "uninstalls the package with brew uninstall" do
allow(provider.current_resource).to receive(:version).and_return("24.3")
allow(provider).to receive(:brew_info).and_return(installed_brew_info)
- expect(provider).to receive(:get_response_from_command).with("brew uninstall emacs")
+ expect(provider).to receive(:get_response_from_command).with("brew", "uninstall", nil, "emacs")
provider.remove_package("emacs", "24.3")
end
@@ -278,7 +278,7 @@ describe Chef::Provider::Package::Homebrew do
it "uninstalls the package with brew uninstall --force" do
allow(provider.current_resource).to receive(:version).and_return("24.3")
allow(provider).to receive(:brew_info).and_return(installed_brew_info)
- expect(provider).to receive(:get_response_from_command).with("brew uninstall --force emacs")
+ expect(provider).to receive(:get_response_from_command).with("brew", "uninstall", "--force", nil, "emacs")
provider.purge_package("emacs", "24.3")
end
diff --git a/spec/unit/provider/package/ips_spec.rb b/spec/unit/provider/package/ips_spec.rb
index f47385da09..3bbdd26ce3 100644
--- a/spec/unit/provider/package/ips_spec.rb
+++ b/spec/unit/provider/package/ips_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Bryan McLellan <btm@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");
@@ -26,9 +26,9 @@ describe Chef::Provider::Package::Ips do
@node = Chef::Node.new
@events = Chef::EventDispatch::Dispatcher.new
@run_context = Chef::RunContext.new(@node, {}, @events)
- @new_resource = Chef::Resource::Package.new("crypto/gnupg", @run_context)
- @current_resource = Chef::Resource::Package.new("crypto/gnupg", @run_context)
- allow(Chef::Resource::Package).to receive(:new).and_return(@current_resource)
+ @new_resource = Chef::Resource::IpsPackage.new("crypto/gnupg", @run_context)
+ @current_resource = Chef::Resource::IpsPackage.new("crypto/gnupg", @run_context)
+ allow(Chef::Resource::IpsPackage).to receive(:new).and_return(@current_resource)
@provider = Chef::Provider::Package::Ips.new(@new_resource, @run_context)
end
@@ -41,7 +41,7 @@ installed on the system. Try specifying -r to query remotely:
crypto/gnupg
PKG_STATUS
- return OpenStruct.new(:stdout => stdout, :stdin => stdin, :stderr => stderr, :status => @status, :exitstatus => 1)
+ OpenStruct.new(:stdout => stdout, :stdin => stdin, :stderr => stderr, :status => @status, :exitstatus => 1)
end
def remote_output
@@ -59,33 +59,33 @@ Packaging Date: April 1, 2012 05:55:52 PM
PKG_STATUS
stdin = StringIO.new
stderr = ""
- return OpenStruct.new(:stdout => stdout, :stdin => stdin, :stderr => stderr, :status => @status, :exitstatus => 0)
+ OpenStruct.new(:stdout => stdout, :stdin => stdin, :stderr => stderr, :status => @status, :exitstatus => 0)
end
context "when loading current resource" do
it "should create a current resource with the name of the new_resource" do
- expect(@provider).to receive(:shell_out).with("pkg info #{@new_resource.package_name}", timeout: 900).and_return(local_output)
- expect(@provider).to receive(:shell_out!).with("pkg info -r #{@new_resource.package_name}", timeout: 900).and_return(remote_output)
- expect(Chef::Resource::Package).to receive(:new).and_return(@current_resource)
+ expect(@provider).to receive(:shell_out).with("pkg", "info", @new_resource.package_name, timeout: 900).and_return(local_output)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "-r", @new_resource.package_name, timeout: 900).and_return(remote_output)
+ expect(Chef::Resource::IpsPackage).to receive(:new).and_return(@current_resource)
@provider.load_current_resource
end
it "should set the current resources package name to the new resources package name" do
- expect(@provider).to receive(:shell_out).with("pkg info #{@new_resource.package_name}", timeout: 900).and_return(local_output)
- expect(@provider).to receive(:shell_out!).with("pkg info -r #{@new_resource.package_name}", timeout: 900).and_return(remote_output)
+ expect(@provider).to receive(:shell_out).with("pkg", "info", @new_resource.package_name, timeout: 900).and_return(local_output)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "-r", @new_resource.package_name, timeout: 900).and_return(remote_output)
@provider.load_current_resource
expect(@current_resource.package_name).to eq(@new_resource.package_name)
end
it "should run pkg info with the package name" do
- expect(@provider).to receive(:shell_out).with("pkg info #{@new_resource.package_name}", timeout: 900).and_return(local_output)
- expect(@provider).to receive(:shell_out!).with("pkg info -r #{@new_resource.package_name}", timeout: 900).and_return(remote_output)
+ expect(@provider).to receive(:shell_out).with("pkg", "info", @new_resource.package_name, timeout: 900).and_return(local_output)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "-r", @new_resource.package_name, timeout: 900).and_return(remote_output)
@provider.load_current_resource
end
it "should set the installed version to nil on the current resource if package state is not installed" do
- expect(@provider).to receive(:shell_out).with("pkg info #{@new_resource.package_name}", timeout: 900).and_return(local_output)
- expect(@provider).to receive(:shell_out!).with("pkg info -r #{@new_resource.package_name}", timeout: 900).and_return(remote_output)
+ expect(@provider).to receive(:shell_out).with("pkg", "info", @new_resource.package_name, timeout: 900).and_return(local_output)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "-r", @new_resource.package_name, timeout: 900).and_return(remote_output)
@provider.load_current_resource
expect(@current_resource.version).to be_nil
end
@@ -107,31 +107,37 @@ Packaging Date: October 19, 2011 09:14:50 AM
Size: 8.07 MB
FMRI: pkg://solaris/crypto/gnupg@2.0.17,5.11-0.175.0.0.0.2.537:20111019T091450Z
INSTALLED
- expect(@provider).to receive(:shell_out).with("pkg info #{@new_resource.package_name}", timeout: 900).and_return(local)
- expect(@provider).to receive(:shell_out!).with("pkg info -r #{@new_resource.package_name}", timeout: 900).and_return(remote_output)
+ expect(@provider).to receive(:shell_out).with("pkg", "info", @new_resource.package_name, timeout: 900).and_return(local)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "-r", @new_resource.package_name, timeout: 900).and_return(remote_output)
@provider.load_current_resource
expect(@current_resource.version).to eq("2.0.17")
end
it "should return the current resource" do
- expect(@provider).to receive(:shell_out).with("pkg info #{@new_resource.package_name}", timeout: 900).and_return(local_output)
- expect(@provider).to receive(:shell_out!).with("pkg info -r #{@new_resource.package_name}", timeout: 900).and_return(remote_output)
+ expect(@provider).to receive(:shell_out).with("pkg", "info", @new_resource.package_name, timeout: 900).and_return(local_output)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "-r", @new_resource.package_name, timeout: 900).and_return(remote_output)
expect(@provider.load_current_resource).to eql(@current_resource)
end
end
context "when installing a package" do
it "should run pkg install with the package name and version" do
- expect(@provider).to receive(:shell_out).with("pkg install -q crypto/gnupg@2.0.17", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("pkg", "install", "-q", "crypto/gnupg@2.0.17", timeout: 900)
@provider.install_package("crypto/gnupg", "2.0.17")
end
it "should run pkg install with the package name and version and options if specified" do
- expect(@provider).to receive(:shell_out).with("pkg --no-refresh install -q crypto/gnupg@2.0.17", timeout: 900)
- allow(@new_resource).to receive(:options).and_return("--no-refresh")
+ expect(@provider).to receive(:shell_out!).with("pkg", "--no-refresh", "install", "-q", "crypto/gnupg@2.0.17", timeout: 900)
+ @new_resource.options "--no-refresh"
@provider.install_package("crypto/gnupg", "2.0.17")
end
+ it "raises an error if package fails to install" do
+ expect(@provider).to receive(:shell_out!).with("pkg", "--no-refresh", "install", "-q", "crypto/gnupg@2.0.17", timeout: 900).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ allow(@new_resource).to receive(:options).and_return("--no-refresh")
+ expect { @provider.install_package("crypto/gnupg", "2.0.17") }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
+ end
+
it "should not include the human-readable version in the candidate_version" do
remote = remote_output
remote.stdout = <<-PKG_STATUS
@@ -146,8 +152,8 @@ Packaging Date: April 1, 2012 05:55:52 PM
Size: 2.57 MB
FMRI: pkg://omnios/security/sudo@1.8.4.1,5.11-0.151002:20120401T175552Z
PKG_STATUS
- expect(@provider).to receive(:shell_out).with("pkg info #{@new_resource.package_name}", timeout: 900).and_return(local_output)
- expect(@provider).to receive(:shell_out!).with("pkg info -r #{@new_resource.package_name}", timeout: 900).and_return(remote)
+ expect(@provider).to receive(:shell_out).with("pkg", "info", @new_resource.package_name, timeout: 900).and_return(local_output)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "-r", @new_resource.package_name, timeout: 900).and_return(remote)
@provider.load_current_resource
expect(@current_resource.version).to be_nil
expect(@provider.candidate_version).to eql("1.8.4.1")
@@ -187,8 +193,8 @@ Packaging Date: October 19, 2011 09:14:50 AM
FMRI: pkg://solaris/crypto/gnupg@2.0.18,5.11-0.175.0.0.0.2.537:20111019T091450Z
REMOTE
- expect(@provider).to receive(:shell_out).with("pkg info #{@new_resource.package_name}", timeout: 900).and_return(local)
- expect(@provider).to receive(:shell_out!).with("pkg info -r #{@new_resource.package_name}", timeout: 900).and_return(remote)
+ expect(@provider).to receive(:shell_out).with("pkg", "info", @new_resource.package_name, timeout: 900).and_return(local)
+ expect(@provider).to receive(:shell_out!).with("pkg", "info", "-r", @new_resource.package_name, timeout: 900).and_return(remote)
expect(@provider).to receive(:install_package).exactly(0).times
@provider.run_action(:install)
end
@@ -199,7 +205,7 @@ REMOTE
end
it "should run pkg install with the --accept flag" do
- expect(@provider).to receive(:shell_out).with("pkg install -q --accept crypto/gnupg@2.0.17", timeout: 900)
+ expect(@provider).to receive(:shell_out).with("pkg", "install", "-q", "--accept", "crypto/gnupg@2.0.17", timeout: 900).and_return(local_output)
@provider.install_package("crypto/gnupg", "2.0.17")
end
end
@@ -207,20 +213,20 @@ REMOTE
context "when upgrading a package" do
it "should run pkg install with the package name and version" do
- expect(@provider).to receive(:shell_out).with("pkg install -q crypto/gnupg@2.0.17", timeout: 900)
+ expect(@provider).to receive(:shell_out).with("pkg", "install", "-q", "crypto/gnupg@2.0.17", timeout: 900).and_return(local_output)
@provider.upgrade_package("crypto/gnupg", "2.0.17")
end
end
context "when uninstalling a package" do
it "should run pkg uninstall with the package name and version" do
- expect(@provider).to receive(:shell_out!).with("pkg uninstall -q crypto/gnupg@2.0.17", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("pkg", "uninstall", "-q", "crypto/gnupg@2.0.17", timeout: 900)
@provider.remove_package("crypto/gnupg", "2.0.17")
end
it "should run pkg uninstall with the package name and version and options if specified" do
- expect(@provider).to receive(:shell_out!).with("pkg --no-refresh uninstall -q crypto/gnupg@2.0.17", timeout: 900)
- allow(@new_resource).to receive(:options).and_return("--no-refresh")
+ expect(@provider).to receive(:shell_out!).with("pkg", "--no-refresh", "uninstall", "-q", "crypto/gnupg@2.0.17", timeout: 900)
+ @new_resource.options "--no-refresh"
@provider.remove_package("crypto/gnupg", "2.0.17")
end
end
diff --git a/spec/unit/provider/package/macports_spec.rb b/spec/unit/provider/package/macports_spec.rb
index b90cf89047..d690791d16 100644
--- a/spec/unit/provider/package/macports_spec.rb
+++ b/spec/unit/provider/package/macports_spec.rb
@@ -105,7 +105,7 @@ EOF
it "should run the port install command with the correct version" do
expect(@current_resource).to receive(:version).and_return("4.1.6")
@provider.current_resource = @current_resource
- expect(@provider).to receive(:shell_out!).with("port install zsh @4.2.7", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "install", "zsh", "@4.2.7", timeout: 900)
@provider.install_package("zsh", "4.2.7")
end
@@ -122,7 +122,7 @@ EOF
expect(@current_resource).to receive(:version).and_return("4.1.6")
@provider.current_resource = @current_resource
allow(@new_resource).to receive(:options).and_return("-f")
- expect(@provider).to receive(:shell_out!).with("port -f install zsh @4.2.7", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "-f", "install", "zsh", "@4.2.7", timeout: 900)
@provider.install_package("zsh", "4.2.7")
end
@@ -130,36 +130,36 @@ EOF
describe "purge_package" do
it "should run the port uninstall command with the correct version" do
- expect(@provider).to receive(:shell_out!).with("port uninstall zsh @4.2.7", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "uninstall", "zsh", "@4.2.7", timeout: 900)
@provider.purge_package("zsh", "4.2.7")
end
it "should purge the currently active version if no explicit version is passed in" do
- expect(@provider).to receive(:shell_out!).with("port uninstall zsh", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "uninstall", "zsh", timeout: 900)
@provider.purge_package("zsh", nil)
end
it "should add options to the port command when specified" do
allow(@new_resource).to receive(:options).and_return("-f")
- expect(@provider).to receive(:shell_out!).with("port -f uninstall zsh @4.2.7", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "-f", "uninstall", "zsh", "@4.2.7", timeout: 900)
@provider.purge_package("zsh", "4.2.7")
end
end
describe "remove_package" do
it "should run the port deactivate command with the correct version" do
- expect(@provider).to receive(:shell_out!).with("port deactivate zsh @4.2.7", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "deactivate", "zsh", "@4.2.7", timeout: 900)
@provider.remove_package("zsh", "4.2.7")
end
it "should remove the currently active version if no explicit version is passed in" do
- expect(@provider).to receive(:shell_out!).with("port deactivate zsh", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "deactivate", "zsh", timeout: 900)
@provider.remove_package("zsh", nil)
end
it "should add options to the port command when specified" do
allow(@new_resource).to receive(:options).and_return("-f")
- expect(@provider).to receive(:shell_out!).with("port -f deactivate zsh @4.2.7", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "-f", "deactivate", "zsh", "@4.2.7", timeout: 900)
@provider.remove_package("zsh", "4.2.7")
end
end
@@ -169,7 +169,7 @@ EOF
expect(@current_resource).to receive(:version).at_least(:once).and_return("4.1.6")
@provider.current_resource = @current_resource
- expect(@provider).to receive(:shell_out!).with("port upgrade zsh @4.2.7", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "upgrade", "zsh", "@4.2.7", timeout: 900)
@provider.upgrade_package("zsh", "4.2.7")
end
@@ -195,7 +195,7 @@ EOF
expect(@current_resource).to receive(:version).at_least(:once).and_return("4.1.6")
@provider.current_resource = @current_resource
- expect(@provider).to receive(:shell_out!).with("port -f upgrade zsh @4.2.7", timeout: 900)
+ expect(@provider).to receive(:shell_out!).with("port", "-f", "upgrade", "zsh", "@4.2.7", timeout: 900)
@provider.upgrade_package("zsh", "4.2.7")
end
diff --git a/spec/unit/provider/package/msu_spec.rb b/spec/unit/provider/package/msu_spec.rb
new file mode 100644
index 0000000000..b9091d757a
--- /dev/null
+++ b/spec/unit/provider/package/msu_spec.rb
@@ -0,0 +1,283 @@
+#
+# 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::Package::Msu, :windows_only do
+ let(:timeout) {}
+
+ let(:new_resource) { Chef::Resource::MsuPackage.new("windows_test_pkg") }
+
+ let(:provider) do
+ node = Chef::Node.new
+ events = Chef::EventDispatch::Dispatcher.new
+ run_context = Chef::RunContext.new(node, {}, events)
+ Chef::Provider::Package::Msu.new(new_resource, run_context)
+ end
+
+ let(:installed_package_list_stdout) do
+ <<-EOF
+Packages listing:
+Package Identity : Package_for_KB2999486~31bf3856ad364e35~amd64~~6.1.9768.0
+Package Identity : Package_for_KB2994825~31bf3856ad364e35~amd64~~6.1.7601.0
+ EOF
+ end
+
+ let(:package_version_stdout) do
+ <<-EOF
+Package information:
+Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0
+State : Installed
+Dependency : Language Pack
+The operation completed successfully
+ EOF
+ end
+
+ let(:get_package_info_stdout) do
+ <<-EOF
+Deployment Image Servicing and Management tool
+Version: 6.1.7600.16385
+
+Image Version: 6.1.7600.16385
+
+Package information:
+Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0
+Applicable : Yes
+Copyright : Microsoft Corporation
+Company : Microsoft Corporation
+State : Installed
+Dependency : Language Pack
+The operation completed successfully
+ EOF
+ end
+
+ def allow_get_packages
+ get_packages_stdout = <<-EOF
+Deployment Image Servicing and Management tool
+Version: 6.1.7600.16385
+
+Image Version: 6.1.7600.16385
+
+Packages listing:
+
+Package Identity : Package_for_KB2999486~31bf3856ad364e35~amd64~~6.1.9768.0
+State : Installed
+Release Type : Language Pack
+Install Time : 2/11/2015 11:33 PM
+
+Package Identity : Package_for_KB2994825~31bf3856ad364e35~amd64~~6.1.7601.0
+State : Installed
+Release Type : Language Pack
+Install Time : 2/11/2015 11:33 PM
+
+Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0
+State : Installed
+Release Type : Feature Pack
+Install Time : 11/21/2010 3:40 AM
+
+The operation completed successfully.
+ EOF
+ get_packages_obj = double(stdout: get_packages_stdout)
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-Packages").and_return(get_packages_obj)
+ end
+
+ before do
+ allow(Dir).to receive(:mktmpdir)
+ allow(provider).to receive(:cleanup_after_converge)
+ end
+
+ describe "#initialize" do
+ it "returns the correct class" do
+ expect(provider).to be_kind_of(Chef::Provider::Package::Msu)
+ end
+ end
+
+ describe "#load_current_resource" do
+ before do
+ new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.msu"
+ cab_file = "c:\\temp\\test6.1-kb2664825-v3-x64.cab"
+ allow(provider).to receive(:extract_msu_contents)
+ allow(provider).to receive(:read_cab_files_from_xml).and_return([cab_file])
+ installed_package_list_obj = double(stdout: installed_package_list_stdout)
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj)
+ package_version_obj = double(stdout: package_version_stdout)
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{cab_file}\"").and_return(package_version_obj)
+ end
+
+ it "returns a current_resource" do
+ expect(provider.load_current_resource).to be_kind_of(Chef::Resource::MsuPackage)
+ end
+
+ it "sets the current_resource.version to nil when the package is not installed" do
+ provider.load_current_resource
+ expect(provider.current_resource.version).to eql([nil])
+ end
+
+ it "calls download_source_file method if source is a URL" do
+ new_resource.source = "https://www.something.com/Test6.1-KB2664825-v3-x64.msu"
+ expect(provider).to receive(:download_source_file)
+ provider.load_current_resource
+ end
+ end
+
+ describe "#source_resource" do
+ before do
+ new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.msu"
+ new_resource.cookbook_name = "Msu_package"
+ end
+
+ it "sets the desired parameters of downloades msu file" do
+ allow(provider).to receive(:default_download_cache_path).and_return("C:\\chef\\cache\\package")
+ source_resource = provider.source_resource
+ expect(source_resource.path).to be == "C:\\chef\\cache\\package"
+ expect(source_resource.name).to be == "windows_test_pkg"
+ expect(source_resource.source).to be == [new_resource.source]
+ expect(source_resource.cookbook_name).to be == "Msu_package"
+ expect(source_resource.checksum).to be nil
+ end
+ end
+
+ describe "#default_download_cache_path" do
+ before do
+ new_resource.source = "https://www.something.com/Test6.1-KB2664825-v3-x64.msu"
+ end
+
+ it "returns a clean cache path where the msu file is downloaded" do
+ allow(Chef::FileCache).to receive(:create_cache_path).and_return("C:\\chef\\abc\\package")
+ path = provider.default_download_cache_path
+ expect(path).to be == "C:\\chef\\abc\\package\\Test6.1-KB2664825-v3-x64.msu"
+ end
+ end
+
+ describe "action specs" do
+ before do
+ new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.msu"
+ cab_file = "c:\\temp\\test6.1-kb2664825-v3-x64.cab"
+ allow(provider).to receive(:extract_msu_contents)
+ allow(provider).to receive(:read_cab_files_from_xml).and_return([cab_file])
+ installed_package_list_obj = double(stdout: installed_package_list_stdout)
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj)
+ package_version_obj = double(stdout: package_version_stdout)
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{cab_file}\"").and_return(package_version_obj)
+ end
+
+ describe "#action_install" do
+ it "installs package if not already installed" do
+ provider.load_current_resource
+ expect(provider.current_resource.version).to eql([nil])
+ expect(provider).to receive(:install_package)
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "does not install package if already installed" do
+ get_package_info_obj = double(stdout: get_package_info_stdout)
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{new_resource.source}\"").and_return(get_package_info_obj)
+ allow_get_packages
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackageName:\"Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0\"").and_return(get_package_info_obj)
+ provider.load_current_resource
+ expect(provider.current_resource.version).to eql(["6.1.3.0"])
+ expect(provider).not_to receive(:install_package)
+ provider.run_action(:install)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+ end
+
+ describe "#action_remove" do
+ it "does nothing when the package is not present" do
+ provider.load_current_resource
+ expect(provider).not_to receive(:remove_package)
+ provider.run_action(:remove)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "removes packages if package is installed" do
+ get_package_info_obj = double(stdout: get_package_info_stdout)
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{new_resource.source}\"").and_return(get_package_info_obj)
+ allow_get_packages
+ allow_any_instance_of(Chef::Provider::Package::Cab).to receive(:dism_command).with("/Get-PackageInfo /PackageName:\"Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0\"").and_return(get_package_info_obj)
+ provider.load_current_resource
+ expect(provider.current_resource.version).to eql(["6.1.3.0"])
+ expect(provider).to receive(:remove_package)
+ provider.run_action(:remove)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+
+ context "Invalid package source" do
+ def package_version_stdout
+ package_version_stdout = <<-EOF
+
+ Deployment Image Servicing and Management tool
+ Version: 6.1.7600.16385
+
+ Image Version: 6.1.7600.16385
+
+ An error occurred trying to open - c:\\temp\\test6.1-KB2664825-v3-x64.cab Error: 0x80070003
+ Error: 3
+ The system cannot find the path specified.
+ The DISM log file can be found at C:\\Windows\\Logs\\DISM\\dism.log.
+ EOF
+ end
+
+ it "raises error for invalid source path or file" do
+ expect { provider.load_current_resource }.to raise_error(Chef::Exceptions::Package, "DISM: The system cannot find the path or file specified.")
+ end
+ end
+ end
+
+ describe "#extract_msu_contents" do
+ it "extracts the msu contents by using mixlib shellout" do
+ expect(provider).to receive(:shell_out_with_timeout!).with("#{ENV['SYSTEMROOT']}\\system32\\expand.exe -f:* msu_file destination")
+ provider.extract_msu_contents("msu_file", "destination")
+ end
+ end
+
+ describe "#read_cab_files_from_xml" do
+ it "raises error if the xml file is not present" do
+ allow(Dir).to receive(:glob).and_return([])
+ expect { provider.read_cab_files_from_xml("msu_dir") }.to raise_error(Chef::Exceptions::Package)
+ end
+
+ it "parses xml file with single cab file" do
+ xml_file = File.join(CHEF_SPEC_DATA, "sample_msu1.xml")
+ allow(Dir).to receive(:glob).and_return([xml_file])
+ cab_files = provider.read_cab_files_from_xml("msu_dir")
+ expect(cab_files).to eql(["msu_dir/IE10-Windows6.1-KB2859903-x86.CAB"])
+ end
+
+# We couldn't find any msu file with multiple cab files in it.
+# So we are not 100% sure about the structure of XML file in this case
+# The specs below cover 2 possible XML formats
+ context "handles different xml formats for multiple cab files in the msu package" do
+ it "parses xml file with multiple <package> tags" do
+ xml_file = File.join(CHEF_SPEC_DATA, "sample_msu2.xml")
+ allow(Dir).to receive(:glob).and_return([xml_file])
+ cab_files = provider.read_cab_files_from_xml("msu_dir")
+ expect(cab_files).to eql(["msu_dir/IE10-Windows6.1-KB2859903-x86.CAB", "msu_dir/abc.CAB"])
+ end
+
+ it "parses xml file with multiple <servicing> tags" do
+ xml_file = File.join(CHEF_SPEC_DATA, "sample_msu3.xml")
+ allow(Dir).to receive(:glob).and_return([xml_file])
+ cab_files = provider.read_cab_files_from_xml("msu_dir")
+ expect(cab_files).to eql(["msu_dir/IE10-Windows6.1-KB2859903-x86.CAB", "msu_dir/abc.CAB"])
+ end
+ end
+ end
+end
diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb
index 3e1c1c90b6..20eb85dfcf 100644
--- a/spec/unit/provider/package/openbsd_spec.rb
+++ b/spec/unit/provider/package/openbsd_spec.rb
@@ -45,17 +45,17 @@ describe Chef::Provider::Package::Openbsd do
context "when not already installed" do
before do
- allow(provider).to receive(:shell_out!).with("pkg_info -e \"#{name}->0\"", anything()).and_return(instance_double("shellout", :stdout => ""))
+ allow(provider).to receive(:shell_out!).with("pkg_info", "-e", "#{name}->0", anything()).and_return(instance_double("shellout", :stdout => ""))
end
context "when there is a single candidate" do
context "when source is not provided" do
it "should run the installation command" do
- expect(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}\"", anything()).and_return(
+ expect(provider).to receive(:shell_out!).with("pkg_info", "-I", name, anything()).and_return(
instance_double("shellout", :stdout => "#{name}-#{version}\n"))
expect(provider).to receive(:shell_out!).with(
- "pkg_add -r #{name}-#{version}",
+ "pkg_add", "-r", "#{name}-#{version}",
{ :env => { "PKG_PATH" => "http://ftp.OpenBSD.org/pub/OpenBSD/5.5/packages/amd64/" }, timeout: 900 }
) { OpenStruct.new :status => true }
provider.run_action(:install)
@@ -69,7 +69,7 @@ describe Chef::Provider::Package::Openbsd do
context "if no version is specified" do
it "should raise an exception" do
- expect(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}\"", anything()).and_return(
+ expect(provider).to receive(:shell_out!).with("pkg_info", "-I", name, anything()).and_return(
instance_double("shellout", :stdout => "#{name}-#{version}-#{flavor_a}\n#{name}-#{version}-#{flavor_b}\n"))
expect { provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package, /multiple matching candidates/)
end
@@ -83,11 +83,11 @@ describe Chef::Provider::Package::Openbsd do
context "if no version is specified" do
it "should run the installation command" do
- expect(provider).to receive(:shell_out!).with("pkg_info -e \"#{package_name}->0\"", anything()).and_return(instance_double("shellout", :stdout => ""))
- expect(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}\"", anything()).and_return(
+ expect(provider).to receive(:shell_out!).with("pkg_info", "-e", "#{package_name}->0", anything()).and_return(instance_double("shellout", :stdout => ""))
+ expect(provider).to receive(:shell_out!).with("pkg_info", "-I", name, anything()).and_return(
instance_double("shellout", :stdout => "#{name}-#{version}-#{flavor}\n"))
expect(provider).to receive(:shell_out!).with(
- "pkg_add -r #{name}-#{version}-#{flavor}",
+ "pkg_add", "-r", "#{name}-#{version}-#{flavor}",
{ env: { "PKG_PATH" => "http://ftp.OpenBSD.org/pub/OpenBSD/5.5/packages/amd64/" }, timeout: 900 }
) { OpenStruct.new :status => true }
provider.run_action(:install)
@@ -98,12 +98,12 @@ describe Chef::Provider::Package::Openbsd do
context "if a version is specified" do
it "should use the flavor from the version" do
- expect(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}-#{version}-#{flavor_b}\"", anything()).and_return(
+ expect(provider).to receive(:shell_out!).with("pkg_info", "-I", "#{name}-#{version}-#{flavor_b}", anything()).and_return(
instance_double("shellout", :stdout => "#{name}-#{version}-#{flavor_a}\n"))
new_resource.version("#{version}-#{flavor_b}")
expect(provider).to receive(:shell_out!).with(
- "pkg_add -r #{name}-#{version}-#{flavor_b}",
+ "pkg_add", "-r", "#{name}-#{version}-#{flavor_b}",
{ env: { "PKG_PATH" => "http://ftp.OpenBSD.org/pub/OpenBSD/5.5/packages/amd64/" }, timeout: 900 }
) { OpenStruct.new :status => true }
provider.run_action(:install)
@@ -123,7 +123,7 @@ describe Chef::Provider::Package::Openbsd do
end
it "should run the command to delete the installed package" do
expect(@provider).to receive(:shell_out!).with(
- "pkg_delete #{@name}", env: nil, timeout: 900
+ "pkg_delete", @name, env: nil, timeout: 900
) { OpenStruct.new :status => true }
@provider.remove_package(@name, nil)
end
diff --git a/spec/unit/provider/package/pacman_spec.rb b/spec/unit/provider/package/pacman_spec.rb
index ce9107f31b..32af9e4bd2 100644
--- a/spec/unit/provider/package/pacman_spec.rb
+++ b/spec/unit/provider/package/pacman_spec.rb
@@ -51,7 +51,7 @@ ERR
end
it "should run pacman query with the package name" do
- expect(@provider).to receive(:shell_out).with("pacman -Qi #{@new_resource.package_name}", { timeout: 900 }).and_return(@status)
+ expect(@provider).to receive(:shell_out).with("pacman", "-Qi", @new_resource.package_name, { timeout: 900 }).and_return(@status)
@provider.load_current_resource
end
@@ -121,7 +121,7 @@ Include = /etc/pacman.d/mirrorlist
PACMAN_CONF
status = double(:stdout => "customrepo nano 1.2.3-4", :exitstatus => 0)
- allow(::File).to receive(:exists?).with("/etc/pacman.conf").and_return(true)
+ allow(::File).to receive(:exist?).with("/etc/pacman.conf").and_return(true)
allow(::File).to receive(:read).with("/etc/pacman.conf").and_return(@pacman_conf)
allow(@provider).to receive(:shell_out).and_return(status)
@@ -151,12 +151,12 @@ PACMAN_CONF
describe Chef::Provider::Package::Pacman, "install_package" do
it "should run pacman install with the package name and version" do
- expect(@provider).to receive(:shell_out!).with("pacman --sync --noconfirm --noprogressbar nano", { timeout: 900 })
+ expect(@provider).to receive(:shell_out!).with("pacman", "--sync", "--noconfirm", "--noprogressbar", "nano", { timeout: 900 })
@provider.install_package("nano", "1.0")
end
it "should run pacman install with the package name and version and options if specified" do
- expect(@provider).to receive(:shell_out!).with("pacman --sync --noconfirm --noprogressbar --debug nano", { timeout: 900 })
+ expect(@provider).to receive(:shell_out!).with("pacman", "--sync", "--noconfirm", "--noprogressbar", "--debug", "nano", { timeout: 900 })
allow(@new_resource).to receive(:options).and_return("--debug")
@provider.install_package("nano", "1.0")
@@ -172,12 +172,12 @@ PACMAN_CONF
describe Chef::Provider::Package::Pacman, "remove_package" do
it "should run pacman remove with the package name" do
- expect(@provider).to receive(:shell_out!).with("pacman --remove --noconfirm --noprogressbar nano", { timeout: 900 })
+ expect(@provider).to receive(:shell_out!).with("pacman", "--remove", "--noconfirm", "--noprogressbar", "nano", { timeout: 900 })
@provider.remove_package("nano", "1.0")
end
it "should run pacman remove with the package name and options if specified" do
- expect(@provider).to receive(:shell_out!).with("pacman --remove --noconfirm --noprogressbar --debug nano", { timeout: 900 })
+ expect(@provider).to receive(:shell_out!).with("pacman", "--remove", "--noconfirm", "--noprogressbar", "--debug", "nano", { timeout: 900 })
allow(@new_resource).to receive(:options).and_return("--debug")
@provider.remove_package("nano", "1.0")
diff --git a/spec/unit/provider/package/paludis_spec.rb b/spec/unit/provider/package/paludis_spec.rb
index b984aeb83f..df0150c8c0 100644
--- a/spec/unit/provider/package/paludis_spec.rb
+++ b/spec/unit/provider/package/paludis_spec.rb
@@ -59,7 +59,7 @@ PKG_STATUS
end
it "should run pkg info with the package name" do
- expect(@provider).to receive(:shell_out!).with("cave -L warning print-ids -M none -m \"#{@new_resource.package_name}\" -f \"%c/%p %v %r\n\"").and_return(@shell_out)
+ expect(@provider).to receive(:shell_out!).with("cave", "-L", "warning", "print-ids", "-M", "none", "-m", @new_resource.package_name, "-f", "%c/%p %v %r\n").and_return(@shell_out)
@provider.load_current_resource
end
@@ -86,13 +86,13 @@ INSTALLED
context "when installing a package" do
it "should run pkg install with the package name and version" do
- expect(@provider).to receive(:shell_out!).with("cave -L warning resolve -x \"=net/ntp-4.2.6_p5-r2\"", { :timeout => @new_resource.timeout })
+ expect(@provider).to receive(:shell_out!).with("cave", "-L", "warning", "resolve", "-x", "=net/ntp-4.2.6_p5-r2", { :timeout => @new_resource.timeout || 900 })
@provider.install_package("net/ntp", "4.2.6_p5-r2")
end
it "should run pkg install with the package name and version and options if specified" do
- expect(@provider).to receive(:shell_out!).with("cave -L warning resolve -x --preserve-world \"=net/ntp-4.2.6_p5-r2\"", { :timeout => @new_resource.timeout })
- allow(@new_resource).to receive(:options).and_return("--preserve-world")
+ expect(@provider).to receive(:shell_out!).with("cave", "-L", "warning", "resolve", "-x", "--preserve-world", "=net/ntp-4.2.6_p5-r2", { :timeout => @new_resource.timeout || 900 })
+ @new_resource.options "--preserve-world"
@provider.install_package("net/ntp", "4.2.6_p5-r2")
end
@@ -101,7 +101,7 @@ INSTALLED
sys-process/lsof 4.87 arbor
sys-process/lsof 4.87 x86_64
PKG_STATUS
- expect(@provider).to receive(:shell_out!).with("cave -L warning resolve -x \"=sys-process/lsof-4.87\"", { :timeout => @new_resource.timeout })
+ expect(@provider).to receive(:shell_out!).with("cave", "-L", "warning", "resolve", "-x", "=sys-process/lsof-4.87", { :timeout => @new_resource.timeout || 900 })
@provider.install_package("sys-process/lsof", "4.87")
end
@@ -119,14 +119,14 @@ PKG_STATUS
context "when upgrading a package" do
it "should run pkg install with the package name and version" do
- expect(@provider).to receive(:shell_out!).with("cave -L warning resolve -x \"=net/ntp-4.2.6_p5-r2\"", { :timeout => @new_resource.timeout })
+ expect(@provider).to receive(:shell_out!).with("cave", "-L", "warning", "resolve", "-x", "=net/ntp-4.2.6_p5-r2", { :timeout => @new_resource.timeout || 900 })
@provider.upgrade_package("net/ntp", "4.2.6_p5-r2")
end
end
context "when uninstalling a package" do
it "should run pkg uninstall with the package name and version" do
- expect(@provider).to receive(:shell_out!).with("cave -L warning uninstall -x \"=net/ntp-4.2.6_p5-r2\"")
+ expect(@provider).to receive(:shell_out!).with("cave", "-L", "warning", "uninstall", "-x", "=net/ntp-4.2.6_p5-r2")
@provider.remove_package("net/ntp", "4.2.6_p5-r2")
end
diff --git a/spec/unit/provider/package/portage_spec.rb b/spec/unit/provider/package/portage_spec.rb
index ebb5b3139f..d77e180181 100644
--- a/spec/unit/provider/package/portage_spec.rb
+++ b/spec/unit/provider/package/portage_spec.rb
@@ -284,31 +284,30 @@ EOF
describe Chef::Provider::Package::Portage, "install_package" do
it "should install a normally versioned package using portage" do
- expect(@provider).to receive(:shell_out!).with("emerge -g --color n --nospinner --quiet =dev-util/git-1.0.0")
+ expect(@provider).to receive(:shell_out!).with("emerge", "-g", "--color", "n", "--nospinner", "--quiet", "=dev-util/git-1.0.0")
@provider.install_package("dev-util/git", "1.0.0")
end
it "should install a tilde versioned package using portage" do
- expect(@provider).to receive(:shell_out!).with("emerge -g --color n --nospinner --quiet ~dev-util/git-1.0.0")
+ expect(@provider).to receive(:shell_out!).with("emerge", "-g", "--color", "n", "--nospinner", "--quiet", "~dev-util/git-1.0.0")
@provider.install_package("dev-util/git", "~1.0.0")
end
it "should add options to the emerge command when specified" do
- expect(@provider).to receive(:shell_out!).with("emerge -g --color n --nospinner --quiet --oneshot =dev-util/git-1.0.0")
- allow(@new_resource).to receive(:options).and_return("--oneshot")
-
+ expect(@provider).to receive(:shell_out!).with("emerge", "-g", "--color", "n", "--nospinner", "--quiet", "--oneshot", "=dev-util/git-1.0.0")
+ @new_resource.options "--oneshot"
@provider.install_package("dev-util/git", "1.0.0")
end
end
describe Chef::Provider::Package::Portage, "remove_package" do
it "should un-emerge the package with no version specified" do
- expect(@provider).to receive(:shell_out!).with("emerge --unmerge --color n --nospinner --quiet dev-util/git")
+ expect(@provider).to receive(:shell_out!).with("emerge", "--unmerge", "--color", "n", "--nospinner", "--quiet", "dev-util/git")
@provider.remove_package("dev-util/git", nil)
end
it "should un-emerge the package with a version specified" do
- expect(@provider).to receive(:shell_out!).with("emerge --unmerge --color n --nospinner --quiet =dev-util/git-1.0.0")
+ expect(@provider).to receive(:shell_out!).with("emerge", "--unmerge", "--color", "n", "--nospinner", "--quiet", "=dev-util/git-1.0.0")
@provider.remove_package("dev-util/git", "1.0.0")
end
end
diff --git a/spec/unit/provider/package/powershell_spec.rb b/spec/unit/provider/package/powershell_spec.rb
new file mode 100644
index 0000000000..4ab100f07f
--- /dev/null
+++ b/spec/unit/provider/package/powershell_spec.rb
@@ -0,0 +1,337 @@
+#
+# Author:: Dheeraj Dubey(<dheeraj.dubey@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"
+require "chef/mixin/powershell_out"
+
+describe Chef::Provider::Package::Powershell do
+ include Chef::Mixin::PowershellOut
+ let(:timeout) { 900 }
+
+ let(:new_resource) { Chef::Resource::PowershellPackage.new("windows_test_pkg") }
+
+ let(:provider) do
+ node = Chef::Node.new
+ events = Chef::EventDispatch::Dispatcher.new
+ run_context = Chef::RunContext.new(node, {}, events)
+ Chef::Provider::Package::Powershell.new(new_resource, run_context)
+ end
+
+ let(:package_xcertificate_installed) do
+ double("powershell_out", :stdout => "2.1.0.0\r\n")
+ end
+
+ let(:package_xcertificate_installed_2_0_0_0) do
+ double("powershell_out", :stdout => "2.0.0.0\r\n")
+ end
+
+ let(:package_xcertificate_available) do
+ double("powershell_out", :stdout => "2.1.0.0\r\n")
+ end
+
+ let(:package_xcertificate_available_2_0_0_0) do
+ double("powershell_out", :stdout => "2.0.0.0\r\n")
+ end
+
+ let(:package_xcertificate_not_installed) do
+ double("powershell_out", :stdout => "")
+ end
+
+ let(:package_xcertificate_not_available) do
+ double("powershell_out", :stdout => "")
+ end
+
+ let(:package_xnetworking_installed) do
+ double("powershell_out", :stdout => "2.12.0.0\r\n")
+ end
+
+ let(:package_xnetworking_installed_2_11_0_0) do
+ double("powershell_out", :stdout => "2.11.0.0\r\n")
+ end
+
+ let(:package_xnetworking_available) do
+ double("powershell_out", :stdout => "2.12.0.0\r\n")
+ end
+
+ let(:package_xnetworking_available_2_11_0_0) do
+ double("powershell_out", :stdout => "2.11.0.0\r\n")
+ end
+
+ let(:package_xnetworking_not_installed) do
+ double("powershell_out", :stdout => "")
+ end
+
+ let(:package_xnetworking_not_available) do
+ double("powershell_out", :stdout => "")
+ end
+
+ let(:package_7zip_available) do
+ double("powershell_out", :stdout => "16.02\r\n")
+ end
+
+ let(:package_7zip_not_installed) do
+ double("powershell_out", :stdout => "")
+ end
+
+ let(:powershell_installed_version) do
+ double("powershell_out", :stdout => "5")
+ end
+
+ describe "#initialize" do
+ it "should return the correct class" do
+ expect(provider).to be_kind_of(Chef::Provider::Package::Powershell)
+ end
+ end
+
+ describe "#candidate_version" do
+
+ it "should set the candidate_version to the latest version when not pinning" do
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ new_resource.package_name(["xNetworking"])
+ new_resource.version(nil)
+ expect(provider.candidate_version).to eql(["2.12.0.0"])
+ end
+
+ it "should set the candidate_version to the latest version when not pinning and package name is space seperated" do
+ allow(provider).to receive(:powershell_out).with("(Find-Package '7-Zip 16.02 (x64)' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_7zip_available)
+ new_resource.package_name(["7-Zip 16.02 (x64)"])
+ new_resource.version(nil)
+ expect(provider.candidate_version).to eql(["16.02"])
+ end
+
+ it "should set the candidate_version to pinned version if available" do
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.0.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available_2_0_0_0)
+ new_resource.package_name(["xCertificate"])
+ new_resource.version(["2.0.0.0"])
+ expect(provider.candidate_version).to eql(["2.0.0.0"])
+ end
+
+ it "should set the candidate_version to nil if there is no candidate" do
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ new_resource.package_name(["xCertificate"])
+ expect(provider.candidate_version).to eql([nil])
+ end
+
+ it "should set the candidate_version correctly when there are two packages to install" do
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ new_resource.package_name(%w{xCertificate xNetworking})
+ new_resource.version(nil)
+ expect(provider.candidate_version).to eql(["2.1.0.0", "2.12.0.0"])
+ end
+
+ it "should set the candidate_version correctly when only the first is installable" do
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ new_resource.package_name(%w{xCertificate xNetworking})
+ new_resource.version(nil)
+ expect(provider.candidate_version).to eql(["2.1.0.0", nil])
+ end
+
+ it "should set the candidate_version correctly when only the last is installable" do
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ new_resource.package_name(%w{xCertificate xNetworking})
+ new_resource.version(nil)
+ expect(provider.candidate_version).to eql([nil, "2.12.0.0"])
+ end
+
+ it "should set the candidate_version correctly when neither are is installable and version is passed as nil array" do
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ new_resource.package_name(%w{xNetworking xCertificate})
+ new_resource.version([nil, nil])
+ expect(provider.candidate_version).to eql([nil, nil])
+ end
+
+ it "should set the candidate_version correctly when neither are is installable and version is not passed" do
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ new_resource.package_name(%w{xNetworking xCertificate})
+ new_resource.version(nil)
+ expect(provider.candidate_version).to eql([nil, nil])
+ end
+
+ end
+
+ describe "#action_install" do
+ it "should install a single package" do
+ provider.load_current_resource
+ new_resource.package_name(["xCertificate"])
+ new_resource.version(nil)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "should install a single package when package name has space in between" do
+ provider.load_current_resource
+ new_resource.package_name(["7-Zip 16.02 (x64)"])
+ new_resource.version(nil)
+ allow(provider).to receive(:powershell_out).with("(Find-Package '7-Zip 16.02 (x64)' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_7zip_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name '7-Zip 16.02 (x64)' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_7zip_not_installed)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ expect(provider).to receive(:powershell_out).with("Install-Package '7-Zip 16.02 (x64)' -Force -ForceBootstrap -RequiredVersion 16.02", { :timeout => new_resource.timeout })
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ context "when changing the timeout to 3600" do
+ let(:timeout) { 3600 }
+ it "sets the timeout on shell_out commands" do
+ new_resource.timeout(timeout)
+ provider.load_current_resource
+ new_resource.package_name(["xCertificate"])
+ new_resource.version(nil)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+
+ it "should not install packages that are up-to-date" do
+ new_resource.package_name(["xCertificate"])
+ new_resource.version(nil)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ provider.load_current_resource
+ expect(provider).not_to receive(:install_package)
+ provider.run_action(:install)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "should not install packages that are up-to-date" do
+ new_resource.package_name(["xNetworking"])
+ new_resource.version(["2.11.0.0"])
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available_2_11_0_0)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ provider.load_current_resource
+ expect(provider).not_to receive(:install_package)
+ provider.run_action(:install)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "should handle complicated cases when the name/version array is pruned" do
+ # implicitly test that we correctly pick up new_resource.version[1] instead of
+ # new_version.resource[0]
+ new_resource.package_name(%w{xCertificate xNetworking})
+ new_resource.version([nil, "2.11.0.0"])
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available_2_11_0_0)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.11.0.0", { :timeout => new_resource.timeout })
+ provider.load_current_resource
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "should split up commands when given two packages, one with a version pin" do
+ new_resource.package_name(%w{xCertificate xNetworking})
+ new_resource.version(["2.1.0.0", nil])
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.12.0.0", { :timeout => new_resource.timeout })
+
+ provider.load_current_resource
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "should do multipackage installs when given two packages without constraints" do
+ new_resource.package_name(%w{xCertificate xNetworking})
+ new_resource.version(nil)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ expect(provider).to receive(:powershell_out).with("Install-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
+ expect(provider).to receive(:powershell_out).with("Install-Package 'xNetworking' -Force -ForceBootstrap -RequiredVersion 2.12.0.0", { :timeout => new_resource.timeout })
+ provider.load_current_resource
+ provider.run_action(:install)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+
+ describe "#action_remove" do
+ it "does nothing when the package is already removed" do
+ provider.load_current_resource
+ new_resource.package_name(["xCertificate"])
+ new_resource.version(["2.1.0.0"])
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ expect(provider).not_to receive(:remove_package)
+ provider.run_action(:remove)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "does nothing when all the packages are already removed" do
+ new_resource.package_name(%w{xCertificate xNetworking})
+ new_resource.version(nil)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ provider.load_current_resource
+ expect(provider).not_to receive(:remove_package)
+ provider.run_action(:remove)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "removes a package when version is specified" do
+ new_resource.package_name(["xCertificate"])
+ new_resource.version(["2.1.0.0"])
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ provider.load_current_resource
+ expect(provider).to receive(:powershell_out).with("Uninstall-Package 'xCertificate' -Force -ForceBootstrap -RequiredVersion 2.1.0.0", { :timeout => new_resource.timeout })
+ provider.run_action(:remove)
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "removes a package when version is not specified" do
+ new_resource.package_name(["xCertificate"])
+ new_resource.version(nil)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
+ provider.load_current_resource
+ expect(provider).to receive(:powershell_out).with("(Uninstall-Package 'xCertificate' -Force -ForceBootstrap | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ provider.run_action(:remove)
+ expect(new_resource).to be_updated_by_last_action
+ end
+ end
+end
diff --git a/spec/unit/provider/package/rpm_spec.rb b/spec/unit/provider/package/rpm_spec.rb
index 1d179edf76..3730878026 100644
--- a/spec/unit/provider/package/rpm_spec.rb
+++ b/spec/unit/provider/package/rpm_spec.rb
@@ -41,7 +41,7 @@ describe Chef::Provider::Package::Rpm do
let(:rpm_q_status) { instance_double("Mixlib::ShellOut", exitstatus: rpm_q_exitstatus, stdout: rpm_q_stdout) }
before(:each) do
- allow(::File).to receive(:exists?).with("PLEASE STUB File.exists? EXACTLY").and_return(true)
+ allow(::File).to receive(:exist?).with("PLEASE STUB File.exists? EXACTLY").and_return(true)
# Ensure all shell out usage is stubbed with exact arguments
allow(provider).to receive(:shell_out!).with("PLEASE STUB YOUR SHELLOUT CALLS").and_return(nil)
@@ -61,7 +61,7 @@ describe Chef::Provider::Package::Rpm do
context "when the source is a file that doesn't exist" do
it "should raise an exception when attempting any action" do
- allow(::File).to receive(:exists?).with(package_source).and_return(false)
+ allow(::File).to receive(:exist?).with(package_source).and_return(false)
expect { provider.run_action(:any) }.to raise_error(Chef::Exceptions::Package)
end
end
@@ -71,7 +71,7 @@ describe Chef::Provider::Package::Rpm do
let(:package_source) { "foobar://example.com/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm" }
it "should raise an exception if an uri formed source is non-supported scheme" do
- allow(::File).to receive(:exists?).with(package_source).and_return(false)
+ allow(::File).to receive(:exist?).with(package_source).and_return(false)
# verify let bindings are as we expect
expect(new_resource.source).to eq("foobar://example.com/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm")
@@ -86,18 +86,18 @@ describe Chef::Provider::Package::Rpm do
before do
expect(provider).to receive(:shell_out!).
- with("rpm -qp --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{package_source}", timeout: 900).
+ with("rpm", "-qp", "--queryformat", "%{NAME} %{VERSION}-%{RELEASE}\n", package_source, timeout: 900).
and_return(rpm_qp_status)
expect(provider).to receive(:shell_out).
- with("rpm -q --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' #{package_name}", timeout: 900).
+ with("rpm", "-q", "--queryformat", "%{NAME} %{VERSION}-%{RELEASE}\n", package_name, timeout: 900).
and_return(rpm_q_status)
end
context "when rpm fails when querying package installed state" do
before do
- allow(::File).to receive(:exists?).with(package_source).and_return(true)
+ allow(::File).to receive(:exist?).with(package_source).and_return(true)
end
let(:rpm_qp_stdout) { "ImageMagick-c++ 6.5.4.7-7.el6_5" }
@@ -129,7 +129,7 @@ describe Chef::Provider::Package::Rpm do
context "when the source is a file system path" do
before do
- allow(::File).to receive(:exists?).with(package_source).and_return(true)
+ allow(::File).to receive(:exist?).with(package_source).and_return(true)
provider.action = action
@@ -151,7 +151,7 @@ describe Chef::Provider::Package::Rpm do
context "when at the desired version already" do
it "does nothing when the correct version is installed" do
- expect(provider).to_not receive(:shell_out!).with("rpm -i /tmp/imagemagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to_not receive(:shell_out!).with("rpm", "-i", "/tmp/imagemagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.action_install
end
@@ -162,7 +162,7 @@ describe Chef::Provider::Package::Rpm do
let(:rpm_q_stdout) { "imagemagick-c++ 0.5.4.7-7.el6_5" }
it "runs rpm -u with the package source to upgrade" do
- expect(provider).to receive(:shell_out!).with("rpm -U /tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "-U", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.action_install
end
end
@@ -178,7 +178,7 @@ describe Chef::Provider::Package::Rpm do
let(:rpm_q_stdout) { "imagemagick-c++ 21.4-19.el6_5" }
it "should run rpm -u --oldpackage with the package source to downgrade" do
- expect(provider).to receive(:shell_out!).with("rpm -U --oldpackage /tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "-U", "--oldpackage", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.action_install
end
@@ -192,7 +192,7 @@ describe Chef::Provider::Package::Rpm do
context "when at the desired version already" do
it "does nothing when the correct version is installed" do
- expect(provider).to_not receive(:shell_out!).with("rpm -i /tmp/imagemagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to_not receive(:shell_out!).with("rpm", "-i", "/tmp/imagemagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.action_upgrade
end
@@ -203,7 +203,7 @@ describe Chef::Provider::Package::Rpm do
let(:rpm_q_stdout) { "imagemagick-c++ 0.5.4.7-7.el6_5" }
it "runs rpm -u with the package source to upgrade" do
- expect(provider).to receive(:shell_out!).with("rpm -U /tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "-U", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.action_upgrade
end
end
@@ -219,7 +219,7 @@ describe Chef::Provider::Package::Rpm do
let(:rpm_q_stdout) { "imagemagick-c++ 21.4-19.el6_5" }
it "should run rpm -u --oldpackage with the package source to downgrade" do
- expect(provider).to receive(:shell_out!).with("rpm -U --oldpackage /tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "-U", "--oldpackage", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.action_upgrade
end
@@ -231,7 +231,7 @@ describe Chef::Provider::Package::Rpm do
let(:action) { :remove }
it "should remove the package" do
- expect(provider).to receive(:shell_out!).with("rpm -e ImageMagick-c++-6.5.4.7-7.el6_5", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "-e", "ImageMagick-c++-6.5.4.7-7.el6_5", timeout: 900)
provider.action_remove
end
end
@@ -276,7 +276,7 @@ describe Chef::Provider::Package::Rpm do
context "when the source is given as an URI" do
before(:each) do
- allow(::File).to receive(:exists?).with(package_source).and_return(false)
+ allow(::File).to receive(:exist?).with(package_source).and_return(false)
provider.action = action
@@ -322,7 +322,7 @@ describe Chef::Provider::Package::Rpm do
let(:action) { :install }
before do
- allow(File).to receive(:exists?).with(package_source).and_return(true)
+ allow(File).to receive(:exist?).with(package_source).and_return(true)
provider.action = action
@@ -357,7 +357,7 @@ describe Chef::Provider::Package::Rpm do
describe "action install" do
it "installs the package" do
- expect(provider).to receive(:shell_out!).with("rpm -i #{package_source}", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "-i", package_source, timeout: 900)
provider.action_install
end
@@ -365,7 +365,7 @@ describe Chef::Provider::Package::Rpm do
context "when custom resource options are given" do
it "installs with custom options specified in the resource" do
new_resource.options("--dbpath /var/lib/rpm")
- expect(provider).to receive(:shell_out!).with("rpm --dbpath /var/lib/rpm -i #{package_source}", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "--dbpath", "/var/lib/rpm", "-i", package_source, timeout: 900)
provider.action_install
end
end
@@ -376,7 +376,7 @@ describe Chef::Provider::Package::Rpm do
let(:action) { :upgrade }
it "installs the package" do
- expect(provider).to receive(:shell_out!).with("rpm -i #{package_source}", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "-i", package_source, timeout: 900)
provider.action_upgrade
end
@@ -387,7 +387,7 @@ describe Chef::Provider::Package::Rpm do
let(:action) { :remove }
it "should do nothing" do
- expect(provider).to_not receive(:shell_out!).with("rpm -e ImageMagick-c++-6.5.4.7-7.el6_5", timeout: 900)
+ expect(provider).to_not receive(:shell_out!).with("rpm", "-e", "ImageMagick-c++-6.5.4.7-7.el6_5", timeout: 900)
provider.action_remove
end
end
@@ -404,7 +404,7 @@ describe Chef::Provider::Package::Rpm do
# provider will call File.exists?. Because of the ordering in our
# let() bindings and such, we have to set the stub here and not in a
# before block.
- allow(::File).to receive(:exists?).with(package_source).and_return(true)
+ allow(::File).to receive(:exist?).with(package_source).and_return(true)
Chef::Resource::Package.new("/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm")
end
@@ -413,7 +413,7 @@ describe Chef::Provider::Package::Rpm do
it "should install from a path when the package is a path and the source is nil" do
expect(new_resource.source).to eq("/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm")
provider.current_resource = current_resource
- expect(provider).to receive(:shell_out!).with("rpm -i /tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "-i", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.install_package("/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", "6.5.4.7-7.el6_5")
end
@@ -421,7 +421,7 @@ describe Chef::Provider::Package::Rpm do
expect(new_resource.source).to eq("/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm")
current_resource.version("21.4-19.el5")
provider.current_resource = current_resource
- expect(provider).to receive(:shell_out!).with("rpm -U /tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
+ expect(provider).to receive(:shell_out!).with("rpm", "-U", "/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", timeout: 900)
provider.upgrade_package("/tmp/ImageMagick-c++-6.5.4.7-7.el6_5.x86_64.rpm", "6.5.4.7-7.el6_5")
end
end
diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb
index 548204df75..53c82f2f70 100644
--- a/spec/unit/provider/package/rubygems_spec.rb
+++ b/spec/unit/provider/package/rubygems_spec.rb
@@ -144,30 +144,30 @@ describe Chef::Provider::Package::Rubygems::CurrentGemEnvironment do
it "installs a gem with a hash of options for the dependency installer" do
dep_installer = Gem::DependencyInstaller.new
- expect(@gem_env).to receive(:dependency_installer).with(:install_dir => "/foo/bar").and_return(dep_installer)
+ expect(@gem_env).to receive(:dependency_installer).with(install_dir: "/foo/bar").and_return(dep_installer)
expect(@gem_env).to receive(:with_gem_sources).with("http://gems.example.com").and_yield
expect(dep_installer).to receive(:install).with(Gem::Dependency.new("rspec", ">= 0"))
- @gem_env.install(Gem::Dependency.new("rspec", ">= 0"), :install_dir => "/foo/bar", :sources => ["http://gems.example.com"])
+ @gem_env.install(Gem::Dependency.new("rspec", ">= 0"), install_dir: "/foo/bar", sources: ["http://gems.example.com"])
end
it "builds an uninstaller for a gem with options set to avoid requiring user input" do
# default options for uninstaller should be:
# :ignore => true, :executables => true
- expect(Gem::Uninstaller).to receive(:new).with("rspec", :ignore => true, :executables => true)
+ expect(Gem::Uninstaller).to receive(:new).with("rspec", ignore: true, executables: true)
@gem_env.uninstaller("rspec")
end
it "uninstalls all versions of a gem" do
uninstaller = double("gem uninstaller")
expect(uninstaller).to receive(:uninstall)
- expect(@gem_env).to receive(:uninstaller).with("rspec", :all => true).and_return(uninstaller)
+ expect(@gem_env).to receive(:uninstaller).with("rspec", all: true).and_return(uninstaller)
@gem_env.uninstall("rspec")
end
it "uninstalls a specific version of a gem" do
uninstaller = double("gem uninstaller")
expect(uninstaller).to receive(:uninstall)
- expect(@gem_env).to receive(:uninstaller).with("rspec", :version => "1.2.3").and_return(uninstaller)
+ expect(@gem_env).to receive(:uninstaller).with("rspec", version: "1.2.3").and_return(uninstaller)
@gem_env.uninstall("rspec", "1.2.3")
end
@@ -184,14 +184,14 @@ describe Chef::Provider::Package::Rubygems::AlternateGemEnvironment do
it "determines the gem paths from shelling out to gem env" do
gem_env_output = ["/path/to/gems", "/another/path/to/gems"].join(File::PATH_SEPARATOR)
- shell_out_result = OpenStruct.new(:stdout => gem_env_output)
+ shell_out_result = OpenStruct.new(stdout: gem_env_output)
expect(@gem_env).to receive(:shell_out!).with("/usr/weird/bin/gem env gempath").and_return(shell_out_result)
expect(@gem_env.gem_paths).to eq(["/path/to/gems", "/another/path/to/gems"])
end
it "caches the gempaths by gem_binary" do
gem_env_output = ["/path/to/gems", "/another/path/to/gems"].join(File::PATH_SEPARATOR)
- shell_out_result = OpenStruct.new(:stdout => gem_env_output)
+ shell_out_result = OpenStruct.new(stdout: gem_env_output)
expect(@gem_env).to receive(:shell_out!).with("/usr/weird/bin/gem env gempath").and_return(shell_out_result)
expected = ["/path/to/gems", "/another/path/to/gems"]
expect(@gem_env.gem_paths).to eq(["/path/to/gems", "/another/path/to/gems"])
@@ -271,7 +271,7 @@ RubyGems Environment:
- https://rubygems.org/
- http://gems.github.com/
JRUBY_GEM_ENV
- expect(@gem_env).to receive(:shell_out!).with("/usr/weird/bin/gem env").and_return(double("jruby_gem_env", :stdout => gem_env_out))
+ expect(@gem_env).to receive(:shell_out!).with("/usr/weird/bin/gem env").and_return(double("jruby_gem_env", stdout: gem_env_out))
expected = ["ruby", Gem::Platform.new("universal-java-1.6")]
expect(@gem_env.gem_platforms).to eq(expected)
# it should also cache the result
@@ -313,7 +313,7 @@ RubyGems Environment:
- https://rubygems.org/
- http://gems.github.com/
RBX_GEM_ENV
- expect(@gem_env).to receive(:shell_out!).with("/usr/weird/bin/gem env").and_return(double("rbx_gem_env", :stdout => gem_env_out))
+ expect(@gem_env).to receive(:shell_out!).with("/usr/weird/bin/gem env").and_return(double("rbx_gem_env", stdout: gem_env_out))
expect(@gem_env.gem_platforms).to eq(Gem.platforms)
expect(Chef::Provider::Package::Rubygems::AlternateGemEnvironment.platform_cache["/usr/weird/bin/gem"]).to eq(Gem.platforms)
end
@@ -351,7 +351,7 @@ describe Chef::Provider::Package::Rubygems do
new_resource
end
- let (:current_resource) { nil }
+ let(:current_resource) { nil }
let(:provider) do
run_context = Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new)
@@ -403,7 +403,7 @@ describe Chef::Provider::Package::Rubygems do
end
context "when you try to use a hash of install options" do
- let(:options) { { :fail => :burger } }
+ let(:options) { { fail: :burger } }
it "smites you" do
expect { provider }.to raise_error(ArgumentError)
@@ -437,9 +437,9 @@ describe Chef::Provider::Package::Rubygems do
it "searches for a gem binary when running on Omnibus on Unix" do
platform_mock :unix do
allow(ENV).to receive(:[]).with("PATH").and_return("/usr/bin:/usr/sbin:/opt/chef/embedded/bin")
- allow(File).to receive(:exists?).with("/usr/bin/gem").and_return(false)
- allow(File).to receive(:exists?).with("/usr/sbin/gem").and_return(true)
- allow(File).to receive(:exists?).with("/opt/chef/embedded/bin/gem").and_return(true) # should not get here
+ allow(File).to receive(:exist?).with("/usr/bin/gem").and_return(false)
+ allow(File).to receive(:exist?).with("/usr/sbin/gem").and_return(true)
+ allow(File).to receive(:exist?).with("/opt/chef/embedded/bin/gem").and_return(true) # should not get here
expect(provider.gem_env.gem_binary_location).to eq("/usr/sbin/gem")
end
end
@@ -450,11 +450,11 @@ describe Chef::Provider::Package::Rubygems do
it "searches for a gem binary when running on Omnibus on Windows" do
platform_mock :windows do
allow(ENV).to receive(:[]).with("PATH").and_return('C:\windows\system32;C:\windows;C:\Ruby186\bin;d:\opscode\chef\embedded\bin')
- allow(File).to receive(:exists?).with('C:\\windows\\system32\\gem').and_return(false)
- allow(File).to receive(:exists?).with('C:\\windows\\gem').and_return(false)
- allow(File).to receive(:exists?).with('C:\\Ruby186\\bin\\gem').and_return(true)
- allow(File).to receive(:exists?).with('d:\\opscode\\chef\\bin\\gem').and_return(false) # should not get here
- allow(File).to receive(:exists?).with('d:\\opscode\\chef\\embedded\\bin\\gem').and_return(false) # should not get here
+ allow(File).to receive(:exist?).with('C:\\windows\\system32\\gem').and_return(false)
+ allow(File).to receive(:exist?).with('C:\\windows\\gem').and_return(false)
+ allow(File).to receive(:exist?).with('C:\\Ruby186\\bin\\gem').and_return(true)
+ allow(File).to receive(:exist?).with('d:\\opscode\\chef\\bin\\gem').and_return(false) # should not get here
+ allow(File).to receive(:exist?).with('d:\\opscode\\chef\\embedded\\bin\\gem').and_return(false) # should not get here
expect(provider.gem_env.gem_binary_location).to eq('C:\Ruby186\bin\gem')
end
end
@@ -526,8 +526,8 @@ describe Chef::Provider::Package::Rubygems do
end
it "queries for available versions on upgrade" do
- expect(provider.gem_env).to receive(:candidate_version_from_remote).
- and_return(Gem::Version.new("9000.0.2"))
+ expect(provider.gem_env).to receive(:candidate_version_from_remote)
+ .and_return(Gem::Version.new("9000.0.2"))
expect(provider.gem_env).to receive(:install)
provider.run_action(:upgrade)
expect(new_resource).to be_updated_by_last_action
@@ -538,17 +538,17 @@ describe Chef::Provider::Package::Rubygems 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).
- and_return(Gem::Version.new(target_version))
+ 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" }
- let (:target_version) { ">= 0" }
+ let(:gem_name) { "chef-integration-test" }
+ let(:source) { CHEF_SPEC_DATA + "/gems/chef-integration-test-0.1.0.gem" }
+ let(:target_version) { ">= 0" }
it "parses the gem's specification" do
expect(provider.candidate_version).to eq("0.1.0")
@@ -570,14 +570,14 @@ describe Chef::Provider::Package::Rubygems 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)
+ allow(provider.gem_env).to receive(:candidate_version_from_remote)
+ .with(*args)
+ .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: nil)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -586,7 +586,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])
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -615,9 +615,9 @@ describe Chef::Provider::Package::Rubygems do
# this catches 'gem_package "foo"' when "./foo" is a file in the cwd, and instead of installing './foo' it fetches the remote gem
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(:exists?).and_return(true)
+ 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: nil)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -671,10 +671,10 @@ describe Chef::Provider::Package::Rubygems do
end
context "when options are given as a Hash" do
- let(:options) { { :install_dir => "/alt/install/location" } }
+ 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: nil }.merge(options))
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -684,7 +684,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: nil)
provider.run_action(:install)
expect(new_resource).to be_updated_by_last_action
end
@@ -780,7 +780,7 @@ describe Chef::Provider::Package::Rubygems do
end
context "when options are given as a Hash" do
- let(:options) { { :install_dir => "/alt/install/location" } }
+ let(:options) { { install_dir: "/alt/install/location" } }
it "uninstalls via the api" do
# pre-reqs for action_remove to actually remove the package:
diff --git a/spec/unit/provider/package/solaris_spec.rb b/spec/unit/provider/package/solaris_spec.rb
index 9cc8deeb2a..2fba2e3a08 100644
--- a/spec/unit/provider/package/solaris_spec.rb
+++ b/spec/unit/provider/package/solaris_spec.rb
@@ -27,7 +27,7 @@ describe Chef::Provider::Package::Solaris do
@new_resource.source("/tmp/bash.pkg")
@provider = Chef::Provider::Package::Solaris.new(@new_resource, @run_context)
- allow(::File).to receive(:exists?).and_return(true)
+ allow(::File).to receive(:exist?).and_return(true)
end
describe "assessing the current package status" do
@@ -63,7 +63,7 @@ PKGINFO
it "should raise an exception if a source is supplied but not found" do
allow(@provider).to receive(:shell_out).and_return(@status)
- allow(::File).to receive(:exists?).and_return(false)
+ allow(::File).to receive(:exist?).and_return(false)
@provider.load_current_resource
@provider.define_resource_requirements
expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Package)
@@ -71,8 +71,8 @@ PKGINFO
it "should get the source package version from pkginfo if provided" do
status = double(:stdout => @pkginfo, :exitstatus => 0)
- expect(@provider).to receive(:shell_out).with("pkginfo -l -d /tmp/bash.pkg SUNWbash", { timeout: 900 }).and_return(status)
- expect(@provider).to receive(:shell_out).with("pkginfo -l SUNWbash", { timeout: 900 }).and_return(@status)
+ expect(@provider).to receive(:shell_out).with("pkginfo", "-l", "-d", "/tmp/bash.pkg", "SUNWbash", { timeout: 900 }).and_return(status)
+ expect(@provider).to receive(:shell_out).with("pkginfo", "-l", "SUNWbash", { timeout: 900 }).and_return(@status)
@provider.load_current_resource
expect(@provider.current_resource.package_name).to eq("SUNWbash")
@@ -81,8 +81,8 @@ PKGINFO
it "should return the current version installed if found by pkginfo" do
status = double(:stdout => @pkginfo, :exitstatus => 0)
- expect(@provider).to receive(:shell_out).with("pkginfo -l -d /tmp/bash.pkg SUNWbash", { timeout: 900 }).and_return(@status)
- expect(@provider).to receive(:shell_out).with("pkginfo -l SUNWbash", { timeout: 900 }).and_return(status)
+ expect(@provider).to receive(:shell_out).with("pkginfo", "-l", "-d", "/tmp/bash.pkg", "SUNWbash", { timeout: 900 }).and_return(@status)
+ expect(@provider).to receive(:shell_out).with("pkginfo", "-l", "SUNWbash", { timeout: 900 }).and_return(status)
@provider.load_current_resource
expect(@provider.current_resource.version).to eq("11.10.0,REV=2005.01.08.05.16")
end
@@ -101,8 +101,8 @@ PKGINFO
end
it "should return a current resource with a nil version if the package is not found" do
- expect(@provider).to receive(:shell_out).with("pkginfo -l -d /tmp/bash.pkg SUNWbash", { timeout: 900 }).and_return(@status)
- expect(@provider).to receive(:shell_out).with("pkginfo -l SUNWbash", { timeout: 900 }).and_return(@status)
+ expect(@provider).to receive(:shell_out).with("pkginfo", "-l", "-d", "/tmp/bash.pkg", "SUNWbash", { timeout: 900 }).and_return(@status)
+ expect(@provider).to receive(:shell_out).with("pkginfo", "-l", "SUNWbash", { timeout: 900 }).and_return(@status)
@provider.load_current_resource
expect(@provider.current_resource.version).to be_nil
end
@@ -132,7 +132,7 @@ PKGINFO
describe "install and upgrade" do
it "should run pkgadd -n -d with the package source to install" do
- expect(@provider).to receive(:shell_out!).with("pkgadd -n -d /tmp/bash.pkg all", { timeout: 900 })
+ expect(@provider).to receive(:shell_out!).with("pkgadd", "-n", "-d", "/tmp/bash.pkg", "all", { timeout: 900 })
@provider.install_package("SUNWbash", "11.10.0,REV=2005.01.08.05.16")
end
@@ -140,26 +140,26 @@ PKGINFO
@new_resource = Chef::Resource::Package.new("/tmp/bash.pkg")
@provider = Chef::Provider::Package::Solaris.new(@new_resource, @run_context)
expect(@new_resource.source).to eq("/tmp/bash.pkg")
- expect(@provider).to receive(:shell_out!).with("pkgadd -n -d /tmp/bash.pkg all", { timeout: 900 })
+ expect(@provider).to receive(:shell_out!).with("pkgadd", "-n", "-d", "/tmp/bash.pkg", "all", { timeout: 900 })
@provider.install_package("/tmp/bash.pkg", "11.10.0,REV=2005.01.08.05.16")
end
it "should run pkgadd -n -a /tmp/myadmin -d with the package options -a /tmp/myadmin" do
- allow(@new_resource).to receive(:options).and_return("-a /tmp/myadmin")
- expect(@provider).to receive(:shell_out!).with("pkgadd -n -a /tmp/myadmin -d /tmp/bash.pkg all", { timeout: 900 })
+ @new_resource.options "-a /tmp/myadmin"
+ expect(@provider).to receive(:shell_out!).with("pkgadd", "-n", "-a", "/tmp/myadmin", "-d", "/tmp/bash.pkg", "all", { timeout: 900 })
@provider.install_package("SUNWbash", "11.10.0,REV=2005.01.08.05.16")
end
end
describe "remove" do
it "should run pkgrm -n to remove the package" do
- expect(@provider).to receive(:shell_out!).with("pkgrm -n SUNWbash", { timeout: 900 })
+ expect(@provider).to receive(:shell_out!).with("pkgrm", "-n", "SUNWbash", { timeout: 900 })
@provider.remove_package("SUNWbash", "11.10.0,REV=2005.01.08.05.16")
end
it "should run pkgrm -n -a /tmp/myadmin with options -a /tmp/myadmin" do
- allow(@new_resource).to receive(:options).and_return("-a /tmp/myadmin")
- expect(@provider).to receive(:shell_out!).with("pkgrm -n -a /tmp/myadmin SUNWbash", { timeout: 900 })
+ @new_resource.options "-a /tmp/myadmin"
+ expect(@provider).to receive(:shell_out!).with("pkgrm", "-n", "-a", "/tmp/myadmin", "SUNWbash", { timeout: 900 })
@provider.remove_package("SUNWbash", "11.10.0,REV=2005.01.08.05.16")
end
diff --git a/spec/unit/provider/package/windows_spec.rb b/spec/unit/provider/package/windows_spec.rb
index 53cbbc1da1..4b258a078f 100644
--- a/spec/unit/provider/package/windows_spec.rb
+++ b/spec/unit/provider/package/windows_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");
@@ -312,6 +312,7 @@ describe Chef::Provider::Package::Windows, :windows_only do
let(:resource_source) { "https://foo.bar/calculator.exe" }
it "downloads the http resource" do
+ allow(File).to receive(:exist?).with('c:\cache\calculator.exe').and_return(false)
expect(provider).to receive(:download_source_file)
provider.run_action(:install)
end
diff --git a/spec/unit/provider/package/yum_spec.rb b/spec/unit/provider/package/yum_spec.rb
index 23a28c6d37..e0a5f8c862 100644
--- a/spec/unit/provider/package/yum_spec.rb
+++ b/spec/unit/provider/package/yum_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");
@@ -40,6 +40,7 @@ describe Chef::Provider::Package::Yum do
)
allow(Chef::Provider::Package::Yum::YumCache).to receive(:instance).and_return(@yum_cache)
allow(@yum_cache).to receive(:yum_binary=).with("yum")
+ allow(::File).to receive(:exist?).with("/usr/bin/yum-deprecated").and_return(false)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@pid = double("PID")
end
@@ -80,12 +81,13 @@ describe Chef::Provider::Package::Yum do
@new_resource = Chef::Resource::YumPackage.new("testing.source")
@new_resource.source "chef-server-core-12.0.5-1.rpm"
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
- allow(File).to receive(:exists?).with(@new_resource.source).and_return(true)
+ allow(File).to receive(:exist?).with(@new_resource.source).and_return(true)
allow(@yum_cache).to receive(:installed_version).and_return(nil)
- shellout_double = double(:stdout => "chef-server-core 12.0.5-1")
+ shellout_double = double(:stdout => "chef-server-core 12.0.5-1 i386")
allow(@provider).to receive(:shell_out!).and_return(shellout_double)
@provider.load_current_resource
expect(@provider.candidate_version).to eql("12.0.5-1")
+ expect(@provider.new_resource.arch).to eql("i386")
end
end
@@ -94,14 +96,14 @@ describe Chef::Provider::Package::Yum do
expect(File).to receive(:exist?).with("/usr/bin/yum-deprecated").and_return(true)
expect(@yum_cache).to receive(:yum_binary=).with("yum-deprecated")
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
- expect(@provider.yum_binary).to eql("yum-deprecated")
+ expect(@provider.send(:yum_binary)).to eql("yum-deprecated")
end
it "when yum-deprecated does not exist" do
expect(File).to receive(:exist?).with("/usr/bin/yum-deprecated").and_return(false)
expect(@yum_cache).to receive(:yum_binary=).with("yum")
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
- expect(@provider.yum_binary).to eql("yum")
+ expect(@provider.send(:yum_binary)).to eql("yum")
end
it "when the yum_binary is set on the resource" do
@@ -109,23 +111,23 @@ describe Chef::Provider::Package::Yum do
expect(File).not_to receive(:exist?)
expect(@yum_cache).to receive(:yum_binary=).with("/usr/bin/yum-something")
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
- expect(@provider.yum_binary).to eql("/usr/bin/yum-something")
+ expect(@provider.send(:yum_binary)).to eql("/usr/bin/yum-something")
end
it "when the new_resource is a vanilla package class and yum-deprecated exists" do
- @new_resource = Chef::Resource::Package.new("cups")
+ @new_resource = Chef::Resource::YumPackage.new("cups")
expect(File).to receive(:exist?).with("/usr/bin/yum-deprecated").and_return(true)
expect(@yum_cache).to receive(:yum_binary=).with("yum-deprecated")
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
- expect(@provider.yum_binary).to eql("yum-deprecated")
+ expect(@provider.send(:yum_binary)).to eql("yum-deprecated")
end
it "when the new_resource is a vanilla package class and yum-deprecated does not exist" do
- @new_resource = Chef::Resource::Package.new("cups")
+ @new_resource = Chef::Resource::YumPackage.new("cups")
expect(File).to receive(:exist?).with("/usr/bin/yum-deprecated").and_return(false)
expect(@yum_cache).to receive(:yum_binary=).with("yum")
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
- expect(@provider.yum_binary).to eql("yum")
+ expect(@provider.send(:yum_binary)).to eql("yum")
end
end
@@ -155,19 +157,17 @@ describe Chef::Provider::Package::Yum do
@provider.load_current_resource
expect(@provider.new_resource.package_name).to eq("testing")
expect(@provider.new_resource.arch).to eq("noarch")
- expect(@provider.arch).to eq("noarch")
@new_resource = Chef::Resource::YumPackage.new("testing.more.noarch")
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@provider.load_current_resource
expect(@provider.new_resource.package_name).to eq("testing.more")
expect(@provider.new_resource.arch).to eq("noarch")
- expect(@provider.arch).to eq("noarch")
end
describe "when version constraint in package_name" do
it "should set package_version if no existing package_name is found and new_package_name is available" do
- @new_resource = Chef::Resource::Package.new("cups = 1.2.4-11.18.el5_2.3")
+ @new_resource = Chef::Resource::YumPackage.new("cups = 1.2.4-11.18.el5_2.3")
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
allow(@yum_cache).to receive(:package_available?) { |pkg| pkg == "cups" ? true : false }
allow(@yum_cache).to receive(:packages_from_require) do |pkg|
@@ -211,14 +211,12 @@ describe Chef::Provider::Package::Yum do
@provider.load_current_resource
expect(@provider.new_resource.package_name).to eq("testing.beta3")
expect(@provider.new_resource.arch).to eq(nil)
- expect(@provider.arch).to eq(nil)
@new_resource = Chef::Resource::YumPackage.new("testing.beta3.more")
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@provider.load_current_resource
expect(@provider.new_resource.package_name).to eq("testing.beta3.more")
expect(@provider.new_resource.arch).to eq(nil)
- expect(@provider.arch).to eq(nil)
end
it "should not set the arch when no existing package_name or new_package_name+new_arch is found" do
@@ -242,14 +240,12 @@ describe Chef::Provider::Package::Yum do
@provider.load_current_resource
expect(@provider.new_resource.package_name).to eq("testing.beta3")
expect(@provider.new_resource.arch).to eq(nil)
- expect(@provider.arch).to eq(nil)
@new_resource = Chef::Resource::YumPackage.new("testing.beta3.more")
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@provider.load_current_resource
expect(@provider.new_resource.package_name).to eq("testing.beta3.more")
expect(@provider.new_resource.arch).to eq(nil)
- expect(@provider.arch).to eq(nil)
end
it "should ensure it doesn't clobber an existing arch if passed" do
@@ -539,8 +535,8 @@ describe Chef::Provider::Package::Yum do
end
it "should run yum localinstall if given a path to an rpm as the package" do
- @new_resource = Chef::Resource::Package.new("/tmp/emacs-21.4-20.el5.i386.rpm")
- allow(::File).to receive(:exists?).and_return(true)
+ @new_resource = Chef::Resource::YumPackage.new("/tmp/emacs-21.4-20.el5.i386.rpm")
+ allow(::File).to receive(:exist?).with("/tmp/emacs-21.4-20.el5.i386.rpm").and_return(true)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
expect(@new_resource.source).to eq("/tmp/emacs-21.4-20.el5.i386.rpm")
expect(@provider).to receive(:yum_command).with(
@@ -550,9 +546,9 @@ describe Chef::Provider::Package::Yum do
end
it "should run yum install with the package name, version and arch" do
- @provider.load_current_resource
allow(@new_resource).to receive(:arch).and_return("i386")
allow(Chef::Provider::Package::Yum::RPMUtils).to receive(:rpmvercmp).and_return(-1)
+ @provider.load_current_resource
expect(@provider).to receive(:yum_command).with(
"-d0 -e0 -y install cups-1.2.4-11.19.el5.i386"
)
@@ -690,7 +686,7 @@ describe Chef::Provider::Package::Yum do
it "should run yum install if the package is not installed" do
@provider.load_current_resource
- @current_resource = Chef::Resource::Package.new("cups")
+ @current_resource = Chef::Resource::YumPackage.new("cups")
allow(@provider).to receive(:candidate_version).and_return("11")
allow(Chef::Provider::Package::Yum::RPMUtils).to receive(:rpmvercmp).and_return(-1)
expect(@provider).to receive(:yum_command).with(
@@ -721,18 +717,15 @@ describe Chef::Provider::Package::Yum do
# Test our little workaround, some crossover into Chef::Provider::Package territory
it "should call action_upgrade in the parent if the current resource version is nil" do
allow(@yum_cache).to receive(:installed_version).and_return(nil)
- @current_resource = Chef::Resource::Package.new("cups")
+ @current_resource = Chef::Resource::YumPackage.new("cups")
allow(@provider).to receive(:candidate_version).and_return("11")
- expect(@provider).to receive(:upgrade_package).with(
- "cups",
- "11"
- )
+ expect(@provider).to receive(:upgrade_package).with(["cups"], ["11"])
@provider.run_action(:upgrade)
end
it "should call action_upgrade in the parent if the candidate version is nil" do
@provider.load_current_resource
- @current_resource = Chef::Resource::Package.new("cups")
+ @current_resource = Chef::Resource::YumPackage.new("cups")
allow(@provider).to receive(:candidate_version).and_return(nil)
expect(@provider).not_to receive(:upgrade_package)
@provider.run_action(:upgrade)
@@ -740,19 +733,16 @@ describe Chef::Provider::Package::Yum do
it "should call action_upgrade in the parent if the candidate is newer" do
@provider.load_current_resource
- @current_resource = Chef::Resource::Package.new("cups")
+ @current_resource = Chef::Resource::YumPackage.new("cups")
allow(@provider).to receive(:candidate_version).and_return("11")
- expect(@provider).to receive(:upgrade_package).with(
- "cups",
- "11"
- )
+ expect(@provider).to receive(:upgrade_package).with(["cups"], ["11"])
@provider.run_action(:upgrade)
end
it "should not call action_upgrade in the parent if the candidate is older" do
allow(@yum_cache).to receive(:installed_version).and_return("12")
@provider.load_current_resource
- @current_resource = Chef::Resource::Package.new("cups")
+ @current_resource = Chef::Resource::YumPackage.new("cups")
allow(@provider).to receive(:candidate_version).and_return("11")
expect(@provider).not_to receive(:upgrade_package)
@provider.run_action(:upgrade)
@@ -811,7 +801,7 @@ describe Chef::Provider::Package::Yum do
"yum -d0 -e0 -y install emacs-1.0",
{ :timeout => Chef::Config[:yum_timeout] }
)
- @provider.yum_command("-d0 -e0 -y install emacs-1.0")
+ @provider.send(:yum_command, "-d0 -e0 -y install emacs-1.0")
end
it "should run yum once if it exits with a return code > 0 and no scriptlet failures" do
@@ -821,7 +811,7 @@ describe Chef::Provider::Package::Yum do
"yum -d0 -e0 -y install emacs-1.0",
{ :timeout => Chef::Config[:yum_timeout] }
)
- expect { @provider.yum_command("-d0 -e0 -y install emacs-1.0") }.to raise_error(Chef::Exceptions::Exec)
+ expect { @provider.send(:yum_command, "-d0 -e0 -y install emacs-1.0") }.to raise_error(Chef::Exceptions::Exec)
end
it "should run yum once if it exits with a return code of 1 and %pre scriptlet failures" do
@@ -833,7 +823,7 @@ describe Chef::Provider::Package::Yum do
{ :timeout => Chef::Config[:yum_timeout] }
)
# will still raise an exception, can't stub out the subsequent call
- expect { @provider.yum_command("-d0 -e0 -y install emacs-1.0") }.to raise_error(Chef::Exceptions::Exec)
+ expect { @provider.send(:yum_command, "-d0 -e0 -y install emacs-1.0") }.to raise_error(Chef::Exceptions::Exec)
end
it "should run yum twice if it exits with a return code of 1 and %post scriptlet failures" do
@@ -845,7 +835,7 @@ describe Chef::Provider::Package::Yum do
{ :timeout => Chef::Config[:yum_timeout] }
)
# will still raise an exception, can't stub out the subsequent call
- expect { @provider.yum_command("-d0 -e0 -y install emacs-1.0") }.to raise_error(Chef::Exceptions::Exec)
+ expect { @provider.send(:yum_command, "-d0 -e0 -y install emacs-1.0") }.to raise_error(Chef::Exceptions::Exec)
end
it "should pass the yum_binary to the command if its specified" do
@@ -858,7 +848,7 @@ describe Chef::Provider::Package::Yum do
"yum-deprecated -d0 -e0 -y install emacs-1.0",
{ :timeout => Chef::Config[:yum_timeout] }
)
- @provider.yum_command("-d0 -e0 -y install emacs-1.0")
+ @provider.send(:yum_command, "-d0 -e0 -y install emacs-1.0")
end
end
end
@@ -2132,7 +2122,7 @@ describe "Chef::Provider::Package::Yum - Multi" do
@node = Chef::Node.new
@events = Chef::EventDispatch::Dispatcher.new
@run_context = Chef::RunContext.new(@node, {}, @events)
- @new_resource = Chef::Resource::Package.new(%w{cups vim})
+ @new_resource = Chef::Resource::YumPackage.new(%w{cups vim})
@status = double("Status", :exitstatus => 0)
@yum_cache = double(
"Chef::Provider::Yum::YumCache",
@@ -2153,6 +2143,14 @@ describe "Chef::Provider::Package::Yum - Multi" do
@pid = double("PID")
end
+ describe "when evaluating the correctness of the resource" do
+ it "raises an error if the array lengths of package name, arch, and version do not match up" do
+ allow(@new_resource).to receive(:version).and_return(["1.1"])
+ allow(@new_resource).to receive(:arch).and_return(%w{x86_64 i386 i686})
+ expect { @provider.check_resource_semantics! }.to raise_error(Chef::Exceptions::InvalidResourceSpecification)
+ end
+ end
+
describe "when loading the current system state" do
it "should create a current resource with the name of the new_resource" do
@provider.load_current_resource
@@ -2194,7 +2192,7 @@ describe "Chef::Provider::Package::Yum - Multi" do
describe "when version constraint in package_name" do
it "should set package_version if no existing package_name is found and new_package_name is available" do
- @new_resource = Chef::Resource::Package.new(["cups = 1.2.4-11.18.el5_2.3", "emacs = 24.4"])
+ @new_resource = Chef::Resource::YumPackage.new(["cups = 1.2.4-11.18.el5_2.3", "emacs = 24.4"])
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
allow(@yum_cache).to receive(:package_available?) { |pkg| %w{cups emacs}.include?(pkg) ? true : false }
allow(@yum_cache).to receive(:candidate_version) do |pkg|
@@ -2212,7 +2210,8 @@ describe "Chef::Provider::Package::Yum - Multi" do
end
end
expect(Chef::Log).to receive(:debug).exactly(2).times.with(%r{matched 1 package,})
- expect(Chef::Log).to receive(:debug).exactly(1).times.with(%r{candidate version: \["1.2.4-11.18.el5_2.3", "24.4"\]})
+ expect(Chef::Log).to receive(:debug).exactly(1).times.with(%r{candidate version: 1.2.4-11.18.el5_2.3})
+ expect(Chef::Log).to receive(:debug).exactly(1).times.with(%r{candidate version: 24.4})
expect(Chef::Log).to receive(:debug).at_least(2).times.with(%r{checking yum info})
@provider.load_current_resource
expect(@provider.new_resource.package_name).to eq(%w{cups emacs})
@@ -2235,9 +2234,18 @@ describe "Chef::Provider::Package::Yum - Multi" do
@provider.install_package(%w{cups vim}, ["1.2.4-11.19.el5", "1.0"])
end
+ it "should not run yum install with nil package name" do
+ @provider.load_current_resource
+ allow(Chef::Provider::Package::Yum::RPMUtils).to receive(:rpmvercmp).and_return(-1)
+ expect(@provider).to receive(:yum_command).with(
+ "-d0 -e0 -y install cups-1.2.4-11.19.el5"
+ )
+ @provider.install_package(["cups", nil], ["1.2.4-11.19.el5", nil])
+ end
+
it "should run yum install with the package name, version and arch" do
@provider.load_current_resource
- allow(@new_resource).to receive(:arch).and_return("i386")
+ allow(@new_resource).to receive(:arch).and_return(%w{i386 i386})
allow(Chef::Provider::Package::Yum::RPMUtils).to receive(:rpmvercmp).and_return(-1)
expect(@provider).to receive(:yum_command).with(
"-d0 -e0 -y install cups-1.2.4-11.19.el5.i386 vim-1.0.i386"
@@ -2258,7 +2266,7 @@ describe "Chef::Provider::Package::Yum - Multi" do
end
it "should run yum install with the package name and version when name has arch" do
- @new_resource = Chef::Resource::Package.new(["cups.x86_64", "vim"])
+ @new_resource = Chef::Resource::YumPackage.new(["cups.x86_64", "vim"])
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
allow(Chef::Provider::Package::Yum::RPMUtils).to receive(:rpmvercmp).and_return(-1)
diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb
index d2800575bc..7e6f204b64 100644
--- a/spec/unit/provider/package/zypper_spec.rb
+++ b/spec/unit/provider/package/zypper_spec.rb
@@ -38,14 +38,14 @@ describe Chef::Provider::Package::Zypper do
allow(provider).to receive(:`).and_return("2.0")
end
- def shell_out_expectation(command, options = nil)
- options ||= { timeout: 900 }
- expect(provider).to receive(:shell_out).with(command, options)
+ def shell_out_expectation(*command, **options)
+ options[:timeout] ||= 900
+ expect(provider).to receive(:shell_out).with(*command, **options)
end
- def shell_out_expectation!(command, options = nil)
- options ||= { timeout: 900 }
- expect(provider).to receive(:shell_out!).with(command, options)
+ def shell_out_expectation!(*command, **options)
+ options[:timeout] ||= 900
+ expect(provider).to receive(:shell_out!).with(*command, **options)
end
describe "when loading the current package state" do
@@ -61,7 +61,7 @@ describe Chef::Provider::Package::Zypper do
it "should run zypper info with the package name" do
shell_out_expectation!(
- "zypper --non-interactive info #{new_resource.package_name}"
+ "zypper", "--non-interactive", "info", new_resource.package_name
).and_return(status)
provider.load_current_resource
end
@@ -113,14 +113,14 @@ describe Chef::Provider::Package::Zypper 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"
+ "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)
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks install " + "--auto-agree-with-licenses emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -129,7 +129,7 @@ describe Chef::Provider::Package::Zypper do
/All packages will be installed without gpg signature checks/
)
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks install " + "--auto-agree-with-licenses emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -139,14 +139,14 @@ describe Chef::Provider::Package::Zypper 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"
+ "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"
+ "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
@@ -155,13 +155,13 @@ describe Chef::Provider::Package::Zypper do
/All packages will be installed without gpg signature checks/
)
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks install " + "--auto-agree-with-licenses emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
it "should run zypper upgrade without gpg checks" do
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks install " + "--auto-agree-with-licenses emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
@@ -173,7 +173,7 @@ describe Chef::Provider::Package::Zypper 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"
+ "zypper", "--non-interactive", "remove", "emacs"
)
provider.remove_package(["emacs"], [nil])
end
@@ -183,14 +183,14 @@ describe Chef::Provider::Package::Zypper 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"
+ "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)
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
@@ -199,7 +199,7 @@ describe Chef::Provider::Package::Zypper do
/All packages will be installed without gpg signature checks/
)
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,14 +209,14 @@ 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", "--no-gpg-checks", "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)
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks remove --clean-deps emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "remove", "--clean-deps", "emacs=1.0"
)
provider.purge_package(["emacs"], ["1.0"])
end
@@ -225,7 +225,7 @@ describe Chef::Provider::Package::Zypper do
/All packages will be installed without gpg signature checks/
)
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks remove --clean-deps emacs=1.0"
+ "zypper", "--non-interactive", "--no-gpg-checks", "remove", "--clean-deps", "emacs=1.0"
)
provider.purge_package(["emacs"], ["1.0"])
end
@@ -235,14 +235,14 @@ describe Chef::Provider::Package::Zypper 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"
+ "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"
+ "zypper", "--non-interactive", "--no-gpg-checks", "addlock", "emacs"
)
provider.lock_package(["emacs"], [nil])
end
@@ -251,13 +251,13 @@ describe Chef::Provider::Package::Zypper do
/All packages will be installed without gpg signature checks/
)
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks addlock emacs"
+ "zypper", "--non-interactive", "--no-gpg-checks", "addlock", "emacs"
)
provider.lock_package(["emacs"], [nil])
end
it "should run zypper addlock without gpg checks" do
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks addlock emacs"
+ "zypper", "--non-interactive", "--no-gpg-checks", "addlock", "emacs"
)
provider.lock_package(["emacs"], [nil])
end
@@ -267,14 +267,14 @@ describe Chef::Provider::Package::Zypper 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"
+ "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"
+ "zypper", "--non-interactive", "--no-gpg-checks", "removelock", "emacs"
)
provider.unlock_package(["emacs"], [nil])
end
@@ -283,13 +283,13 @@ describe Chef::Provider::Package::Zypper do
/All packages will be installed without gpg signature checks/
)
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks removelock emacs"
+ "zypper", "--non-interactive", "--no-gpg-checks", "removelock", "emacs"
)
provider.unlock_package(["emacs"], [nil])
end
it "should run zypper removelock without gpg checks" do
shell_out_expectation!(
- "zypper --non-interactive --no-gpg-checks removelock emacs"
+ "zypper", "--non-interactive", "--no-gpg-checks", "removelock", "emacs"
)
provider.unlock_package(["emacs"], [nil])
end
@@ -303,7 +303,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", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "-y", "emacs"
)
provider.install_package(["emacs"], ["1.0"])
end
@@ -312,7 +312,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", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "-y", "emacs"
)
provider.upgrade_package(["emacs"], ["1.0"])
end
@@ -321,7 +321,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", "--no-gpg-checks", "remove", "-y", "emacs"
)
provider.remove_package(["emacs"], ["1.0"])
end
@@ -332,7 +332,7 @@ describe Chef::Provider::Package::Zypper do
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", "--no-gpg-checks", "install", "--auto-agree-with-licenses", "emacs=1.0", "vim=2.0"
)
provider.install_package(%w{emacs vim}, ["1.0", "2.0"])
end
@@ -340,7 +340,7 @@ describe Chef::Provider::Package::Zypper do
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", "--no-gpg-checks", "remove", "emacs=1.0", "vim=2.0"
)
provider.remove_package(%w{emacs vim}, ["1.0", "2.0"])
end
diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb
index 27d28c698c..122e58efb7 100644
--- a/spec/unit/provider/package_spec.rb
+++ b/spec/unit/provider/package_spec.rb
@@ -517,6 +517,10 @@ describe "Subclass with use_multipackage_api" do
end
context "#a_to_s utility for subclasses" do
+ before(:each) do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ end
+
it "converts varargs of strings to a single string" do
expect(provider.send(:a_to_s, "a", nil, "b", "", "c", " ", "d e", "f-g")).to eq("a b c d e f-g")
end
@@ -906,6 +910,10 @@ describe "Chef::Provider::Package - Multi" do
end
describe "shell_out helpers" do
+ before(:each) do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ end
+
[ :shell_out_with_timeout, :shell_out_with_timeout! ].each do |method|
stubbed_method = method == :shell_out_with_timeout! ? :shell_out! : :shell_out
[ %w{command arg1 arg2}, "command arg1 arg2" ].each do |command|
diff --git a/spec/unit/provider/remote_file/sftp_spec.rb b/spec/unit/provider/remote_file/sftp_spec.rb
index 7be507dc89..ddab1605f0 100644
--- a/spec/unit/provider/remote_file/sftp_spec.rb
+++ b/spec/unit/provider/remote_file/sftp_spec.rb
@@ -117,7 +117,7 @@ describe Chef::Provider::RemoteFile::SFTP do
end
context "and the URI specifies an alternate port" do
- let(:uri) { URI.parse("ftp://conan:cthu1hu@opscode.com:8021/seattle.txt") }
+ let(:uri) { URI.parse("sftp://conan:cthu1hu@opscode.com:8021/seattle.txt") }
it "should connect on an alternate port when one is provided" do
expect(Net::SFTP).to receive(:start).with("opscode.com:8021", "conan", :password => "cthu1hu")
@@ -127,10 +127,10 @@ describe Chef::Provider::RemoteFile::SFTP do
end
context "and the uri specifies a nested path" do
- let(:uri) { URI.parse("ftp://conan:cthu1hu@opscode.com/the/whole/path/seattle.txt") }
+ let(:uri) { URI.parse("sftp://conan:cthu1hu@opscode.com/the/whole/path/seattle.txt") }
it "should fetch the file from the correct path" do
- expect(sftp).to receive(:download!).with("the/whole/path/seattle.txt", "/tmp/somedir/remote-file-sftp-backend-spec-test")
+ expect(sftp).to receive(:download!).with("/the/whole/path/seattle.txt", "/tmp/somedir/remote-file-sftp-backend-spec-test")
fetcher.fetch
end
end
diff --git a/spec/unit/provider/route_spec.rb b/spec/unit/provider/route_spec.rb
index 2e3f6e4e9e..03d1ad2477 100644
--- a/spec/unit/provider/route_spec.rb
+++ b/spec/unit/provider/route_spec.rb
@@ -51,7 +51,7 @@ describe Chef::Provider::Route do
context "on linux" do
before do
@node.automatic_attrs[:os] = "linux"
- routing_table = "Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT\n" +
+ routing_table = "Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT\n" \
"eth0 0064A8C0 0984A8C0 0003 0 0 0 00FFFFFF 0 0 0\n"
route_file = StringIO.new(routing_table)
allow(File).to receive(:open).with("/proc/net/route", "r").and_return(route_file)
@@ -91,16 +91,16 @@ describe Chef::Provider::Route do
describe Chef::Provider::Route, "action_add" do
it "should add the route if it does not exist" do
- allow(@provider).to receive(:run_command).and_return(true)
+ allow(@provider).to receive(:shell_out!)
allow(@current_resource).to receive(:gateway).and_return(nil)
- expect(@provider).to receive(:generate_command).once.with(:add)
+ expect(@provider).to receive(:generate_command).with(:add).and_return(["command"])
expect(@provider).to receive(:generate_config)
@provider.run_action(:add)
expect(@new_resource).to be_updated
end
it "should not add the route if it exists" do
- allow(@provider).to receive(:run_command).and_return(true)
+ allow(@provider).to receive(:shell_out!)
allow(@provider).to receive(:is_running).and_return(true)
expect(@provider).not_to receive(:generate_command).with(:add)
expect(@provider).to receive(:generate_config)
@@ -115,7 +115,7 @@ describe Chef::Provider::Route do
expect(File).to receive(:new).and_return(route_file)
@resource_add = Chef::Resource::Route.new("192.168.1.0/24 via 192.168.0.1")
@run_context.resource_collection << @resource_add
- allow(@provider).to receive(:run_command).and_return(true)
+ allow(@provider).to receive(:shell_out!).and_return(true)
@resource_add.action(:add)
@provider.run_action(:add)
@@ -126,8 +126,8 @@ describe Chef::Provider::Route do
describe Chef::Provider::Route, "action_delete" do
it "should delete the route if it exists" do
- allow(@provider).to receive(:run_command).and_return(true)
- expect(@provider).to receive(:generate_command).once.with(:delete)
+ allow(@provider).to receive(:shell_out!).and_return(true)
+ expect(@provider).to receive(:generate_command).with(:delete).and_return(["command"])
allow(@provider).to receive(:is_running).and_return(true)
@provider.run_action(:delete)
expect(@new_resource).to be_updated
@@ -135,7 +135,7 @@ describe Chef::Provider::Route do
it "should not delete the route if it does not exist" do
allow(@current_resource).to receive(:gateway).and_return(nil)
- allow(@provider).to receive(:run_command).and_return(true)
+ allow(@provider).to receive(:shell_out!).and_return(true)
expect(@provider).not_to receive(:generate_command).with(:add)
@provider.run_action(:delete)
expect(@new_resource).not_to be_updated
@@ -145,61 +145,61 @@ describe Chef::Provider::Route do
describe Chef::Provider::Route, "generate_command for action_add" do
it "should include a netmask when a one is specified" do
allow(@new_resource).to receive(:netmask).and_return("255.255.0.0")
- expect(@provider.generate_command(:add)).to match(/\/\d{1,2}\s/)
+ expect(@provider.generate_command(:add).join(" ")).to match(/\/\d{1,2}/)
end
it "should not include a netmask when a one is specified" do
allow(@new_resource).to receive(:netmask).and_return(nil)
- expect(@provider.generate_command(:add)).not_to match(/\/\d{1,2}\s/)
+ expect(@provider.generate_command(:add).join(" ")).not_to match(/\/\d{1,2}/)
end
it "should include ' via $gateway ' when a gateway is specified" do
- expect(@provider.generate_command(:add)).to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}\s/)
+ expect(@provider.generate_command(:add).join(" ")).to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}/)
end
it "should not include ' via $gateway ' when a gateway is not specified" do
allow(@new_resource).to receive(:gateway).and_return(nil)
- expect(@provider.generate_command(:add)).not_to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}\s/)
+ expect(@provider.generate_command(:add).join(" ")).not_to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}/)
end
end
describe Chef::Provider::Route, "generate_command for action_delete" do
it "should include a netmask when a one is specified" do
allow(@new_resource).to receive(:netmask).and_return("255.255.0.0")
- expect(@provider.generate_command(:delete)).to match(/\/\d{1,2}\s/)
+ expect(@provider.generate_command(:delete).join(" ")).to match(/\/\d{1,2}/)
end
it "should not include a netmask when a one is specified" do
allow(@new_resource).to receive(:netmask).and_return(nil)
- expect(@provider.generate_command(:delete)).not_to match(/\/\d{1,2}\s/)
+ expect(@provider.generate_command(:delete).join(" ")).not_to match(/\/\d{1,2}/)
end
it "should include ' via $gateway ' when a gateway is specified" do
- expect(@provider.generate_command(:delete)).to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}\s/)
+ expect(@provider.generate_command(:delete).join(" ")).to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}/)
end
it "should not include ' via $gateway ' when a gateway is not specified" do
allow(@new_resource).to receive(:gateway).and_return(nil)
- expect(@provider.generate_command(:delete)).not_to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}\s/)
+ expect(@provider.generate_command(:delete).join(" ")).not_to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}/)
end
end
describe Chef::Provider::Route, "config_file_contents for action_add" do
it "should include a netmask when a one is specified" do
allow(@new_resource).to receive(:netmask).and_return("255.255.0.0")
- expect(@provider.config_file_contents(:add, { :target => @new_resource.target, :netmask => @new_resource.netmask })).to match(/\/\d{1,2}.*\n$/)
+ expect(@provider.config_file_contents(:add, target: @new_resource.target, netmask: @new_resource.netmask)).to match(/\/\d{1,2}.*\n$/)
end
it "should not include a netmask when a one is specified" do
- expect(@provider.config_file_contents(:add, { :target => @new_resource.target })).not_to match(/\/\d{1,2}.*\n$/)
+ expect(@provider.config_file_contents(:add, target: @new_resource.target)).not_to match(/\/\d{1,2}.*\n$/)
end
it "should include ' via $gateway ' when a gateway is specified" do
- expect(@provider.config_file_contents(:add, { :target => @new_resource.target, :gateway => @new_resource.gateway })).to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}\n/)
+ expect(@provider.config_file_contents(:add, target: @new_resource.target, gateway: @new_resource.gateway)).to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}\n/)
end
it "should not include ' via $gateway ' when a gateway is not specified" do
- expect(@provider.generate_command(:add)).not_to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}\n/)
+ expect(@provider.generate_command(:add).join(" ")).not_to match(/\svia\s#{Regexp.escape(@new_resource.gateway.to_s)}\n/)
end
end
@@ -216,7 +216,7 @@ describe Chef::Provider::Route do
route_file = StringIO.new
expect(File).to receive(:new).with("/etc/sysconfig/network-scripts/route-eth0", "w").and_return(route_file)
- #Chef::Log.should_receive(:debug).with("route[10.0.0.10] writing route.eth0\n10.0.0.10 via 10.0.0.9\n")
+ # Chef::Log.should_receive(:debug).with("route[10.0.0.10] writing route.eth0\n10.0.0.10 via 10.0.0.9\n")
@run_context.resource_collection << @new_resource
@provider.generate_config
end
@@ -230,13 +230,19 @@ describe Chef::Provider::Route do
@run_context.resource_collection << Chef::Resource::Route.new("192.168.1.0/24 via 192.168.0.1")
@run_context.resource_collection << Chef::Resource::Route.new("192.168.2.0/24 via 192.168.0.1")
@run_context.resource_collection << Chef::Resource::Route.new("192.168.3.0/24 via 192.168.0.1")
+ @run_context.resource_collection << Chef::Resource::Route.new("Complex Route").tap do |r|
+ r.target "192.168.4.0"
+ r.gateway "192.168.0.1"
+ r.netmask "255.255.255.0"
+ end
@provider.action = :add
@provider.generate_config
- expect(route_file.string.split("\n").size).to eq(3)
+ expect(route_file.string.split("\n").size).to eq(4)
expect(route_file.string).to match(/^192\.168\.1\.0\/24 via 192\.168\.0\.1$/)
expect(route_file.string).to match(/^192\.168\.2\.0\/24 via 192\.168\.0\.1$/)
expect(route_file.string).to match(/^192\.168\.3\.0\/24 via 192\.168\.0\.1$/)
+ expect(route_file.string).to match(/^192\.168\.4\.0\/24 via 192\.168\.0\.1$/)
end
end
end
diff --git a/spec/unit/provider/script_spec.rb b/spec/unit/provider/script_spec.rb
index 7e34a8f083..2f024c4c29 100644
--- a/spec/unit/provider/script_spec.rb
+++ b/spec/unit/provider/script_spec.rb
@@ -56,12 +56,55 @@ describe Chef::Provider::Script, "action_run" do
end
end
- context "#set_owner_and_group" do
- it "sets the owner and group for the script file" do
- new_resource.user "toor"
- new_resource.group "wheel"
- expect(FileUtils).to receive(:chown).with("toor", "wheel", tempfile.path)
- provider.set_owner_and_group
+ context "when configuring the script file's security" do
+ context "when not running on Windows" do
+ before do
+ allow(::Chef::Platform).to receive(:windows?).and_return(false)
+ end
+ context "#set_owner_and_group" do
+ it "sets the owner and group for the script file" do
+ new_resource.user "toor"
+ new_resource.group "wheel"
+ expect(FileUtils).to receive(:chown).with("toor", "wheel", tempfile.path)
+ provider.set_owner_and_group
+ end
+ end
+ end
+
+ context "when running on Windows" do
+ before do
+ allow(::Chef::Platform).to receive(:windows?).and_return(true)
+ expect(new_resource.user).to eq(nil)
+ stub_const("Chef::ReservedNames::Win32::API::Security::GENERIC_READ", 1)
+ stub_const("Chef::ReservedNames::Win32::API::Security::GENERIC_EXECUTE", 4)
+ stub_const("Chef::ReservedNames::Win32::Security", Class.new)
+ stub_const("Chef::ReservedNames::Win32::Security::SecurableObject", Class.new)
+ stub_const("Chef::ReservedNames::Win32::Security::SID", Class.new)
+ stub_const("Chef::ReservedNames::Win32::Security::ACE", Class.new)
+ stub_const("Chef::ReservedNames::Win32::Security::ACL", Class.new)
+ end
+
+ context "when an alternate user is not specified" do
+ it "does not attempt to set the script file's security descriptor" do
+ expect(provider).to receive(:grant_alternate_user_read_access)
+ expect(Chef::ReservedNames::Win32::Security::SecurableObject).not_to receive(:new)
+ provider.set_owner_and_group
+ end
+ end
+
+ context "when an alternate user is specified" do
+ let(:security_descriptor) { instance_double("Chef::ReservedNames::Win32::Security::SecurityDescriptor", :dacl => []) }
+ let(:securable_object) { instance_double("Chef::ReservedNames::Win32::Security::SecurableObject", :security_descriptor => security_descriptor, :dacl= => nil) }
+ it "sets the script file's security descriptor" do
+ new_resource.user("toor")
+ expect(Chef::ReservedNames::Win32::Security::SecurableObject).to receive(:new).and_return(securable_object)
+ expect(Chef::ReservedNames::Win32::Security::SID).to receive(:from_account).and_return(nil)
+ expect(Chef::ReservedNames::Win32::Security::ACE).to receive(:access_allowed).and_return(nil)
+ expect(Chef::ReservedNames::Win32::Security::ACL).to receive(:create).and_return(nil)
+ expect(securable_object).to receive(:dacl=)
+ provider.set_owner_and_group
+ end
+ end
end
end
diff --git a/spec/unit/provider/service/macosx_spec.rb b/spec/unit/provider/service/macosx_spec.rb
index 12f97431ba..c9dd629187 100644
--- a/spec/unit/provider/service/macosx_spec.rb
+++ b/spec/unit/provider/service/macosx_spec.rb
@@ -322,7 +322,7 @@ SVC_LIST
it "stops and then starts service" do
expect(provider).to receive(:unload_service)
- expect(provider).to receive(:load_service);
+ expect(provider).to receive(:load_service)
provider.restart_service
end
diff --git a/spec/unit/provider/subversion_spec.rb b/spec/unit/provider/subversion_spec.rb
index ac2a8dd754..a4ab4ae42c 100644
--- a/spec/unit/provider/subversion_spec.rb
+++ b/spec/unit/provider/subversion_spec.rb
@@ -32,6 +32,15 @@ describe Chef::Provider::Subversion do
@events = Chef::EventDispatch::Dispatcher.new
@run_context = Chef::RunContext.new(@node, {}, @events)
@provider = Chef::Provider::Subversion.new(@resource, @run_context)
+ @original_env = ENV.to_hash
+ # Generated command lines would include any environmental proxies
+ ENV.delete("http_proxy")
+ ENV.delete("https_proxy")
+ end
+
+ after do
+ ENV.clear
+ ENV.update(@original_env)
end
it "converts resource attributes to options for run_command and popen4" do
diff --git a/spec/unit/provider/user/dscl_spec.rb b/spec/unit/provider/user/dscl_spec.rb
index 7b8be02f3a..f59709e717 100644
--- a/spec/unit/provider/user/dscl_spec.rb
+++ b/spec/unit/provider/user/dscl_spec.rb
@@ -116,38 +116,38 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
describe "when shelling out to dscl" do
it "should run dscl with the supplied cmd /Path args" do
shell_return = shellcmdresult.new("stdout", "err", 0)
- expect(provider).to receive(:shell_out).with("dscl . -cmd /Path args").and_return(shell_return)
- expect(provider.run_dscl("cmd /Path args")).to eq("stdout")
+ expect(provider).to receive(:shell_out).with("dscl", ".", "-cmd", "/Path", "args").and_return(shell_return)
+ expect(provider.run_dscl("cmd", "/Path", "args")).to eq("stdout")
end
it "returns an empty string from delete commands" do
shell_return = shellcmdresult.new("out", "err", 23)
- expect(provider).to receive(:shell_out).with("dscl . -delete /Path args").and_return(shell_return)
- expect(provider.run_dscl("delete /Path args")).to eq("")
+ expect(provider).to receive(:shell_out).with("dscl", ".", "-delete", "/Path", "args").and_return(shell_return)
+ expect(provider.run_dscl("delete", "/Path", "args")).to eq("")
end
it "should raise an exception for any other command" do
shell_return = shellcmdresult.new("out", "err", 23)
- expect(provider).to receive(:shell_out).with("dscl . -cmd /Path arguments").and_return(shell_return)
- expect { provider.run_dscl("cmd /Path arguments") }.to raise_error(Chef::Exceptions::DsclCommandFailed)
+ expect(provider).to receive(:shell_out).with("dscl", ".", "-cmd", "/Path", "arguments").and_return(shell_return)
+ expect { provider.run_dscl("cmd", "/Path", "arguments") }.to raise_error(Chef::Exceptions::DsclCommandFailed)
end
it "raises an exception when dscl reports 'no such key'" do
shell_return = shellcmdresult.new("No such key: ", "err", 23)
- expect(provider).to receive(:shell_out).with("dscl . -cmd /Path args").and_return(shell_return)
- expect { provider.run_dscl("cmd /Path args") }.to raise_error(Chef::Exceptions::DsclCommandFailed)
+ expect(provider).to receive(:shell_out).with("dscl", ".", "-cmd", "/Path", "args").and_return(shell_return)
+ expect { provider.run_dscl("cmd", "/Path", "args") }.to raise_error(Chef::Exceptions::DsclCommandFailed)
end
it "raises an exception when dscl reports 'eDSRecordNotFound'" do
shell_return = shellcmdresult.new("<dscl_cmd> DS Error: -14136 (eDSRecordNotFound)", "err", -14136)
- expect(provider).to receive(:shell_out).with("dscl . -cmd /Path args").and_return(shell_return)
- expect { provider.run_dscl("cmd /Path args") }.to raise_error(Chef::Exceptions::DsclCommandFailed)
+ expect(provider).to receive(:shell_out).with("dscl", ".", "-cmd", "/Path", "args").and_return(shell_return)
+ expect { provider.run_dscl("cmd", "/Path", "args") }.to raise_error(Chef::Exceptions::DsclCommandFailed)
end
end
describe "get_free_uid" do
before do
- expect(provider).to receive(:run_dscl).with("list /Users uid").and_return("\nwheel 200\nstaff 201\nbrahms 500\nchopin 501\n")
+ expect(provider).to receive(:run_dscl).with("list", "/Users", "uid").and_return("\nwheel 200\nstaff 201\nbrahms 500\nchopin 501\n")
end
describe "when resource is configured as system" do
@@ -177,7 +177,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
describe "when called with a user id" do
before do
- expect(provider).to receive(:run_dscl).with("list /Users uid").and_return("\naj 500\n")
+ expect(provider).to receive(:run_dscl).with("list", "/Users", "uid").and_return("\naj 500\n")
end
it "should return true for a used uid number" do
@@ -198,8 +198,8 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
end
it "finds a valid, unused uid when none is specified" do
- expect(provider).to receive(:run_dscl).with("list /Users uid").and_return("")
- expect(provider).to receive(:run_dscl).with("create /Users/toor UniqueID 501")
+ expect(provider).to receive(:run_dscl).with("list", "/Users", "uid").and_return("")
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "UniqueID", 501)
expect(provider).to receive(:get_free_uid).and_return(501)
provider.dscl_set_uid
expect(new_resource.uid).to eq(501)
@@ -207,8 +207,8 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
it "sets the uid specified in the resource" do
new_resource.uid(1000)
- expect(provider).to receive(:run_dscl).with("create /Users/toor UniqueID 1000").and_return(true)
- expect(provider).to receive(:run_dscl).with("list /Users uid").and_return("")
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "UniqueID", 1000).and_return(true)
+ expect(provider).to receive(:run_dscl).with("list", "/Users", "uid").and_return("")
provider.dscl_set_uid
end
end
@@ -219,9 +219,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
end
before do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- new_resource.supports({ :manage_home => true })
+ new_resource.manage_home true
new_resource.home("/Users/toor")
provider.current_resource = current_resource
@@ -229,7 +227,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
it "deletes the home directory when resource#home is nil" do
new_resource.instance_variable_set(:@home, nil)
- expect(provider).to receive(:run_dscl).with("delete /Users/toor NFSHomeDirectory").and_return(true)
+ expect(provider).to receive(:run_dscl).with("delete", "/Users/toor", "NFSHomeDirectory").and_return(true)
provider.dscl_set_home
end
@@ -239,40 +237,40 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
end
it "moves the users home to the new location if it exists and the target location is different" do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- new_resource.supports(:manage_home => true)
+ new_resource.manage_home true
current_home = CHEF_SPEC_DATA + "/old_home_dir"
current_home_files = [current_home + "/my-dot-emacs", current_home + "/my-dot-vim"]
current_resource.home(current_home)
new_resource.gid(23)
- allow(::File).to receive(:exists?).with("/old/home/toor").and_return(true)
- allow(::File).to receive(:exists?).with("/Users/toor").and_return(true)
+ allow(::File).to receive(:exist?).with("/old/home/toor").and_return(true)
+ allow(::File).to receive(:exist?).with("/Users/toor").and_return(true)
+ allow(::File).to receive(:exist?).with(current_home).and_return(true)
expect(FileUtils).to receive(:mkdir_p).with("/Users/toor").and_return(true)
expect(FileUtils).to receive(:rmdir).with(current_home)
expect(::Dir).to receive(:glob).with("#{CHEF_SPEC_DATA}/old_home_dir/*", ::File::FNM_DOTMATCH).and_return(current_home_files)
- expect(FileUtils).to receive(:mv).with(current_home_files, "/Users/toor", :force => true)
+ expect(FileUtils).to receive(:mv).with(current_home_files, "/Users/toor", force: true)
expect(FileUtils).to receive(:chown_R).with("toor", "23", "/Users/toor")
- expect(provider).to receive(:run_dscl).with("create /Users/toor NFSHomeDirectory '/Users/toor'")
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "NFSHomeDirectory", "/Users/toor")
provider.dscl_set_home
end
it "should raise an exception when the systems user template dir (skel) cannot be found" do
- allow(::File).to receive(:exists?).and_return(false, false, false)
+ allow(::File).to receive(:exist?).and_return(false, false, false)
expect { provider.dscl_set_home }.to raise_error(Chef::Exceptions::User)
end
it "should run ditto to copy any missing files from skel to the new home dir" do
- expect(::File).to receive(:exists?).with("/System/Library/User\ Template/English.lproj").and_return(true)
+ expect(::File).to receive(:exist?).with("/System/Library/User\ Template/English.lproj").and_return(true)
expect(FileUtils).to receive(:chown_R).with("toor", "", "/Users/toor")
- expect(provider).to receive(:shell_out!).with("ditto '/System/Library/User Template/English.lproj' '/Users/toor'")
+ expect(provider).to receive(:shell_out!).with("ditto", "/System/Library/User Template/English.lproj", "/Users/toor")
provider.ditto_home
end
it "creates the user's NFSHomeDirectory and home directory" do
- expect(provider).to receive(:run_dscl).with("create /Users/toor NFSHomeDirectory '/Users/toor'").and_return(true)
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "NFSHomeDirectory", "/Users/toor").and_return(true)
expect(provider).to receive(:ditto_home)
provider.dscl_set_home
end
@@ -283,8 +281,8 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
let(:plutil_exists) { true }
before do
- allow(::File).to receive(:exists?).with("/usr/bin/dscl").and_return(dscl_exists)
- allow(::File).to receive(:exists?).with("/usr/bin/plutil").and_return(plutil_exists)
+ allow(::File).to receive(:exist?).with("/usr/bin/dscl").and_return(dscl_exists)
+ allow(::File).to receive(:exist?).with("/usr/bin/plutil").and_return(plutil_exists)
end
def run_requirements
@@ -382,8 +380,8 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
let(:user_plist_file) { nil }
before do
- expect(provider).to receive(:shell_out).with("dscacheutil '-flushcache'")
- expect(provider).to receive(:shell_out).with("plutil -convert xml1 -o - /var/db/dslocal/nodes/Default/users/toor.plist") do
+ expect(provider).to receive(:shell_out).with("dscacheutil", "-flushcache")
+ expect(provider).to receive(:shell_out).with("plutil", "-convert", "xml1", "-o", "-", "/var/db/dslocal/nodes/Default/users/toor.plist") do
if user_plist_file.nil?
shellcmdresult.new("Can not find the file", "Sorry!!", 1)
else
@@ -391,7 +389,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
end
end
- if !user_plist_file.nil?
+ unless user_plist_file.nil?
expect(provider).to receive(:convert_binary_plist_to_xml).and_return(File.read(File.join(CHEF_SPEC_DATA, "mac_users/#{user_plist_file}.shadow.xml")))
end
end
@@ -726,7 +724,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30")
expect(provider).to receive(:prepare_password_shadow_info).and_return({})
mock_shellout = double("Mock::Shellout")
allow(mock_shellout).to receive(:run_command)
- expect(Mixlib::ShellOut).to receive(:new).and_return(mock_shellout)
+ expect(provider).to receive(:shell_out).and_return(mock_shellout)
expect(provider).to receive(:read_user_info)
expect(provider).to receive(:dscl_set)
expect(provider).to receive(:sleep).with(3)
@@ -754,29 +752,29 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30")
end
it "creates the user and sets the comment field" do
- expect(provider).to receive(:run_dscl).with("create /Users/toor").and_return(true)
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor").and_return(true)
provider.dscl_create_user
end
it "sets the comment field" do
- expect(provider).to receive(:run_dscl).with("create /Users/toor RealName '#mockssuck'").and_return(true)
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "RealName", "#mockssuck").and_return(true)
provider.dscl_create_comment
end
it "sets the comment field to username" do
new_resource.comment nil
- expect(provider).to receive(:run_dscl).with("create /Users/toor RealName '#mockssuck'").and_return(true)
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "RealName", "#mockssuck").and_return(true)
provider.dscl_create_comment
expect(new_resource.comment).to eq("#mockssuck")
end
it "should run run_dscl with create /Users/user PrimaryGroupID to set the users primary group" do
- expect(provider).to receive(:run_dscl).with("create /Users/toor PrimaryGroupID '1001'").and_return(true)
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "PrimaryGroupID", 1001).and_return(true)
provider.dscl_set_gid
end
it "should run run_dscl with create /Users/user UserShell to set the users login shell" do
- expect(provider).to receive(:run_dscl).with("create /Users/toor UserShell '/usr/bin/false'").and_return(true)
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "UserShell", "/usr/bin/false").and_return(true)
provider.dscl_set_shell
end
end
@@ -788,21 +786,21 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30")
end
it "should map the group name to a numeric ID when the group exists" do
- expect(provider).to receive(:run_dscl).with("read /Groups/newgroup PrimaryGroupID").ordered.and_return("PrimaryGroupID: 1001\n")
- expect(provider).to receive(:run_dscl).with("create /Users/toor PrimaryGroupID '1001'").ordered.and_return(true)
+ expect(provider).to receive(:run_dscl).with("read", "/Groups/newgroup", "PrimaryGroupID").ordered.and_return("PrimaryGroupID: 1001\n")
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "PrimaryGroupID", "1001").ordered.and_return(true)
provider.dscl_set_gid
end
it "should raise an exception when the group does not exist" do
shell_return = shellcmdresult.new("<dscl_cmd> DS Error: -14136 (eDSRecordNotFound)", "err", -14136)
- expect(provider).to receive(:shell_out).with("dscl . -read /Groups/newgroup PrimaryGroupID").and_return(shell_return)
+ expect(provider).to receive(:shell_out).with("dscl", ".", "-read", "/Groups/newgroup", "PrimaryGroupID").and_return(shell_return)
expect { provider.dscl_set_gid }.to raise_error(Chef::Exceptions::GroupIDNotFound)
end
end
it "should set group ID to 20 if it's not specified" do
new_resource.gid nil
- expect(provider).to receive(:run_dscl).with("create /Users/toor PrimaryGroupID '20'").ordered.and_return(true)
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "PrimaryGroupID", 20).ordered.and_return(true)
provider.dscl_set_gid
expect(new_resource.gid).to eq(20)
end
@@ -850,8 +848,8 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30")
describe "when the user exists" do
before do
- expect(provider).to receive(:shell_out).with("dscacheutil '-flushcache'")
- expect(provider).to receive(:shell_out).with("plutil -convert xml1 -o - /var/db/dslocal/nodes/Default/users/toor.plist") do
+ expect(provider).to receive(:shell_out).with("dscacheutil", "-flushcache")
+ expect(provider).to receive(:shell_out).with("plutil", "-convert", "xml1", "-o", "-", "/var/db/dslocal/nodes/Default/users/toor.plist") do
shellcmdresult.new(File.read(File.join(CHEF_SPEC_DATA, "mac_users/10.9.plist.xml")), "", 0)
end
provider.load_current_resource
@@ -859,14 +857,13 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30")
describe "when Chef is removing the user" do
it "removes the user from the groups and deletes home directory when the resource is configured to manage home" do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- new_resource.supports({ :manage_home => true })
- expect(provider).to receive(:run_dscl).with("list /Groups").and_return("my_group\nyour_group\nreal_group\n")
- expect(provider).to receive(:run_dscl).with("read /Groups/my_group").and_raise(Chef::Exceptions::DsclCommandFailed) # Empty group
- expect(provider).to receive(:run_dscl).with("read /Groups/your_group").and_return("GroupMembership: not_you")
- expect(provider).to receive(:run_dscl).with("read /Groups/real_group").and_return("GroupMembership: toor")
- expect(provider).to receive(:run_dscl).with("delete /Groups/real_group GroupMembership 'toor'")
- expect(provider).to receive(:run_dscl).with("delete /Users/toor")
+ new_resource.manage_home true
+ expect(provider).to receive(:run_dscl).with("list", "/Groups").and_return("my_group\nyour_group\nreal_group\n")
+ expect(provider).to receive(:run_dscl).with("read", "/Groups/my_group").and_raise(Chef::Exceptions::DsclCommandFailed) # Empty group
+ expect(provider).to receive(:run_dscl).with("read", "/Groups/your_group").and_return("GroupMembership: not_you")
+ expect(provider).to receive(:run_dscl).with("read", "/Groups/real_group").and_return("GroupMembership: toor")
+ expect(provider).to receive(:run_dscl).with("delete", "/Groups/real_group", "GroupMembership", "toor")
+ expect(provider).to receive(:run_dscl).with("delete", "/Users/toor")
expect(FileUtils).to receive(:rm_rf).with("/Users/vagrant")
provider.remove_user
end
@@ -889,7 +886,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30")
end
it "can unlock the user" do
- expect(provider).to receive(:run_dscl).with("create /Users/toor AuthenticationAuthority ';ShadowHash;HASHLIST:<SALTED-SHA512-PBKDF2>'")
+ expect(provider).to receive(:run_dscl).with("create", "/Users/toor", "AuthenticationAuthority", ";ShadowHash;HASHLIST:<SALTED-SHA512-PBKDF2>")
provider.unlock_user
end
end
@@ -897,7 +894,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30")
describe "when locking the user" do
it "should run run_dscl with append /Users/user AuthenticationAuthority ;DisabledUser; to lock the user account" do
- expect(provider).to receive(:run_dscl).with("append /Users/toor AuthenticationAuthority ';DisabledUser;'")
+ expect(provider).to receive(:run_dscl).with("append", "/Users/toor", "AuthenticationAuthority", ";DisabledUser;")
provider.lock_user
end
end
diff --git a/spec/unit/provider/user/linux_spec.rb b/spec/unit/provider/user/linux_spec.rb
index 1c487c0de9..b04ada2511 100644
--- a/spec/unit/provider/user/linux_spec.rb
+++ b/spec/unit/provider/user/linux_spec.rb
@@ -55,7 +55,7 @@ describe Chef::Provider::User::Linux do
# supports is a method on the superclass so can't totally be removed, but we should aggressively NOP it to decisively break it
it "disables the supports API", chef: ">= 13" do
- @new_resource.supports( { manage_home: true } )
+ @new_resource.supports( manage_home: true )
expect( @new_resource.supports.key?(:manage_home) ).to be false
end
@@ -67,10 +67,16 @@ describe Chef::Provider::User::Linux do
expect( @new_resource.supports[:non_unique] ).to be false
end
+ it "throws a deprecation warning on setting supports[:non_unique]" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ expect(Chef).to receive(:deprecated).with(:supports_property, "supports { non_unique: true } on the user resource is deprecated and will be removed in Chef 13, set non_unique true instead")
+ @new_resource.supports( non_unique: true )
+ end
+
it "throws a deprecation warning on setting supports[:manage_home]" do
Chef::Config[:treat_deprecation_warnings_as_errors] = false
- expect(Chef).to receive(:log_deprecation).with("supports { manage_home: true } on the user resource is deprecated and will be removed in Chef 13, set manage_home: true instead")
- @new_resource.supports( { :manage_home => true } )
+ expect(Chef).to receive(:deprecated).with(:supports_property, "supports { manage_home: true } on the user resource is deprecated and will be removed in Chef 13, set manage_home true instead")
+ @new_resource.supports( manage_home: true )
end
it "defaults manage_home to false" do
@@ -79,13 +85,13 @@ describe Chef::Provider::User::Linux do
it "supports[:manage_home] (incorectly) acts like manage_home" do
Chef::Config[:treat_deprecation_warnings_as_errors] = false
- @new_resource.supports({ manage_home: true })
+ @new_resource.supports(manage_home: true)
expect( provider.useradd_options ).to eql(["-m"])
end
it "supports[:manage_home] does not change behavior of manage_home: false", chef: ">= 13" do
Chef::Config[:treat_deprecation_warnings_as_errors] = false
- @new_resource.supports({ manage_home: true })
+ @new_resource.supports(manage_home: true)
expect( provider.useradd_options ).to eql(["-M"])
end
diff --git a/spec/unit/provider/user/pw_spec.rb b/spec/unit/provider/user/pw_spec.rb
index fb7c9211a1..2f44d6f3e3 100644
--- a/spec/unit/provider/user/pw_spec.rb
+++ b/spec/unit/provider/user/pw_spec.rb
@@ -34,7 +34,7 @@ describe Chef::Provider::User::Pw do
# XXX: rip out in Chef-13
Chef::Config[:treat_deprecation_warnings_as_errors] = false
- @new_resource.supports :manage_home => true
+ @new_resource.supports manage_home: true
@current_resource = Chef::Resource::User::PwUser.new("adam")
@current_resource.comment "Adam Jacob"
@@ -65,35 +65,36 @@ describe Chef::Provider::User::Pw do
it "should set the option for #{attribute} if the new resources #{attribute} is not null" do
allow(@new_resource).to receive(attribute).and_return("hola")
- expect(@provider.set_options).to eql(" #{@new_resource.username} #{option} '#{@new_resource.send(attribute)}' -m")
+ expect(@provider.set_options).to eql([ @new_resource.username, option, @new_resource.send(attribute), "-m"])
end
it "should set the option for #{attribute} if the new resources #{attribute} is not null, without homedir management" do
- allow(@new_resource).to receive(:supports).and_return({ :manage_home => false })
+ allow(@new_resource).to receive(:supports).and_return(manage_home: false)
allow(@new_resource).to receive(attribute).and_return("hola")
- expect(@provider.set_options).to eql(" #{@new_resource.username} #{option} '#{@new_resource.send(attribute)}'")
+ expect(@provider.set_options).to eql([@new_resource.username, option, @new_resource.send(attribute)])
end
end
it "should combine all the possible options" do
- match_string = " adam"
+ match_array = [ "adam" ]
field_list.sort { |a, b| a[0] <=> b[0] }.each do |attribute, option|
allow(@new_resource).to receive(attribute).and_return("hola")
- match_string << " #{option} 'hola'"
+ match_array << option
+ match_array << "hola"
end
- match_string << " -m"
- expect(@provider.set_options).to eql(match_string)
+ match_array << "-m"
+ expect(@provider.set_options).to eql(match_array)
end
end
describe "create_user" do
before(:each) do
- allow(@provider).to receive(:run_command).and_return(true)
+ allow(@provider).to receive(:shell_out!).and_return(true)
allow(@provider).to receive(:modify_password).and_return(true)
end
it "should run pw useradd with the return of set_options" do
- expect(@provider).to receive(:run_command).with({ :command => "pw useradd adam -m" }).and_return(true)
+ expect(@provider).to receive(:shell_out!).with("pw", "useradd", "adam", "-m").and_return(true)
@provider.create_user
end
@@ -105,12 +106,12 @@ describe Chef::Provider::User::Pw do
describe "manage_user" do
before(:each) do
- allow(@provider).to receive(:run_command).and_return(true)
+ allow(@provider).to receive(:shell_out!).and_return(true)
allow(@provider).to receive(:modify_password).and_return(true)
end
it "should run pw usermod with the return of set_options" do
- expect(@provider).to receive(:run_command).with({ :command => "pw usermod adam -m" }).and_return(true)
+ expect(@provider).to receive(:shell_out!).with("pw", "usermod", "adam", "-m").and_return(true)
@provider.manage_user
end
@@ -122,13 +123,13 @@ describe Chef::Provider::User::Pw do
describe "remove_user" do
it "should run pw userdel with the new resources user name" do
- @new_resource.supports :manage_home => false
- expect(@provider).to receive(:run_command).with({ :command => "pw userdel #{@new_resource.username}" }).and_return(true)
+ @new_resource.supports manage_home: false
+ expect(@provider).to receive(:shell_out!).with("pw", "userdel", @new_resource.username).and_return(true)
@provider.remove_user
end
it "should run pw userdel with the new resources user name and -r if manage_home is true" do
- expect(@provider).to receive(:run_command).with({ :command => "pw userdel #{@new_resource.username} -r" }).and_return(true)
+ expect(@provider).to receive(:shell_out!).with("pw", "userdel", @new_resource.username, "-r").and_return(true)
@provider.remove_user
end
end
@@ -147,23 +148,26 @@ describe Chef::Provider::User::Pw do
describe "when locking the user" do
it "should run pw lock with the new resources username" do
- expect(@provider).to receive(:run_command).with({ :command => "pw lock #{@new_resource.username}" })
+ expect(@provider).to receive(:shell_out!).with("pw", "lock", @new_resource.username)
@provider.lock_user
end
end
describe "when unlocking the user" do
it "should run pw unlock with the new resources username" do
- expect(@provider).to receive(:run_command).with({ :command => "pw unlock #{@new_resource.username}" })
+ expect(@provider).to receive(:shell_out!).with("pw", "unlock", @new_resource.username)
@provider.unlock_user
end
end
describe "when modifying the password" do
before(:each) do
- @status = double("Status", :exitstatus => 0)
+ @status = double("Status", exitstatus: 0)
allow(@provider).to receive(:popen4).and_return(@status)
- @pid, @stdin, @stdout, @stderr = nil, nil, nil, nil
+ @pid = nil
+ @stdin = nil
+ @stdout = nil
+ @stderr = nil
end
describe "and the new password has not been specified" do
@@ -210,7 +214,7 @@ 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(:popen4).with("pw usermod adam -H 0", waitlast: true).and_return(@status)
@provider.modify_password
end
@@ -239,12 +243,12 @@ describe Chef::Provider::User::Pw do
end
it "should raise an error if the required binary /usr/sbin/pw doesn't exist" do
- expect(File).to receive(:exists?).with("/usr/sbin/pw").and_return(false)
+ expect(File).to receive(:exist?).with("/usr/sbin/pw").and_return(false)
expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::User)
end
it "shouldn't raise an error if /usr/sbin/pw exists" do
- allow(File).to receive(:exists?).and_return(true)
+ allow(File).to receive(:exist?).and_return(true)
expect { @provider.load_current_resource }.not_to raise_error
end
end
diff --git a/spec/unit/provider/user/windows_spec.rb b/spec/unit/provider/user/windows_spec.rb
index 324b5f503f..82f3c1ab2a 100644
--- a/spec/unit/provider/user/windows_spec.rb
+++ b/spec/unit/provider/user/windows_spec.rb
@@ -127,19 +127,19 @@ describe Chef::Provider::User::Windows do
describe "when creating the user" do
it "should call @net_user.add with the return of set_options" do
- allow(@provider).to receive(:set_options).and_return(:name => "monkey")
- expect(@net_user).to receive(:add).with(:name => "monkey")
+ allow(@provider).to receive(:set_options).and_return(name: "monkey")
+ expect(@net_user).to receive(:add).with(name: "monkey")
@provider.create_user
end
end
describe "manage_user" do
before(:each) do
- allow(@provider).to receive(:set_options).and_return(:name => "monkey")
+ allow(@provider).to receive(:set_options).and_return(name: "monkey")
end
it "should call @net_user.update with the return of set_options" do
- expect(@net_user).to receive(:update).with(:name => "monkey")
+ expect(@net_user).to receive(:update).with(name: "monkey")
@provider.manage_user
end
end
diff --git a/spec/unit/provider/user_spec.rb b/spec/unit/provider/user_spec.rb
index 719dc8d492..489597445f 100644
--- a/spec/unit/provider/user_spec.rb
+++ b/spec/unit/provider/user_spec.rb
@@ -58,7 +58,7 @@ describe Chef::Provider::User do
describe "executing load_current_resource" do
before(:each) do
@node = Chef::Node.new
- #@new_resource = double("Chef::Resource::User",
+ # @new_resource = double("Chef::Resource::User",
# :null_object => true,
# :username => "adam",
# :comment => "Adam Jacob",
@@ -68,7 +68,7 @@ describe Chef::Provider::User do
# :shell => "/usr/bin/zsh",
# :password => nil,
# :updated => nil
- #)
+ # )
allow(Chef::Resource::User).to receive(:new).and_return(@current_resource)
@pw_user = EtcPwnamIsh.new
@pw_user.name = "adam"
@@ -110,11 +110,11 @@ describe Chef::Provider::User do
# The mapping between the Chef::Resource::User and Getpwnam struct
user_attrib_map = {
- :uid => :uid,
- :gid => :gid,
- :comment => :gecos,
- :home => :dir,
- :shell => :shell,
+ uid: :uid,
+ gid: :gid,
+ comment: :gecos,
+ home: :dir,
+ shell: :shell,
}
user_attrib_map.each do |user_attrib, getpwnam_attrib|
it "should set the current resources #{user_attrib} based on getpwnam #{getpwnam_attrib}" do
@@ -140,18 +140,16 @@ describe Chef::Provider::User do
describe "and running assertions" do
def self.shadow_lib_unavail?
- begin
- require "rubygems"
- require "shadow"
- rescue LoadError
- skip "ruby-shadow gem not installed for dynamic load test"
- true
- else
- false
- end
+ require "rubygems"
+ require "shadow"
+ rescue LoadError
+ skip "ruby-shadow gem not installed for dynamic load test"
+ true
+ else
+ false
end
- before (:each) do
+ before(:each) do
user = @pw_user.dup
user.name = "root"
user.passwd = "x"
@@ -161,15 +159,15 @@ describe Chef::Provider::User do
unless shadow_lib_unavail?
context "and we have the ruby-shadow gem" do
- skip "and we are not root (rerun this again as root)", :requires_unprivileged_user => true
+ skip "and we are not root (rerun this again as root)", requires_unprivileged_user: true
- context "and we are root", :requires_root => true do
+ context "and we are root", requires_root: true do
it "should pass assertions when ruby-shadow can be loaded" do
@provider.action = "create"
original_method = @provider.method(:require)
expect(@provider).to receive(:require) { |*args| original_method.call(*args) }
- passwd_info = Struct::PasswdEntry.new(:sp_namp => "adm ", :sp_pwdp => "$1$T0N0Q.lc$nyG6pFI3Dpqa5cxUz/57j0", :sp_lstchg => 14861, :sp_min => 0, :sp_max => 99999,
- :sp_warn => 7, :sp_inact => -1, :sp_expire => -1, :sp_flag => -1)
+ passwd_info = Struct::PasswdEntry.new(sp_namp: "adm ", sp_pwdp: "$1$T0N0Q.lc$nyG6pFI3Dpqa5cxUz/57j0", sp_lstchg: 14861, sp_min: 0, sp_max: 99999,
+ sp_warn: 7, sp_inact: -1, sp_expire: -1, sp_flag: -1)
expect(Shadow::Passwd).to receive(:getspnam).with("adam").and_return(passwd_info)
@provider.load_current_resource
@provider.define_resource_requirements
diff --git a/spec/unit/provider_resolver_spec.rb b/spec/unit/provider_resolver_spec.rb
index 5ba5ddae03..ec102209ab 100644
--- a/spec/unit/provider_resolver_spec.rb
+++ b/spec/unit/provider_resolver_spec.rb
@@ -135,6 +135,7 @@ describe Chef::ProviderResolver do
end
else
it "'#{name}' fails to resolve (since #{name.inspect} is unsupported on #{platform} #{platform_version})", *tags do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect(resolved_provider).to be_nil
end
end
diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb
index f42b7563f5..e1e3e0ad72 100644
--- a/spec/unit/recipe_spec.rb
+++ b/spec/unit/recipe_spec.rb
@@ -193,9 +193,41 @@ describe Chef::Recipe do
end
end
+ describe "when resource cloning is disabled" do
+ def not_expect_warning
+ expect(Chef::Log).not_to receive(:warn).with(/3694/)
+ expect(Chef::Log).not_to receive(:warn).with(/Previous/)
+ expect(Chef::Log).not_to receive(:warn).with(/Current/)
+ end
+
+ before do
+ Chef::Config[:resource_cloning] = false
+ end
+
+ it "should emit a 3694 warning when attributes change" do
+ recipe.zen_master "klopp" do
+ something "bvb"
+ end
+ not_expect_warning
+ recipe.zen_master "klopp" do
+ something "vbv"
+ end
+ end
+
+ it "should not copy attributes from a prior resource" do
+ recipe.zen_master "klopp" do
+ something "bvb"
+ end
+ not_expect_warning
+ recipe.zen_master "klopp"
+ expect(run_context.resource_collection.first.something).to eql("bvb")
+ expect(run_context.resource_collection[1].something).to be nil
+ end
+ end
+
describe "when cloning resources" do
def expect_warning
- expect(Chef).to receive(:log_deprecation).with(/^Cloning resource attributes for zen_master\[klopp\]/)
+ expect(Chef).to receive(:deprecated).with(:resource_cloning, /^Cloning resource attributes for zen_master\[klopp\]/)
end
it "should emit a 3694 warning when attributes change" do
@@ -242,7 +274,7 @@ describe Chef::Recipe do
it "should not emit a 3694 warning for completely trivial resource cloning" do
recipe.zen_master "klopp"
- expect(Chef).to_not receive(:log_deprecation)
+ expect(Chef).to_not receive(:deprecated)
recipe.zen_master "klopp"
end
@@ -250,7 +282,7 @@ describe Chef::Recipe do
recipe.zen_master "klopp" do
action :nothing
end
- expect(Chef).to_not receive(:log_deprecation)
+ expect(Chef).to_not receive(:deprecated)
recipe.zen_master "klopp" do
action :score
end
@@ -260,7 +292,7 @@ describe Chef::Recipe do
recipe.zen_master "klopp" do
action :score
end
- expect(Chef).to_not receive(:log_deprecation)
+ expect(Chef).to_not receive(:deprecated)
recipe.zen_master "klopp" do
action :nothing
end
@@ -283,7 +315,7 @@ describe Chef::Recipe do
it "does not emit 3694 when the name_property is unlazied by running it at compile_time" do
recipe.coerced "string"
- expect(Chef).to_not receive(:log_deprecation)
+ expect(Chef).to_not receive(:deprecated)
recipe.coerced "string"
end
@@ -319,7 +351,7 @@ describe Chef::Recipe do
end
it "will insert another resource if create_if_missing is not set (cloned resource as of Chef-12)" do
- expect(Chef).to receive(:log_deprecation).with(/^Cloning resource attributes for zen_master\[klopp\]/)
+ expect(Chef).to receive(:deprecated).with(:resource_cloning, /^Cloning resource attributes for zen_master\[klopp\]/)
zm_resource
recipe.declare_resource(:zen_master, "klopp")
expect(run_context.resource_collection.count).to eql(2)
@@ -442,18 +474,18 @@ describe Chef::Recipe do
end
it "copies attributes from the first resource" do
- expect(Chef).to receive(:log_deprecation).with(/^Cloning resource attributes for zen_master\[klopp\]/)
+ expect(Chef).to receive(:deprecated).with(:resource_cloning, /^Cloning resource attributes for zen_master\[klopp\]/)
expect(duplicated_resource.something).to eq("bvb09")
end
it "does not copy the action from the first resource" do
- expect(Chef).to receive(:log_deprecation).with(/^Cloning resource attributes for zen_master\[klopp\]/)
+ expect(Chef).to receive(:deprecated).with(:resource_cloning, /^Cloning resource attributes for zen_master\[klopp\]/)
expect(original_resource.action).to eq([:score])
expect(duplicated_resource.action).to eq([:nothing])
end
it "does not copy the source location of the first resource" do
- expect(Chef).to receive(:log_deprecation).with(/^Cloning resource attributes for zen_master\[klopp\]/)
+ expect(Chef).to receive(:deprecated).with(:resource_cloning, /^Cloning resource attributes for zen_master\[klopp\]/)
# sanity check source location:
expect(original_resource.source_line).to include(__FILE__)
expect(duplicated_resource.source_line).to include(__FILE__)
@@ -462,12 +494,12 @@ describe Chef::Recipe do
end
it "sets the cookbook name on the cloned resource to that resource's cookbook" do
- expect(Chef).to receive(:log_deprecation).with(/^Cloning resource attributes for zen_master\[klopp\]/)
+ expect(Chef).to receive(:deprecated).with(:resource_cloning, /^Cloning resource attributes for zen_master\[klopp\]/)
expect(duplicated_resource.cookbook_name).to eq("second_cb")
end
it "sets the recipe name on the cloned resource to that resoure's recipe" do
- expect(Chef).to receive(:log_deprecation).with(/^Cloning resource attributes for zen_master\[klopp\]/)
+ expect(Chef).to receive(:deprecated).with(:resource_cloning, /^Cloning resource attributes for zen_master\[klopp\]/)
expect(duplicated_resource.recipe_name).to eq("second_recipe")
end
diff --git a/spec/unit/resource/apt_update_spec.rb b/spec/unit/resource/apt_update_spec.rb
index a7d2c64fee..dd72b18063 100644
--- a/spec/unit/resource/apt_update_spec.rb
+++ b/spec/unit/resource/apt_update_spec.rb
@@ -24,35 +24,27 @@ describe Chef::Resource::AptUpdate do
let(:run_context) { Chef::RunContext.new(node, {}, events) }
let(:resource) { Chef::Resource::AptUpdate.new("update", run_context) }
- context "on linux", :linux_only do
- it "should create a new Chef::Resource::AptUpdate" do
- expect(resource).to be_a_kind_of(Chef::Resource)
- expect(resource).to be_a_kind_of(Chef::Resource::AptUpdate)
- end
-
- it "the default frequency should be 1 day" do
- expect(resource.frequency).to eql(86_400)
- end
+ it "should create a new Chef::Resource::AptUpdate" do
+ expect(resource).to be_a_kind_of(Chef::Resource)
+ expect(resource).to be_a_kind_of(Chef::Resource::AptUpdate)
+ end
- it "the frequency should accept integers" do
- resource.frequency(400)
- expect(resource.frequency).to eql(400)
- end
+ it "the default frequency should be 1 day" do
+ expect(resource.frequency).to eql(86_400)
+ end
- it "should resolve to a Noop class when apt-get is not found" do
- expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(false)
- expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
- end
+ it "the frequency should accept integers" do
+ resource.frequency(400)
+ expect(resource.frequency).to eql(400)
+ end
- it "should resolve to a AptUpdate class when apt-get is found" do
- expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(true)
- expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::AptUpdate)
- end
+ it "should resolve to a Noop class when apt-get is not found" do
+ expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(false)
+ expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
end
- context "on windows", :windows_only do
- it "should resolve to a NoOp provider" do
- expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
- end
+ it "should resolve to a AptUpdate class when apt-get is found" do
+ expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(true)
+ expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::AptUpdate)
end
end
diff --git a/spec/unit/resource/chocolatey_package_spec.rb b/spec/unit/resource/chocolatey_package_spec.rb
index e43803a65f..9b433045c1 100644
--- a/spec/unit/resource/chocolatey_package_spec.rb
+++ b/spec/unit/resource/chocolatey_package_spec.rb
@@ -64,4 +64,16 @@ describe Chef::Resource::ChocolateyPackage do
resource.version(["1.2.3", "4.5.6"])
expect(resource.version).to eql(["1.2.3", "4.5.6"])
end
+
+ it "the default returns should be 0" do
+ expect(resource.returns).to eql([0])
+ end
+
+ # Integer, Array
+ [ 0, [0, 48, 49] ].each do |val|
+ it "supports setting an alternate return value as a #{val.class}" do
+ resource.returns(val)
+ expect(resource.returns).to eql(val)
+ end
+ end
end
diff --git a/spec/unit/resource/dnf_package_spec.rb b/spec/unit/resource/dnf_package_spec.rb
new file mode 100644
index 0000000000..0cc673d897
--- /dev/null
+++ b/spec/unit/resource/dnf_package_spec.rb
@@ -0,0 +1,99 @@
+#
+# Copyright:: Copyright 2016, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+require "support/shared/unit/resource/static_provider_resolution"
+
+describe Chef::Resource::DnfPackage, "initialize" do
+
+ static_provider_resolution(
+ resource: Chef::Resource::DnfPackage,
+ provider: Chef::Provider::Package::Dnf,
+ name: :dnf_package,
+ action: :install,
+ os: "linux",
+ platform_family: "rhel"
+ )
+
+end
+
+describe Chef::Resource::DnfPackage, "arch" do
+ before(:each) do
+ @resource = Chef::Resource::DnfPackage.new("foo")
+ end
+
+ it "should set the arch variable to whatever is passed in" do
+ @resource.arch("i386")
+ expect(@resource.arch).to eql(["i386"])
+ end
+end
+
+describe Chef::Resource::DnfPackage, "flush_cache" do
+ before(:each) do
+ @resource = Chef::Resource::DnfPackage.new("foo")
+ end
+
+ it "should default the flush timing to false" do
+ flush_hash = { :before => false, :after => false }
+ expect(@resource.flush_cache).to eq(flush_hash)
+ end
+
+ it "should allow you to set the flush timing with an array" do
+ flush_array = [ :before, :after ]
+ flush_hash = { :before => true, :after => true }
+ @resource.flush_cache(flush_array)
+ expect(@resource.flush_cache).to eq(flush_hash)
+ end
+
+ it "should allow you to set the flush timing with a hash" do
+ flush_hash = { :before => true, :after => true }
+ @resource.flush_cache(flush_hash)
+ expect(@resource.flush_cache).to eq(flush_hash)
+ end
+
+ it "should allow 'true' for flush_cache" do
+ @resource.flush_cache(true)
+ expect(@resource.flush_cache).to eq({ before: true, after: true })
+ end
+
+ it "should allow 'false' for flush_cache" do
+ @resource.flush_cache(false)
+ expect(@resource.flush_cache).to eq({ before: false, after: false })
+ end
+
+ it "should allow ':before' for flush_cache" do
+ @resource.flush_cache(:before)
+ expect(@resource.flush_cache).to eq({ before: true, after: false })
+ end
+
+ it "should allow ':after' for flush_cache" do
+ @resource.flush_cache(:after)
+ expect(@resource.flush_cache).to eq({ before: false, after: true })
+ end
+end
+
+describe Chef::Resource::DnfPackage, "allow_downgrade" do
+ before(:each) do
+ @resource = Chef::Resource::DnfPackage.new("foo")
+ end
+
+ it "should allow you to specify whether allow_downgrade is true or false" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ expect { @resource.allow_downgrade true }.not_to raise_error
+ expect { @resource.allow_downgrade false }.not_to raise_error
+ end
+end
diff --git a/spec/unit/resource/dsc_resource_spec.rb b/spec/unit/resource/dsc_resource_spec.rb
index b610c262cc..b687811392 100644
--- a/spec/unit/resource/dsc_resource_spec.rb
+++ b/spec/unit/resource/dsc_resource_spec.rb
@@ -18,6 +18,7 @@
require "spec_helper"
describe Chef::Resource::DscResource do
let(:dsc_test_resource_name) { "DSCTest" }
+ let(:dsc_test_resource_module_version) { "2.7.2" }
let(:dsc_test_property_name) { :DSCTestProperty }
let(:dsc_test_property_value) { "DSCTestValue" }
let(:dsc_test_reboot_action) { :reboot_now }
@@ -53,6 +54,11 @@ describe Chef::Resource::DscResource do
expect(dsc_test_resource.module_name).to eq(dsc_test_resource_name)
end
+ it "allows the module_version attribute to be set" do
+ dsc_test_resource.module_version(dsc_test_resource_module_version)
+ expect(dsc_test_resource.module_version).to eq(dsc_test_resource_module_version)
+ end
+
it "allows the reboot_action attribute to be set" do
dsc_test_resource.reboot_action(dsc_test_reboot_action)
expect(dsc_test_resource.reboot_action).to eq(dsc_test_reboot_action)
diff --git a/spec/unit/resource/execute_spec.rb b/spec/unit/resource/execute_spec.rb
index 70824e9f5b..4c0ee694c3 100644
--- a/spec/unit/resource/execute_spec.rb
+++ b/spec/unit/resource/execute_spec.rb
@@ -32,4 +32,218 @@ describe Chef::Resource::Execute do
expect(execute_resource.is_guard_interpreter).to eq(false)
end
+ describe "#qualify_user" do
+ let(:password) { "password" }
+ let(:domain) { nil }
+
+ context "when username is passed as user@domain" do
+ let(:username) { "user@domain" }
+
+ it "correctly parses the user and domain" do
+ identity = execute_resource.qualify_user(username, password, domain)
+ expect(identity[:domain]).to eq("domain")
+ expect(identity[:user]).to eq("user")
+ end
+ end
+
+ context "when username is passed as domain\\user" do
+ let(:username) { "domain\\user" }
+
+ it "correctly parses the user and domain" do
+ identity = execute_resource.qualify_user(username, password, domain)
+ expect(identity[:domain]).to eq("domain")
+ expect(identity[:user]).to eq("user")
+ end
+ end
+ end
+
+ shared_examples_for "it received valid credentials" do
+ describe "the validation method" do
+ it "should not raise an error" do
+ expect { execute_resource.validate_identity_platform(username, password, domain) }.not_to raise_error
+ end
+ end
+
+ describe "the name qualification method" do
+ it "should correctly translate the user and domain" do
+ identity = nil
+ expect { identity = execute_resource.qualify_user(username, password, domain) }.not_to raise_error
+ expect(identity[:domain]).to eq(domain)
+ expect(identity[:user]).to eq(username)
+ end
+ end
+ end
+
+ shared_examples_for "it received invalid credentials" do
+ describe "the validation method" do
+ it "should raise an error" do
+ expect { execute_resource.validate_identity_platform(username, password, domain) }.to raise_error(ArgumentError)
+ end
+ end
+ end
+
+ shared_examples_for "it received invalid username and domain" do
+ describe "the validation method" do
+ it "should raise an error" do
+ expect { execute_resource.qualify_user(username, password, domain) }.to raise_error(ArgumentError)
+ end
+ end
+ end
+
+ shared_examples_for "it received credentials that are not valid on the platform" do
+ describe "the validation method" do
+ it "should raise an error" do
+ expect { execute_resource.validate_identity_platform(username, password, domain) }.to raise_error(Chef::Exceptions::UnsupportedPlatform)
+ end
+ end
+ end
+
+ shared_examples_for "a consumer of the Execute resource" do
+ context "when running on Windows" do
+ before do
+ allow(execute_resource).to receive(:node).and_return({ :platform_family => "windows" })
+ end
+
+ context "when no user, domain, or password is specified" do
+ let(:username) { nil }
+ let(:domain) { nil }
+ let(:password) { nil }
+ it_behaves_like "it received valid credentials"
+ end
+
+ context "when a valid username is specified" do
+ let(:username) { "starchild" }
+ context "when a valid domain is specified" do
+ let(:domain) { "mothership" }
+
+ context "when the password is not specified" do
+ let(:password) { nil }
+ it_behaves_like "it received invalid credentials"
+ end
+
+ context "when the password is specified" do
+ let(:password) { "we.funk!" }
+ it_behaves_like "it received valid credentials"
+ end
+ end
+
+ context "when the domain is not specified" do
+ let(:domain) { nil }
+
+ context "when the password is not specified" do
+ let(:password) { nil }
+ it_behaves_like "it received invalid credentials"
+ end
+
+ context "when the password is specified" do
+ let(:password) { "we.funk!" }
+ it_behaves_like "it received valid credentials"
+ end
+ end
+
+ context "when username is not specified" do
+ let(:username) { nil }
+
+ context "when domain is specified" do
+ let(:domain) { "mothership" }
+ let(:password) { nil }
+ it_behaves_like "it received invalid username and domain"
+ end
+
+ context "when password is specified" do
+ let(:domain) { nil }
+ let(:password) { "we.funk!" }
+ it_behaves_like "it received invalid username and domain"
+ end
+ end
+ end
+
+ context "when invalid username is specified" do
+ let(:username) { "user@domain@domain" }
+ let(:domain) { nil }
+ let(:password) { "we.funk!" }
+ it_behaves_like "it received invalid username and domain"
+ end
+
+ context "when the domain is provided in both username and domain" do
+ let(:domain) { "some_domain" }
+ let(:password) { "we.funk!" }
+
+ context "when username is in the form domain\\user" do
+ let(:username) { "mothership\\starchild" }
+ it_behaves_like "it received invalid username and domain"
+ end
+
+ context "when username is in the form user@domain" do
+ let(:username) { "starchild@mothership" }
+ it_behaves_like "it received invalid username and domain"
+ end
+ end
+ end
+
+ context "when not running on Windows" do
+ before do
+ allow(execute_resource).to receive(:node).and_return({ :platform_family => "ubuntu" })
+ end
+
+ context "when no user, domain, or password is specified" do
+ let(:username) { nil }
+ let(:domain) { nil }
+ let(:password) { nil }
+ it_behaves_like "it received valid credentials"
+ end
+
+ context "when the user is specified and the domain and password are not" do
+ let(:username) { "starchild" }
+ let(:domain) { nil }
+ let(:password) { nil }
+ it_behaves_like "it received valid credentials"
+
+ context "when the password is specified and the domain is not" do
+ let(:password) { "we.funk!" }
+ let(:domain) { nil }
+ it_behaves_like "it received credentials that are not valid on the platform"
+ end
+
+ context "when the domain is specified and the password is not" do
+ let(:domain) { "mothership" }
+ let(:password) { nil }
+ it_behaves_like "it received credentials that are not valid on the platform"
+ end
+
+ context "when the domain and password are specified" do
+ let(:domain) { "mothership" }
+ let(:password) { "we.funk!" }
+ it_behaves_like "it received credentials that are not valid on the platform"
+ end
+ end
+
+ context "when the user is not specified" do
+ let(:username) { nil }
+ context "when the domain is specified" do
+ let(:domain) { "mothership" }
+ context "when the password is specified" do
+ let(:password) { "we.funk!" }
+ it_behaves_like "it received credentials that are not valid on the platform"
+ end
+
+ context "when password is not specified" do
+ let(:password) { nil }
+ it_behaves_like "it received credentials that are not valid on the platform"
+ end
+ end
+
+ context "when the domain is not specified" do
+ let(:domain) { nil }
+ context "when the password is specified" do
+ let(:password) { "we.funk!" }
+ it_behaves_like "it received credentials that are not valid on the platform"
+ end
+ end
+ end
+ end
+ end
+
+ it_behaves_like "a consumer of the Execute resource"
+
end
diff --git a/spec/unit/resource/file/verification/systemd_unit_spec.rb b/spec/unit/resource/file/verification/systemd_unit_spec.rb
new file mode 100644
index 0000000000..8a3d849582
--- /dev/null
+++ b/spec/unit/resource/file/verification/systemd_unit_spec.rb
@@ -0,0 +1,103 @@
+#
+# Author:: Mal Graty (<mal.graty@googlemail.com>)
+# Copyright:: Copyright 2014-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::File::Verification::SystemdUnit do
+ let(:command) { "#{systemd_analyze_path} verify %{path}" }
+ let(:opts) { { :future => true } }
+ let(:parent_resource) { Chef::Resource.new("llama") }
+ let(:systemd_analyze_path) { "/usr/bin/systemd-analyze" }
+ let(:systemd_dir) { "/etc/systemd/system" }
+ let(:temp_path) { "/tmp" }
+ let(:unit_name) { "sysstat-collect.timer" }
+ let(:unit_path) { "#{systemd_dir}/#{unit_name}" }
+ let(:unit_temp_path) { "#{systemd_dir}/.chef-#{unit_name}" }
+ let(:unit_test_path) { "#{temp_path}/#{unit_name}" }
+
+ describe "verification registration" do
+ it "registers itself for later use" do
+ expect(Chef::Resource::File::Verification.lookup(:systemd_unit)).to eq(Chef::Resource::File::Verification::SystemdUnit)
+ end
+ end
+
+ describe "#initialize" do
+ before(:each) do
+ allow_any_instance_of(Chef::Resource::File::Verification::SystemdUnit).to receive(:which)
+ .with("systemd-analyze")
+ .and_return(systemd_analyze_path)
+ end
+
+ it "overwrites the @command variable with the verification command" do
+ v = Chef::Resource::File::Verification::SystemdUnit.new(parent_resource, :systemd_unit, {})
+ expect(v.instance_variable_get(:@command)).to eql(command)
+ end
+ end
+
+ describe "#verify" do
+ context "with the systemd-analyze binary available" do
+ before(:each) do
+ allow_any_instance_of(Chef::Resource::File::Verification::SystemdUnit).to receive(:which)
+ .with("systemd-analyze")
+ .and_return(systemd_analyze_path)
+
+ allow(parent_resource).to receive(:path)
+ .and_return(unit_path)
+ allow(Dir).to receive(:mktmpdir)
+ .with("chef-systemd-unit") { |&b| b.call temp_path }
+ allow(FileUtils).to receive(:cp)
+ .with(unit_temp_path, unit_test_path)
+ end
+
+ it "copies the temp file to secondary location under correct name" do
+ v = Chef::Resource::File::Verification::SystemdUnit.new(parent_resource, :systemd_unit, {})
+
+ expect(FileUtils).to receive(:cp).with(unit_temp_path, unit_test_path)
+ expect(v).to receive(:verify_command).with(unit_test_path, opts)
+
+ v.verify(unit_temp_path, opts)
+ end
+
+ it "returns the value given by #verify_command" do
+ v = Chef::Resource::File::Verification::SystemdUnit.new(parent_resource, :systemd_unit, {})
+
+ expect(v).to receive(:verify_command)
+ .with(unit_test_path, opts)
+ .and_return("foo")
+
+ expect(v.verify(unit_temp_path, opts)).to eql("foo")
+ end
+ end
+
+ context "with the systemd-analyze binary unavailable" do
+ before(:each) do
+ allow_any_instance_of(Chef::Resource::File::Verification::SystemdUnit).to receive(:which)
+ .with("systemd-analyze")
+ .and_return(false)
+ end
+
+ it "skips verification" do
+ v = Chef::Resource::File::Verification::SystemdUnit.new(parent_resource, :systemd_unit, {})
+
+ expect(v).to_not receive(:verify_command)
+
+ expect(v.verify(unit_temp_path)).to eq(true)
+ end
+ end
+ end
+end
diff --git a/spec/unit/resource/file/verification_spec.rb b/spec/unit/resource/file/verification_spec.rb
index bc51eccaef..6416bb3ad8 100644
--- a/spec/unit/resource/file/verification_spec.rb
+++ b/spec/unit/resource/file/verification_spec.rb
@@ -88,7 +88,7 @@ describe Chef::Resource::File::Verification do
end
it "warns about deprecation when \%{file} is used" do
- expect(Chef::Log).to receive(:deprecation).with(/%{file} is deprecated/, /verification_spec\.rb/)
+ expect(Chef).to receive(:deprecated).with(:verify_file, /%{file} is deprecated/)
test_command = platform_specific_verify_command("file")
Chef::Resource::File::Verification.new(parent_resource, test_command, {})
.verify(temp_path)
diff --git a/spec/unit/resource/freebsd_package_spec.rb b/spec/unit/resource/freebsd_package_spec.rb
index 4edc3dbc78..ce4300497e 100644
--- a/spec/unit/resource/freebsd_package_spec.rb
+++ b/spec/unit/resource/freebsd_package_spec.rb
@@ -65,7 +65,7 @@ describe Chef::Resource::FreebsdPackage do
describe "if pkgng enabled" do
it "should be Freebsd::Pkgng" do
pkg_enabled = OpenStruct.new(:stdout => "yes\n")
- allow(@resource).to receive(:shell_out!).with("make -V WITH_PKGNG", :env => nil).and_return(pkg_enabled)
+ allow(@resource).to receive(:shell_out!).with("make", "-V", "WITH_PKGNG", :env => nil).and_return(pkg_enabled)
@resource.after_created
expect(@resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkgng)
end
@@ -74,7 +74,7 @@ describe Chef::Resource::FreebsdPackage do
describe "if freebsd_version is less than 1000017 and pkgng not enabled" do
it "should be Freebsd::Pkg" do
pkg_enabled = OpenStruct.new(:stdout => "\n")
- allow(@resource).to receive(:shell_out!).with("make -V WITH_PKGNG", :env => nil).and_return(pkg_enabled)
+ allow(@resource).to receive(:shell_out!).with("make", "-V", "WITH_PKGNG", :env => nil).and_return(pkg_enabled)
[1000016, 1000000, 901503, 902506, 802511].each do |freebsd_version|
@node.automatic_attrs[:os_version] = freebsd_version
diff --git a/spec/unit/resource/mount_spec.rb b/spec/unit/resource/mount_spec.rb
index 188eaa67d6..832f7644ac 100644
--- a/spec/unit/resource/mount_spec.rb
+++ b/spec/unit/resource/mount_spec.rb
@@ -41,9 +41,10 @@ describe Chef::Resource::Mount do
expect(@resource.action).to eql([:mount])
end
- it "should accept mount, umount and remount as actions" do
+ it "should accept mount, umount, unmount and remount as actions" do
expect { @resource.action :mount }.not_to raise_error
expect { @resource.action :umount }.not_to raise_error
+ expect { @resource.action :unmount }.not_to raise_error
expect { @resource.action :remount }.not_to raise_error
expect { @resource.action :brooklyn }.to raise_error(ArgumentError)
end
diff --git a/spec/unit/resource/msu_package_spec.rb b/spec/unit/resource/msu_package_spec.rb
new file mode 100644
index 0000000000..349a382b31
--- /dev/null
+++ b/spec/unit/resource/msu_package_spec.rb
@@ -0,0 +1,49 @@
+#
+# 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::Resource::MsuPackage do
+ let(:resource) { Chef::Resource::MsuPackage.new("test_pkg") }
+
+ it "creates a new Chef::Resource::MsuPackage" do
+ expect(resource).to be_a_kind_of(Chef::Resource)
+ expect(resource).to be_a_kind_of(Chef::Resource::Package)
+ expect(resource).to be_a_instance_of(Chef::Resource::MsuPackage)
+ end
+
+ it "sets resource name as :msu_package" do
+ expect(resource.resource_name).to eql(:msu_package)
+ end
+
+ it "sets the source as it's name" do
+ expect(resource.source).to eql("test_pkg")
+ end
+
+ it "sets the default action as :install" do
+ expect(resource.action).to eql(:install)
+ end
+
+ it "raises error if invalid action is given" do
+ expect { resource.action "abc" }.to raise_error(Chef::Exceptions::ValidationFailed)
+ end
+
+ it "coerce its name to a package_name" do
+ expect(resource.package_name).to eql("test_pkg")
+ end
+end
diff --git a/spec/unit/resource/ohai_spec.rb b/spec/unit/resource/ohai_spec.rb
index 9669ef193d..cf1748002b 100644
--- a/spec/unit/resource/ohai_spec.rb
+++ b/spec/unit/resource/ohai_spec.rb
@@ -33,7 +33,7 @@ describe Chef::Resource::Ohai do
expect(@resource.resource_name).to eql(:ohai)
end
- it "should have a default action of create" do
+ it "should have a default action of reload" do
expect(@resource.action).to eql([:reload])
end
diff --git a/spec/unit/resource/package_spec.rb b/spec/unit/resource/package_spec.rb
index dbd76d2eba..7ec3c198e4 100644
--- a/spec/unit/resource/package_spec.rb
+++ b/spec/unit/resource/package_spec.rb
@@ -80,6 +80,11 @@ describe Chef::Resource::Package do
it "returns the file path as its identity" do
expect(@resource.identity).to eq("tomcat")
end
+
+ it "takes options as an array" do
+ @resource.options [ "-a", "-l" ]
+ expect(@resource.options).to eq(["-a", "-l" ])
+ end
end
# String, Integer
diff --git a/spec/unit/resource/powershell_package_spec.rb b/spec/unit/resource/powershell_package_spec.rb
new file mode 100644
index 0000000000..ff4aa991a7
--- /dev/null
+++ b/spec/unit/resource/powershell_package_spec.rb
@@ -0,0 +1,68 @@
+#
+# Author:: Dheeraj Dubey(<dheeraj.dubey@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::Resource::PowershellPackage do
+
+ let(:resource) { Chef::Resource::PowershellPackage.new("test_package") }
+
+ it "should create a new Chef::Resource::PowershellPackage" do
+ expect(resource).to be_a_kind_of(Chef::Resource)
+ expect(resource).to be_a_kind_of(Chef::Resource::Package)
+ expect(resource).to be_a_instance_of(Chef::Resource::PowershellPackage)
+ end
+
+ #to check the value of resource.resource_name
+ it "should have a resource name of :python" do
+ expect(resource.resource_name).to eql(:powershell_package)
+ end
+
+ it "should coerce its name to a package_name array" do
+ expect(resource.package_name).to eql(["test_package"])
+ end
+
+ it "the package_name setter should coerce to arrays" do
+ resource.package_name("git")
+ expect(resource.package_name).to eql(["git"])
+ end
+
+ it "the package_name setter should accept arrays" do
+ resource.package_name(%w{git unzip})
+ expect(resource.package_name).to eql(%w{git unzip})
+ end
+
+ it "the name should accept arrays" do
+ resource = Chef::Resource::PowershellPackage.new(%w{git unzip})
+ expect(resource.package_name).to eql(%w{git unzip})
+ end
+
+ it "the default version should be nil" do
+ expect(resource.version).to eql(nil)
+ end
+
+ it "the version setter should coerce to arrays" do
+ resource.version("1.2.3")
+ expect(resource.version).to eql(["1.2.3"])
+ end
+
+ it "the version setter should accept arrays" do
+ resource.version(["1.2.3", "4.5.6"])
+ expect(resource.version).to eql(["1.2.3", "4.5.6"])
+ end
+end
diff --git a/spec/unit/resource/remote_file_spec.rb b/spec/unit/resource/remote_file_spec.rb
index 5fac457ebf..274f98e7f4 100644
--- a/spec/unit/resource/remote_file_spec.rb
+++ b/spec/unit/resource/remote_file_spec.rb
@@ -36,13 +36,13 @@ describe Chef::Resource::RemoteFile do
it "says its provider is RemoteFile when the source is an absolute URI" do
@resource.source("http://www.google.com/robots.txt")
expect(@resource.provider).to eq(Chef::Provider::RemoteFile)
- expect(Chef::Platform.find_provider(:noplatform, "noversion", @resource)).to eq(Chef::Provider::RemoteFile)
+ expect(@resource.provider_for_action(:create)).to be_kind_of(Chef::Provider::RemoteFile)
end
it "says its provider is RemoteFile when the source is a network share" do
@resource.source("\\\\fakey\\fakerton\\fake.txt")
expect(@resource.provider).to eq(Chef::Provider::RemoteFile)
- expect(Chef::Platform.find_provider(:noplatform, "noversion", @resource)).to eq(Chef::Provider::RemoteFile)
+ expect(@resource.provider_for_action(:create)).to be_kind_of(Chef::Provider::RemoteFile)
end
describe "source" do
diff --git a/spec/unit/resource/yum_package_spec.rb b/spec/unit/resource/yum_package_spec.rb
index dd0d3ae928..a1e8417e0e 100644
--- a/spec/unit/resource/yum_package_spec.rb
+++ b/spec/unit/resource/yum_package_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: AJ Christensen (<aj@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");
@@ -32,6 +32,47 @@ describe Chef::Resource::YumPackage, "initialize" do
end
+describe Chef::Resource::YumPackage do
+ before(:each) do
+ @resource = Chef::Resource::YumPackage.new("foo")
+ end
+
+ # this set of tests is somewhat terrible. the yum provider promiscuously writes over
+ # the new_resource.package_named/version/arch properties. until that is fixed properly
+ # we need to coerce and dup those properties into normal arrays. this does not affect
+ # strings because those are not mutated in place and they are not (currently) frozen
+ # in immutable attributes (even though they really, really should be).
+ context "when passed immutable node attribute arrays" do
+ let(:node) { Chef::Node.new }
+
+ before do
+ node.default["foo"] = %w{one two three}
+ end
+
+ it "allows mutation of the package_name array" do
+ @resource.package_name node["foo"]
+ expect(@resource.package_name).not_to be_a_kind_of(Chef::Node::ImmutableArray)
+ expect { @resource.package_name[0] = "four" }.not_to raise_error
+ expect(@resource.package_name).to eql(%w{four two three})
+ end
+
+ it "allows mutation of the version array" do
+ @resource.version node["foo"]
+ expect(@resource.version).not_to be_a_kind_of(Chef::Node::ImmutableArray)
+ expect { @resource.version[0] = "four" }.not_to raise_error
+ expect(@resource.version).to eql(%w{four two three})
+ end
+
+ it "allows mutation of the arch array" do
+ @resource.arch node["foo"]
+ expect(@resource.arch).not_to be_a_kind_of(Chef::Node::ImmutableArray)
+ expect { @resource.arch[0] = "four" }.not_to raise_error
+ expect(@resource.arch).to eql(%w{four two three})
+ end
+
+ end
+end
+
describe Chef::Resource::YumPackage, "arch" do
before(:each) do
@resource = Chef::Resource::YumPackage.new("foo")
@@ -65,6 +106,26 @@ describe Chef::Resource::YumPackage, "flush_cache" do
@resource.flush_cache(flush_hash)
expect(@resource.flush_cache).to eq(flush_hash)
end
+
+ it "should allow 'true' for flush_cache" do
+ @resource.flush_cache(true)
+ expect(@resource.flush_cache).to eq({ before: true, after: true })
+ end
+
+ it "should allow 'false' for flush_cache" do
+ @resource.flush_cache(false)
+ expect(@resource.flush_cache).to eq({ before: false, after: false })
+ end
+
+ it "should allow ':before' for flush_cache" do
+ @resource.flush_cache(:before)
+ expect(@resource.flush_cache).to eq({ before: true, after: false })
+ end
+
+ it "should allow ':after' for flush_cache" do
+ @resource.flush_cache(:after)
+ expect(@resource.flush_cache).to eq({ before: false, after: true })
+ end
end
describe Chef::Resource::YumPackage, "allow_downgrade" do
diff --git a/spec/unit/resource_reporter_spec.rb b/spec/unit/resource_reporter_spec.rb
index 51075a7d44..84cfb52418 100644
--- a/spec/unit/resource_reporter_spec.rb
+++ b/spec/unit/resource_reporter_spec.rb
@@ -92,8 +92,8 @@ describe Chef::ResourceReporter do
context "when chef fails" do
before do
- allow(@rest_client).to receive(:raw_request).and_return({ "result" => "ok" });
- allow(@rest_client).to receive(:post).and_return({ "uri" => "https://example.com/reports/nodes/spitfire/runs/#{@run_id}" });
+ allow(@rest_client).to receive(:raw_request).and_return({ "result" => "ok" })
+ allow(@rest_client).to receive(:post).and_return({ "uri" => "https://example.com/reports/nodes/spitfire/runs/#{@run_id}" })
end
@@ -259,12 +259,36 @@ describe Chef::ResourceReporter do
describe "when generating a report for the server" do
before do
- allow(@rest_client).to receive(:raw_request).and_return({ "result" => "ok" });
- allow(@rest_client).to receive(:post).and_return({ "uri" => "https://example.com/reports/nodes/spitfire/runs/#{@run_id}" });
+ allow(@rest_client).to receive(:raw_request).and_return({ "result" => "ok" })
+ allow(@rest_client).to receive(:post).and_return({ "uri" => "https://example.com/reports/nodes/spitfire/runs/#{@run_id}" })
@resource_reporter.run_started(@run_status)
end
+ context "when the new_resource is sensitive" do
+ before do
+ @execute_resource = Chef::Resource::Execute.new("sensitive-resource")
+ @execute_resource.name("sensitive-resource")
+ @execute_resource.command('echo "password: SECRET"')
+ @execute_resource.sensitive(true)
+ @resource_reporter.resource_action_start(@execute_resource, :run)
+ @resource_reporter.resource_current_state_loaded(@execute_resource, :run, @current_resource)
+ @resource_reporter.resource_updated(@execute_resource, :run)
+ @resource_reporter.resource_completed(@execute_resource)
+ @run_status.stop_clock
+ @report = @resource_reporter.prepare_run_data
+ @first_update_report = @report["resources"].first
+ end
+
+ it "resource_name in prepared_run_data should be the same" do
+ expect(@first_update_report["name"]).to eq("sensitive-resource")
+ end
+
+ it "resource_command in prepared_run_data should be blank" do
+ expect(@first_update_report["after"]).to eq({ :command => "sensitive-resource", :user => nil })
+ end
+ end
+
context "when the new_resource does not have a string for name and identity" do
context "the new_resource name and id are nil" do
before do
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb
index 68fc675b37..2f75ba0241 100644
--- a/spec/unit/resource_spec.rb
+++ b/spec/unit/resource_spec.rb
@@ -354,6 +354,24 @@ describe Chef::Resource do
end
end
+ describe "to_text" do
+ it "prints nice message" do
+ resource_class = Class.new(Chef::Resource) { property :foo, String }
+ resource = resource_class.new("sensitive_property_tests")
+ resource.foo = "some value"
+ expect(resource.to_text).to match(/foo "some value"/)
+ end
+
+ context "when property is sensitive" do
+ it "supresses that properties value" do
+ resource_class = Class.new(Chef::Resource) { property :foo, String, sensitive: true }
+ resource = resource_class.new("sensitive_property_tests")
+ resource.foo = "some value"
+ expect(resource.to_text).to match(/foo "\*sensitive value suppressed\*"/)
+ end
+ end
+ end
+
describe "self.resource_name" do
context "When resource_name is not set" do
it "and there are no provides lines, resource_name is nil" do
@@ -838,6 +856,8 @@ describe Chef::Resource do
it "should run only_if/not_if conditionals when notified to run another action (CHEF-972)" do
snitch_var1 = snitch_var2 = 0
runner = Chef::Runner.new(run_context)
+
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
Chef::Platform.set(
:resource => :cat,
:provider => Chef::Provider::SnakeOil
diff --git a/spec/unit/run_status_spec.rb b/spec/unit/run_status_spec.rb
index 6305b7497b..60717fb3a8 100644
--- a/spec/unit/run_status_spec.rb
+++ b/spec/unit/run_status_spec.rb
@@ -100,7 +100,7 @@ describe Chef::RunStatus do
describe "and some have been updated" do
before do
- @all_resources.first.updated = true
+ @all_resources.first.updated_by_last_action true
end
it "lists the updated resources" do
diff --git a/spec/unit/runner_spec.rb b/spec/unit/runner_spec.rb
index c1e10a78f4..4e7f4d6671 100644
--- a/spec/unit/runner_spec.rb
+++ b/spec/unit/runner_spec.rb
@@ -101,6 +101,7 @@ describe Chef::Runner do
context "when we fall through to old Chef::Platform resolution" do
let(:provider_resolver) { Chef::ProviderResolver.new(node, first_resource, nil) }
before do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
# set up old Chef::Platform resolution instead of provider_resolver
Chef::Platform.set(
:resource => :cat,
diff --git a/spec/unit/server_api_versions_spec.rb b/spec/unit/server_api_versions_spec.rb
new file mode 100644
index 0000000000..43445eb825
--- /dev/null
+++ b/spec/unit/server_api_versions_spec.rb
@@ -0,0 +1,44 @@
+#
+# 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"
+
+describe Chef::ServerAPIVersions do
+ before do
+ Chef::ServerAPIVersions.instance.reset!
+ end
+
+ describe "#min_server_version" do
+ it "returns nil if no versions have been recorded" do
+ expect(Chef::ServerAPIVersions.instance.min_server_version).to be_nil
+ end
+ it "returns the correct value" do
+ Chef::ServerAPIVersions.instance.set_versions({ "min_version" => 0, "max_version" => 2 })
+ expect(Chef::ServerAPIVersions.instance.min_server_version).to eq(0)
+ end
+ end
+
+ describe "#max_server_version" do
+ it "returns nil if no versions have been recorded" do
+ expect(Chef::ServerAPIVersions.instance.max_server_version).to be_nil
+ end
+ it "returns the correct value" do
+ Chef::ServerAPIVersions.instance.set_versions({ "min_version" => 0, "max_version" => 2 })
+ expect(Chef::ServerAPIVersions.instance.max_server_version).to eq(2)
+ end
+ end
+end
diff --git a/spec/unit/util/selinux_spec.rb b/spec/unit/util/selinux_spec.rb
index 609ff02215..751092bc9a 100644
--- a/spec/unit/util/selinux_spec.rb
+++ b/spec/unit/util/selinux_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Serdar Sutay (<serdar@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");
@@ -148,21 +148,10 @@ describe Chef::Util::Selinux do
end
describe "when restorecon doesn't exist on the system" do
- before do
- allow(File).to receive(:executable?) do |file_path|
- expect(file_path.end_with?("restorecon")).to be_truthy
- false
- end
- end
-
it "should log a warning message" do
- log = [ ]
- allow(Chef::Log).to receive(:warn) do |message|
- log << message
- end
-
+ allow(File).to receive(:executable?).with(/restorecon$/).and_return(false)
+ expect(Chef::Log).to receive(:warn).with(/Can not find 'restorecon' on the system. Skipping selinux security context restore./).at_least(:once)
@test_instance.restore_security_context(path)
- expect(log).not_to be_empty
expect(File).not_to receive(:executable?)
@test_instance.restore_security_context(path)
end
diff --git a/spec/unit/win32/error_spec.rb b/spec/unit/win32/error_spec.rb
new file mode 100644
index 0000000000..e8b6d5af6a
--- /dev/null
+++ b/spec/unit/win32/error_spec.rb
@@ -0,0 +1,67 @@
+#
+# Author:: Aliasgar Batterywala (aliasgar.batterywala@msystechnologies.com)
+# 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"
+if Chef::Platform.windows?
+ require "chef/win32/error"
+ require "chef/win32/api/error"
+end
+
+describe "Chef::Win32::Error", :windows_only do
+ describe "self.raise!" do
+ context "code is not passed to the raise! method" do
+ context "last error received is user_not_found" do
+ it "raises UserIDNotFound exception" do
+ expect(Chef::ReservedNames::Win32::Error).to receive(:get_last_error).and_return(
+ Chef::ReservedNames::Win32::API::Error::ERROR_USER_NOT_FOUND
+ )
+ expect(Chef::ReservedNames::Win32::Error).to receive_message_chain(:format_message, :strip)
+ expect { Chef::ReservedNames::Win32::Error.raise! }.to raise_error Chef::Exceptions::UserIDNotFound
+ end
+ end
+
+ context "last error received is not user_not_found" do
+ it "raises Win32APIError exception" do
+ expect(Chef::ReservedNames::Win32::Error).to receive(:get_last_error).and_return(
+ Chef::ReservedNames::Win32::API::Error::ERROR_BAD_USERNAME
+ )
+ expect(Chef::ReservedNames::Win32::Error).to receive_message_chain(:format_message, :strip).and_return("Bad Username")
+ expect { Chef::ReservedNames::Win32::Error.raise! }.to raise_error Chef::Exceptions::Win32APIError
+ end
+ end
+ end
+
+ context "code is passed to the raise! method" do
+ context "last error received is user_not_found" do
+ it "raises UserIDNotFound exception" do
+ expect(Chef::ReservedNames::Win32::Error).to_not receive(:get_last_error)
+ expect(Chef::ReservedNames::Win32::Error).to receive_message_chain(:format_message, :strip)
+ expect { Chef::ReservedNames::Win32::Error.raise! nil, Chef::ReservedNames::Win32::API::Error::ERROR_USER_NOT_FOUND }.to raise_error Chef::Exceptions::UserIDNotFound
+ end
+ end
+
+ context "last error received is not user_not_found" do
+ it "raises Win32APIError exception" do
+ expect(Chef::ReservedNames::Win32::Error).to_not receive(:get_last_error)
+ expect(Chef::ReservedNames::Win32::Error).to receive_message_chain(:format_message, :strip).and_return("Bad Username")
+ expect { Chef::ReservedNames::Win32::Error.raise! nil, Chef::ReservedNames::Win32::API::Error::ERROR_BAD_USERNAME }.to raise_error Chef::Exceptions::Win32APIError
+ end
+ end
+ end
+ end
+end
diff --git a/spec/unit/win32/security_spec.rb b/spec/unit/win32/security_spec.rb
new file mode 100644
index 0000000000..1c755061ce
--- /dev/null
+++ b/spec/unit/win32/security_spec.rb
@@ -0,0 +1,66 @@
+#
+# Author:: Aliasgar Batterywala (aliasgar.batterywala@msystechnologies.com)
+# 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"
+if Chef::Platform.windows?
+ require "chef/win32/error"
+ require "chef/win32/security"
+ require "chef/win32/api/error"
+end
+
+describe "Chef::Win32::Security", :windows_only do
+ describe "self.get_named_security_info" do
+ context "when HR result is ERROR_SUCCESS" do
+ it "does not raise the exception" do
+ expect(Chef::ReservedNames::Win32::Security).to receive(:GetNamedSecurityInfoW).and_return(
+ Chef::ReservedNames::Win32::API::Error::ERROR_SUCCESS
+ )
+ expect { Chef::ReservedNames::Win32::Security.get_named_security_info "/temp_path" }.to_not raise_error
+ end
+ end
+
+ context "when HR result is not ERROR_SUCCESS and not ERROR_USER_NOT_FOUND" do
+ it "raises Win32APIError exception" do
+ expect(Chef::ReservedNames::Win32::Security).to receive(:GetNamedSecurityInfoW).and_return(
+ Chef::ReservedNames::Win32::API::Error::ERROR_INVALID_ACCESS
+ )
+ expect { Chef::ReservedNames::Win32::Security.get_named_security_info "/temp_path" }.to raise_error Chef::Exceptions::Win32APIError
+ end
+ end
+ end
+
+ describe "self.set_named_security_info" do
+ context "when HR result is ERROR_SUCCESS" do
+ it "does not raise the exception" do
+ expect(Chef::ReservedNames::Win32::Security).to receive(:SetNamedSecurityInfoW).and_return(
+ Chef::ReservedNames::Win32::API::Error::ERROR_SUCCESS
+ )
+ expect { Chef::ReservedNames::Win32::Security.set_named_security_info "/temp_path", :SE_FILE_OBJECT, {} }.to_not raise_error
+ end
+ end
+
+ context "when HR result is not ERROR_SUCCESS but it is ERROR_USER_NOT_FOUND" do
+ it "raises UserIDNotFound exception" do
+ expect(Chef::ReservedNames::Win32::Security).to receive(:SetNamedSecurityInfoW).and_return(
+ Chef::ReservedNames::Win32::API::Error::ERROR_USER_NOT_FOUND
+ )
+ expect { Chef::ReservedNames::Win32::Security.set_named_security_info "/temp_path", :SE_FILE_OBJECT, {} }.to raise_error Chef::Exceptions::Chef::Exceptions::UserIDNotFound
+ end
+ end
+ end
+end
diff --git a/tasks/announce.rb b/tasks/announce.rb
new file mode 100644
index 0000000000..0399137eb0
--- /dev/null
+++ b/tasks/announce.rb
@@ -0,0 +1,58 @@
+#
+# Copyright:: Copyright (c) 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 "date"
+require "erb"
+
+class ReleaseAnnouncement
+ include ERB::Util
+ attr_accessor :type, :version, :maj_minor, :date, :release_notes
+
+ def initialize(version, date, type)
+ @version = version
+ @maj_minor = version.split(".")[0..1].join(".")
+ @date = Date.parse(date) unless date.nil?
+ @release_notes = release_notes_from_file
+ @type = type
+ end
+
+ def render
+ puts "-" * 30
+ puts ERB.new(template_for(@type)).result(binding)
+ puts "-" * 30
+ end
+
+ def template_for(type)
+ File.read("tasks/templates/#{type}.md.erb")
+ end
+
+ def release_notes_from_file
+ File.read("RELEASE_NOTES.md").match(/^# Chef Client Release Notes #{@maj_minor}:\n\n(.*)/m)[1]
+ end
+end
+
+namespace :announce do
+ desc "Generate the Prerelease Announcement (version: X.Y.Z, release_date: YYYY-MM-DD)"
+ task :prerelease, :version, :release_date do |t, args|
+ ReleaseAnnouncement.new(args[:version], args[:release_date], "prerelease").render
+ end
+
+ desc "Generate the Release Announcement (version: X.Y.Z)"
+ task :release, :version do |t, args|
+ ReleaseAnnouncement.new(args[:version], nil, "release").render
+ end
+end
diff --git a/tasks/bin/bundle-platform b/tasks/bin/bundle-platform
index aa8443e74c..aaf433c98d 100755
--- a/tasks/bin/bundle-platform
+++ b/tasks/bin/bundle-platform
@@ -6,7 +6,7 @@ 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 } })"
+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("_")
diff --git a/tasks/changelog.rb b/tasks/changelog.rb
index 6dd1ba58ae..8484acde24 100644
--- a/tasks/changelog.rb
+++ b/tasks/changelog.rb
@@ -1,30 +1,33 @@
begin
require "github_changelog_generator/task"
+ require "mixlib/install"
- # Take the current changelog and move it to HISTORY.md. Should be done when
- # cutting a release
- task :archive_changelog do
- changelog = File.readlines("CHANGELOG.md")
- File.open("HISTORY.md", "w+") { |f| f.write(changelog[2..-1].join("")) }
- end
+ namespace :changelog do
+ # Fetch the latest version from mixlib-install
+ latest_stable_version = Mixlib::Install.available_versions("chef", "stable").last
- # Run this to just update the changelog for the current release. This will
- # take what is in History and generate a changelog of PRs between the most
- # recent tag in HISTORY.md and HEAD.
- GitHubChangelogGenerator::RakeTask.new :update_changelog do |config|
- config.future_release = Chef::VERSION
- config.between_tags = ["v#{Chef::VERSION}"]
- config.max_issues = 0
- config.add_issues_wo_labels = false
- config.enhancement_labels = "enhancement,Enhancement,New Feature,Feature".split(",")
- config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(",")
- config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog,Question,Discussion".split(",")
- end
+ # Take the changelog from the latest stable release and put it into history.
+ task :archive do
+ changelog = Net::HTTP.get(URI("https://raw.githubusercontent.com/chef/chef/v#{latest_stable_version}/CHANGELOG.md")).chomp.split("\n")
+ File.open("HISTORY.md", "w+") { |f| f.write(changelog[2..-4].join("\n")) }
+ end
- task :changelog do
- Rake::Task["archive_changelog"].execute
- Rake::Task["update_changelog"].execute
+ # Run this to just update the changelog for the current release. This will
+ # take what is in HISTORY and generate a changelog of PRs between the most
+ # recent stable version and HEAD.
+ GitHubChangelogGenerator::RakeTask.new :update do |config|
+ config.future_release = "v#{Chef::VERSION}"
+ config.between_tags = ["v#{latest_stable_version}", "v#{Chef::VERSION}"]
+ config.max_issues = 0
+ config.add_issues_wo_labels = false
+ config.enhancement_labels = "enhancement,Enhancement,New Feature,Feature".split(",")
+ config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(",")
+ config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog,Question,Discussion,Meta: Exclude From Changelog".split(",")
+ config.header = "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)."
+ end
end
+
+ task :changelog => "changelog:update"
rescue LoadError
puts "github_changelog_generator is not available. gem install github_changelog_generator to generate changelogs"
end
diff --git a/tasks/dependencies.rb b/tasks/dependencies.rb
index 0b216f8e52..b37c351d12 100644
--- a/tasks/dependencies.rb
+++ b/tasks/dependencies.rb
@@ -21,9 +21,23 @@ require_relative "../version_policy"
desc "Tasks to update and check dependencies"
namespace :dependencies do
- # Update all dependencies to the latest constraint-matching version
+
+ # Running update_ci on your local system wont' work. The best way to update
+ # dependencies locally is by running the dependency update script.
desc "Update all dependencies. dependencies:update to update as little as possible."
- task :update => %w{
+ task :update do |t, rake_args|
+ system("#{File.join(Dir.pwd, "ci", "dependency_update.sh")}")
+ end
+
+ desc "Force update (when adding new gems to Gemfiles)"
+ task :force_update do |t, rake_args|
+ FileUtils.rm_f(File.join(Dir.pwd, ".bundle", "config"))
+ system("#{File.join(Dir.pwd, "ci", "dependency_update.sh")}")
+ end
+
+ # Update all dependencies to the latest constraint-matching version
+ desc "Update all dependencies. dependencies:update to update as little as possible (CI-only)."
+ task :update_ci => %w{
dependencies:update_gemfile_lock
dependencies:update_omnibus_overrides
dependencies:update_omnibus_gemfile_lock
@@ -130,6 +144,8 @@ namespace :dependencies do
end
end
end
+
desc "Update all dependencies and check for outdated gems."
-task :dependencies => [ "dependencies:update", "bundle:outdated" ]
-task :update => [ "dependencies:update", "bundle:outdated"]
+task :dependencies_ci => [ "dependencies:update_ci", "bundle:outdated" ]
+task :dependencies => [ "dependencies:update" ]
+task :update => [ "dependencies:update" ]
diff --git a/tasks/gemfile_util.rb b/tasks/gemfile_util.rb
index e21299705a..03a729148a 100644
--- a/tasks/gemfile_util.rb
+++ b/tasks/gemfile_util.rb
@@ -255,8 +255,8 @@ module GemfileUtil
result = {}
gems.each do |name, g|
dep_groups = g[:declared_groups] - [ :only_a_runtime_dependency_of_other_gems ]
- dep_groups = dep_groups & groups if groups
- dep_groups = dep_groups - without_groups if without_groups
+ dep_groups &= groups if groups
+ dep_groups -= without_groups if without_groups
if dep_groups.any?
result[name] ||= g
g[:dependencies].each do |dep|
diff --git a/tasks/templates/prerelease.md.erb b/tasks/templates/prerelease.md.erb
new file mode 100644
index 0000000000..0c5c55cffc
--- /dev/null
+++ b/tasks/templates/prerelease.md.erb
@@ -0,0 +1,26 @@
+Ohai Chefs!
+
+We have selected <%= @version %> as our Chef v<%= @maj_minor %> release candidate which is scheduled for release on <%= @date.strftime('%A %B %-d, %Y') %>.
+
+# Release Highlights
+
+<%= @release_notes %>
+
+Please see the [CHANGELOG](https://github.com/chef/chef/blob/master/CHANGELOG.md) for the complete list of changes.
+
+# Get the Build
+As always, you can download binaries directly from [downloads.chef.io](https://downloads.chef.io/chef/current/<%= @version %>) or by using the new `mixlib-install` command line utility available in ChefDK 0.19.6 or greater.
+
+```shell
+$ mixlib-install download chef -v <%= @version %> -c current
+```
+
+Alternatively, you can install Chef using one of the following command options:
+
+```shell
+# In Shell
+$ curl https://omnitruck.chef.io/install.sh | sudo bash -s -- -P chef -v <%= @version %> -c current
+
+# In Windows Powershell
+. { iwr -useb https://omnitruck.chef.io/install.ps1 } | iex; install -project chef -version <%= @version %> -channel current
+```
diff --git a/tasks/templates/release.md.erb b/tasks/templates/release.md.erb
new file mode 100644
index 0000000000..2c6ff0b7c6
--- /dev/null
+++ b/tasks/templates/release.md.erb
@@ -0,0 +1,26 @@
+Ohai Chefs!
+
+We're happy to announce the release of Chef v<%= @maj_minor %>!
+
+# Release Highlights
+
+<%= @release_notes %>
+
+Please see the [CHANGELOG](https://github.com/chef/chef/blob/master/CHANGELOG.md) for the complete list of changes.
+
+# Get the Build
+As always, you can download binaries directly from [downloads.chef.io](https://downloads.chef.io/chef/<%= @version %>) or by using the new `mixlib-install` command line utility available in ChefDK 0.19.6 or greater.
+
+```shell
+$ mixlib-install download chef -v <%= @version %>
+```
+
+Alternatively, you can install Chef using one of the following command options:
+
+```shell
+# In Shell
+$ curl https://omnitruck.chef.io/install.sh | sudo bash -s -- -P chef -v <%= @version %>
+
+# In Windows Powershell
+. { iwr -useb https://omnitruck.chef.io/install.ps1 } | iex; install -project chef -version <%= @version %>
+```
diff --git a/version_policy.rb b/version_policy.rb
index 5621ea43ff..85c29a760b 100644
--- a/version_policy.rb
+++ b/version_policy.rb
@@ -81,6 +81,11 @@ ACCEPTABLE_OUTDATED_GEMS = [
"slop", # expected to disappear with pry 0.11
"typhoeus", # Until the travis gem updates to 1.0.
"cucumber-core", # Until cucumber 2.0
+ "addressable", # gh (via travis) wants this ~> 2.4.0
+ "rake", # poise limits this to < 12
+ "github_changelog_generator", # we manage this independent of the rubygem
+ "cheffish", # 5.0.0 breaks chef-provisioning
+ "net-ssh-gateway", # chef-provisiong and test-kitchen have ~> 1.2 constraint
]
#